700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Android9.0Wifi热点开启流程梳理

Android9.0Wifi热点开启流程梳理

时间:2023-12-06 22:07:30

相关推荐

Android9.0Wifi热点开启流程梳理

如果你也是年轻的程序员,关注我一起学习探讨

Android9.0中对热点做了较大改动,将热点很大程度从Wifi中剥离出来了。

下面我们看一下热点是怎么开启的。

首先是在WifiTetherSettings中,调用startTether()函数,可以看到startTether函数中主要是调用了WifiTetherSwitchBarController.java中的startTether()函数。

源码路径:

/9.0.0_r3/xref/packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSettings.java#174

private void startTether() {mRestartWifiApAfterConfigChange = false;mSwitchBarController.startTether();}

然后我们看WifiTetherSwitchBarController里的startTether函数,WifiTetherSwitchBarController是用来控制开关栏切换的,可以看到他调用了ConnectivityManager的startTethering函数。

源码路径:

/9.0.0_r3/xref/packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java#107

void startTether() {mSwitchBar.setEnabled(false);mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));}

然后在这里调用了ConnectivityService的startTethering函数。

源码路径:

/9.0.0_r3/xref/frameworks/base/core/java/android/net/ConnectivityManager.java#2261

public void startTethering(int type, boolean showProvisioningUi,final OnStartTetheringCallback callback, Handler handler) {try {String pkgName = mContext.getOpPackageName();Log.i(TAG, "startTethering caller:" + pkgName);mService.startTethering(type, wrappedCallback, showProvisioningUi, pkgName);} catch (RemoteException e) {Log.e(TAG, "Exception trying to start tethering.", e);wrappedCallback.send(TETHER_ERROR_SERVICE_UNAVAIL, null);}}

在ConnectivityService中,会跳到Tethering.java的startTethering函数。

源码路径:

/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/ConnectivityService.java#3232

public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,String callerPkg) {ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);if (!isTetheringSupported()) {receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null);return;}mTethering.startTethering(type, receiver, showProvisioningUi);}

在Tethering.java中,函数的调用顺序如下:startTethering—>enableTetheringInternal—>setWifiTethering。在setWifiTethering中,调用了WifiManager的startSoftAp函数。

源码路径:

/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/connectivity/Tethering.java#368

368 public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {if (!isTetherProvisioningRequired()) {enableTetheringInternal(type, true, receiver);return;}if (showProvisioningUi) {runUiTetherProvisioningAndEnable(type, receiver);} else {runSilentTetherProvisioningAndEnable(type, receiver);}}

private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) {boolean isProvisioningRequired = enable && isTetherProvisioningRequired();int result;switch (type) {case TETHERING_WIFI:result = setWifiTethering(enable);if (isProvisioningRequired && result == TETHER_ERROR_NO_ERROR) {scheduleProvisioningRechecks(type);}sendTetherResult(receiver, result);break;

private int setWifiTethering(final boolean enable) {int rval = TETHER_ERROR_MASTER_ERROR;final long ident = Binder.clearCallingIdentity();try {synchronized (mPublicSync) {mWifiTetherRequested = enable;final WifiManager mgr = getWifiManager();if ((enable && mgr.startSoftAp(null /* use existing wifi config */)) ||(!enable && mgr.stopSoftAp())) {rval = TETHER_ERROR_NO_ERROR;}}} finally {Binder.restoreCallingIdentity(ident);}return rval;}

在这里调用了WifiServiceImpl.java的startSoftAp函数。

源码路径:

/9.0.0_r3/xref/frameworks/base/wifi/java/android/net/wifi/WifiManager.java#1909

public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) {try {return mService.startSoftAp(wifiConfig);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}

在这里调用了startSoftApInternal函数,然后向WifiController的状态机发送了CMD_SET_AP消息。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java#1004

public boolean startSoftAp(WifiConfiguration wifiConfig) {// NETWORK_STACK is a signature only permission.enforceNetworkStackPermission();mLog.info("startSoftAp uid=%").c(Binder.getCallingUid()).flush();synchronized (mLocalOnlyHotspotRequests) {// If a tethering request comes in while we have LOHS running (or requested), call stop// for softap mode and restart softap with the tethering config.if (!mLocalOnlyHotspotRequests.isEmpty()) {stopSoftApInternal();}return startSoftApInternal(wifiConfig, WifiManager.IFACE_IP_MODE_TETHERED);}}

private boolean startSoftApInternal(WifiConfiguration wifiConfig, int mode) {mLog.trace("startSoftApInternal uid=% mode=%").c(Binder.getCallingUid()).c(mode).flush();// null wifiConfig is a meaningful input for CMD_SET_APif (wifiConfig == null || WifiApConfigStore.validateApWifiConfiguration(wifiConfig)) {SoftApModeConfiguration softApConfig = new SoftApModeConfiguration(mode, wifiConfig);mWifiController.sendMessage(CMD_SET_AP, 1, 0, softApConfig);return true;}Slog.e(TAG, "Invalid WifiConfiguration");return false;}

在这里,处理结果是调用WifiStateMachinePrime的enterSoftAPMode方法。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiController.java#593

class DefaultState extends State {case CMD_SET_AP:// note: CMD_SET_AP is handled/dropped in ECM mode - will not start here// first make sure we aren't in airplane modeif (mSettingsStore.isAirplaneModeOn()) {log("drop softap requests when in airplane mode");break;}if (msg.arg1 == 1) {SoftApModeConfiguration config = (SoftApModeConfiguration) msg.obj;mWifiStateMachinePrime.enterSoftAPMode((SoftApModeConfiguration) msg.obj);} else {mWifiStateMachinePrime.stopSoftAPMode();}break;

在WifiStateMachinePrime中,创建了SoftApManager对象,并且调用了start方法。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachinePrime.java#549

public void enterSoftAPMode(@NonNull SoftApModeConfiguration wifiConfig) {mHandler.post(() -> {startSoftAp(wifiConfig);});}

private void startSoftAp(SoftApModeConfiguration softapConfig) {Log.d(TAG, "Starting SoftApModeManager");WifiConfiguration config = softapConfig.getWifiConfiguration();if (config != null && config.SSID != null) {Log.d(TAG, "Passing config to SoftApManager! " + config);} else {config = null;}SoftApCallbackImpl callback = new SoftApCallbackImpl();ActiveModeManager manager = mWifiInjector.makeSoftApManager(callback, softapConfig);callback.setActiveModeManager(manager);manager.start();mActiveModeManagers.add(manager);updateBatteryStatsWifiState(true);}

在这里,StateMachine发送了消息CMD_START,然后由IdleState 处理,这里主要的处理结果就是调用startSoftAp方法。在startSoftAp里,调用了WifiNative.java的startSoftAp方法。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/SoftApManager.java#142

public void start() {mStateMachine.sendMessage(SoftApStateMachine.CMD_START, mApConfig);}

private class IdleState extends State {public boolean processMessage(Message message) {switch (message.what) {case CMD_START:mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode(mWifiNativeInterfaceCallback);if (TextUtils.isEmpty(mApInterfaceName)) {Log.e(TAG, "setup failure when creating ap interface.");updateApState(WifiManager.WIFI_AP_STATE_FAILED,WifiManager.WIFI_AP_STATE_DISABLED,WifiManager.SAP_START_FAILURE_GENERAL);mWifiMetrics.incrementSoftApStartResult(false, WifiManager.SAP_START_FAILURE_GENERAL);break;}updateApState(WifiManager.WIFI_AP_STATE_ENABLING,WifiManager.WIFI_AP_STATE_DISABLED, 0);int result = startSoftAp((WifiConfiguration) message.obj);if (result != SUCCESS) {int failureReason = WifiManager.SAP_START_FAILURE_GENERAL;if (result == ERROR_NO_CHANNEL) {failureReason = WifiManager.SAP_START_FAILURE_NO_CHANNEL;}updateApState(WifiManager.WIFI_AP_STATE_FAILED,WifiManager.WIFI_AP_STATE_ENABLING,failureReason);stopSoftAp();mWifiMetrics.incrementSoftApStartResult(false, failureReason);break;}transitionTo(mStartedState);break;

private int startSoftAp(WifiConfiguration config) {if (config == null || config.SSID == null) {Log.e(TAG, "Unable to start soft AP without valid configuration");return ERROR_GENERIC;}// Make a copy of configuration for updating AP band and channel.WifiConfiguration localConfig = new WifiConfiguration(config);int result = ApConfigUtil.updateApChannelConfig(mWifiNative, mCountryCode,mWifiApConfigStore.getAllowed2GChannel(), localConfig);if (result != SUCCESS) {Log.e(TAG, "Failed to update AP band and channel");return result;}// Setup country code if it is provided.if (mCountryCode != null) {// Country code is mandatory for 5GHz band, return an error if failed to set// country code when AP is configured for 5GHz band.if (!mWifiNative.setCountryCodeHal(mApInterfaceName, mCountryCode.toUpperCase(Locale.ROOT))&& config.apBand == WifiConfiguration.AP_BAND_5GHZ) {Log.e(TAG, "Failed to set country code, required for setting up "+ "soft ap in 5GHz");return ERROR_GENERIC;}}if (localConfig.hiddenSSID) {Log.d(TAG, "SoftAP is a hidden network");}if (!mWifiNative.startSoftAp(mApInterfaceName, localConfig, mSoftApListener)) {Log.e(TAG, "Soft AP start failed");return ERROR_GENERIC;}Log.d(TAG, "Soft AP is started");return SUCCESS;}

在这里,主要是调用WificondControl.java的startHostapd方法。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java#1250

public boolean startSoftAp(@NonNull String ifaceName, WifiConfiguration config, SoftApListener listener) {if (!mWificondControl.startHostapd(ifaceName, listener)) {Log.e(TAG, "Failed to start hostapd");mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();return false;}if (!waitForHostapdConnection()) {Log.e(TAG, "Failed to establish connection to hostapd");mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();return false;}if (!mHostapdHal.registerDeathHandler(new HostapdDeathHandlerInternal())) {Log.e(TAG, "Failed to register hostapd death handler");mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();return false;}if (!mHostapdHal.addAccessPoint(ifaceName, config)) {Log.e(TAG, "Failed to add acccess point");mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();return false;}return true;}

在这里可以看到创建了IApInterface 对象,然后调用了他的startHostapd方法。而IApInterface 是由ap_interface_impl.cpp实现的。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WificondControl.java#787

public boolean startHostapd(@NonNull String ifaceName,SoftApListener listener) {IApInterface iface = getApInterface(ifaceName);if (iface == null) {Log.e(TAG, "No valid ap interface handler");return false;}try {IApInterfaceEventCallback callback = new ApInterfaceEventCallback(listener);mApInterfaceListeners.put(ifaceName, callback);boolean success = iface.startHostapd(callback);if (!success) {Log.e(TAG, "Failed to start hostapd.");return false;}} catch (RemoteException e) {Log.e(TAG, "Exception in starting soft AP: " + e);return false;}return true;}

在这里又调用了hostapd_manager的StartHostapd函数。

源码路径:

/9.0.0_r3/xref/system/connectivity/wificond/ap_interface_impl.cpp#86

bool ApInterfaceImpl::StartHostapd() {return hostapd_manager_->StartHostapd();}

然后在hostapd_manager.cpp里调用了StartHostapd方法。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/libwifi_system/hostapd_manager.cpp#26

bool HostapdManager::StartHostapd() {if (property_set("ctl.start", kHostapdServiceName) != 0) {LOG(ERROR) << "Failed to start SoftAP";return false;LOG(DEBUG) << "SoftAP started successfully";return true;}

再往后就是底层C的代码了,不是特别看得懂。然后返回success的话,热点就成功打开了,状态也变为started。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。