欢迎大家一起学习探讨通信之WLAN。本节重点基于Android11分析讨论WiFi开启流程。用户点击一下“WiFi”开关,WiFi开启了。看似如此简单操作,但系统流程调用还是相当复杂。因Android11版本框架中WiFi打开流程有一部分变化。接下来我们一起分析下Android 11 WiFi的打开流程是怎么样的呢?

【1】系统启动时,system_server进程中会启动Wifiservice服务,启动该服务在SystemServer.java文件。

private static final String WIFI_SERVICE_CLASS ="com.android.server.wifi.WifiService";if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {// Wifi Service must be started first for wifi-related services.mSystemServiceManager.startService(WIFI_SERVICE_CLASS); mSystemServiceManager.startService("com.android.server.wifi.scanner.WifiScanningService");}

该方法在启动Wifiservice服务时将会被调用到,作用是将服务注册到ServiceManager中。

protected final void publishBinderService(String name, IBinder service,boolean allowIsolated, int dumpPriority) {ServiceManager.addService(name, service, allowIsolated, dumpPriority);}

【2】在Wifiservice启动时,创建WifiServiceImpl实例对象,并将WiFiserviceimpl对象注册到servicemanager中。

这个对象很重要,它是整个系统WiFi服务的管理者,所有的用户端操作请求都将由它初步预处理,然后分发给不同的服务处理执行。

android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiService.javapublic WifiService(Context contextBase) {super(contextBase);mWifiContext = new WifiContext(contextBase);WifiInjector injector = new WifiInjector(mWifiContext);WifiAsyncChannel channel = new WifiAsyncChannel(TAG);mImpl = new WifiServiceImpl(mWifiContext, injector, channel);}public void onStart() {Log.i(TAG, "Registering " + Context.WIFI_SERVICE);publishBinderService(Context.WIFI_SERVICE, mImpl);}

【3】好,接下来到了WifiServiceImpl初始化过程,首先,看下该类的构造函数。

public WifiServiceImpl(Context context, WifiInjector wifiInjector, AsyncChannel asyncChannel) {mContext = context;mWifiInjector = wifiInjector;... ... ... ...mClientModeImpl = mWifiInjector.getClientModeImpl();mActiveModeWarden = mWifiInjector.getActiveModeWarden();... ... ... ...}

看到WiFiserviceimpl构造函数,基本上做了与WiFi服务管理的相关类的初始化动作。下面简单看下Android11 相对Android9 新增加与Wifi打开相关的几个初始化类:

  • ClientModeImpl 作为客户端的模式实现,作为客户端事件处理在这里完成,并所有的连接状态变化在这里初始化。
  • ActiveModeWarden 提供WiFi不同操作模式的配置实现。

到这里,系统启动完成,WifiService服务已正常运行,接下来分析用户“打开WiFi”这个简单的操作,Android11 系统背后的运行流程。

【4】用户点击WiFi开关按钮打开WiFi,通过Android提供的WiFiManager的接口类,通过AIDL机制将事件传递至WifiSerivce管理服务,在WifiServiceImpl对象中对其处理。

public synchronized boolean setWifiEnabled(String packageName, boolean enable) {//权限检查boolean isPrivileged = isPrivileged(Binder.getCallingPid(), Binder.getCallingUid());//检查飞行模式是否打开,同时只运行授权的app打开WiFiif (mSettingsStore.isAirplaneModeOn() && !isPrivileged) {mLog.err("setWifiEnabled in Airplane mode: only Settings can toggle wifi").flush();return false;}//检查调用客户端是否拥有NETWORK_SETTINGS权限,如有在将事件数据记录。if (mWifiPermissionsUtil.checkNetworkSettingsPermission(Binder.getCallingUid())) {mWifiMetrics.logUserActionEvent(enable ? UserActionEvent.EVENT_TOGGLE_WIFI_ON: UserActionEvent.EVENT_TOGGLE_WIFI_OFF);}//记录WiFi切换状态。mWifiMetrics.incrementNumWifiToggles(isPrivileged, enable);//触发WiFi打开动作。mActiveModeWarden.wifiToggled();}private boolean isPrivileged(int pid, int uid) {return checkNetworkSettingsPermission(pid, uid)|| checkNetworkSetupWizardPermission(pid, uid)|| checkNetworkStackPermission(pid, uid)|| checkNetworkManagedProvisioningPermission(pid, uid);}

【5】接下来将进入“ActiveModeWarden”类中。先看 WifiService服务调用的方法“mActiveModeWarden.wifiToggled()”。

android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/ActiveModeWarden.java在wifiToggled方法中,发送消息“WifiController.CMD_WIFI_TOGGLED”。public void wifiToggled() {mWifiController.sendMessage(WifiController.CMD_WIFI_TOGGLED);}

WifiController是ActiveModeWarden的内部类,继承StateMachine类,在ActiveModeWarden构造函数中对其进行初始化;

WifiService服务启动后,在WifiServiceImpl中,调用mActiveModeWarden.start()对其启动。WifiController状态机状态有三个如下:

状态机启动时,根据WiFi开启状态进行状态机初始化。因WiFi是由关闭切换至打开,因此,状态机初始到“mDisabledState”状态。

public void start() {if (shouldEnableSta()) {startClientModeManager();setInitialState(mEnabledState);} else {setInitialState(mDisabledState);}}private boolean shouldEnableSta() {return mSettingsStore.isWifiToggleEnabled() || checkScanOnlyModeAvailable();}

WifiController接收到CMD_WIFI_TOGGLED消息,将在“mDisabledState”状态进行处理,

public boolean processMessageFiltered(Message msg) {... ... ... ...case CMD_WIFI_TOGGLED:case CMD_SCAN_ALWAYS_MODE_CHANGED:if (shouldEnableSta()) {startClientModeManager();transitionTo(mEnabledState);}break;... ... ... ...

这里调用startClientModeManager()方法,启动一个客户端管理对象。

private boolean startClientModeManager() {//ClientListener为ActiveModeWarden的内部监听类。ClientListener listener = new ClientListener();//获取客户端管理对象,并设置监听。ClientModeManager manager = mWifiInjector.makeClientModeManager(listener);listener.setActiveModeManager(manager);manager.start();//切换客户端模式if (!switchClientModeManagerRole(manager)) {return false;}mActiveModeManagers.add(manager);return true;}

【6】好!到这里我们跳到ClientModeManager类中。在其构造函数中,实例化了ClientModeStateMachine内部类对象mStateMachine 。start方法中,触发设置Station模式“ROLE_CLIENT_SCAN_ONLY”,并发送

ClientModeStateMachine.CMD_START消息。

ClientModeManager(Context context, @NonNull Looper looper, Clock clock, WifiNative wifiNative,Listener listener, WifiMetrics wifiMetrics, SarManager sarManager,WakeupController wakeupController, ClientModeImpl clientModeImpl) {... ... ... ...mStateMachine = new ClientModeStateMachine(looper);mDeferStopHandler = new DeferStopHandler(TAG, looper);... ... ... ...}public void start() {mTargetRole = ROLE_CLIENT_SCAN_ONLY;mStateMachine.sendMessage(ClientModeStateMachine.CMD_START);}

ClientModeStateMachine类的状态机状态如下,并初始到“mIdleState”状态和启动状态机。

ClientModeStateMachine(Looper looper) {super(TAG, looper);addState(mIdleState);addState(mStartedState);addState(mScanOnlyModeState, mStartedState);addState(mConnectModeState, mStartedState);setInitialState(mIdleState);start();}

接下来在startClientModeManager()调用方法switchClientModeManagerRole(manager)切换客户端设置模式角色。

private boolean switchClientModeManagerRole(@NonNull ClientModeManager modeManager) {if (mSettingsStore.isWifiToggleEnabled()) {//打开WiFi将设置角色为“ROLE_CLIENT_PRIMARY”;modeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY);} else if (checkScanOnlyModeAvailable()) {modeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY);}... ... ... ...}

在setRole()方法中,将role设置的值保存在mTargetRole变量,并发送消息给ClientModeStateMachine状态机。

public void setRole(@Role int role) {if (role == ROLE_CLIENT_SCAN_ONLY) {mTargetRole = role;mStateMachine.sendMessage(ClientModeStateMachine.CMD_SWITCH_TO_SCAN_ONLY_MODE)} else if (CLIENT_CONNECTIVITY_ROLES.contains(role)) {mTargetRole = role;// Switch client mode manager to connect mode mStateMachine.sendMessage(ClientModeStateMachine.CMD_SWITCH_TO_CONNECT_MODE, role);}}

程序执行到此,ActiveModeWarden类中WiFicontroller状态机在DisabledState状态处理完了“CMD_WIFI_TOGGLED”这个消息,状态机将跳转至“EnabledState”。通过状态机机制可知,将会执行DisabledState.exit()方法退出DisabledState状态;执行EnabledState.enter()方法进入到EnabledState状态。WiFicontroller状态机在WiFi打开中将停留在该状态。

【7】从上流程可知,“ClientModeStateMachine.CMD_START”和“ClientModeStateMachine.CMD_SWITCH_TO_CONNECT_MODE”两条消息还处于待处理状态。

在ClientModeStateMachine类构造函数可知,状态机初始状态为“IdleState”,此时,将执行IdleState.enter()方法进入该状态,并开始处理CMD_START消息。

private class IdleState extends State {... ... ... ...case CMD_START:// Always start in scan mode first.mClientInterfaceName =mWifiNative.setupInterfaceForClientInScanMode(mWifiNativeInterfaceCallback);if (TextUtils.isEmpty(mClientInterfaceName)) {Log.e(TAG, "Failed to create ClientInterface. Sit in Idle");mModeListener.onStartFailure();break;}transitionTo(mScanOnlyModeState);break;... ... ... ...

在处理CMD_START消息时,将调用WifiNative类中setupInterfaceForClientInScanMode()方法。

【8】好!先看WifiNative类中该方法的实现。

android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.javapublic String setupInterfaceForClientInScanMode(@NonNull InterfaceCallback interfaceCallback) {synchronized (mLock) {//startwifi 加载WiFi驱动if (!startHal()) {Log.e(TAG, "Failed to start Hal");mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();return null;}//分配对应的接口Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA_FOR_SCAN);if (iface == null) {Log.e(TAG, "Failed to allocate new STA iface");return null;}iface.externalListener = interfaceCallback;//创建对应的station接口iface.name = createStaIface(iface);if (TextUtils.isEmpty(iface.name)) {Log.e(TAG, "Failed to create iface in vendor HAL");mIfaceMgr.removeIface(iface.id);mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();return null;}//设置客户端接口if (!mWifiCondManager.setupInterfaceForClientMode(iface.name, Runnable::run,new NormalScanEventCallback(iface.name),new PnoScanEventCallback(iface.name))) {Log.e(TAG, "Failed to setup iface in wificond=" + iface.name);teardownInterface(iface.name);mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();return null;}//设置接口up/down的检测通知iface.networkObserver = new NetworkObserverInternal(iface.id);if (!registerNetworkObserver(iface.networkObserver)) {Log.e(TAG, "Failed to register network observer for iface=" + iface.name);teardownInterface(iface.name);return null;}//启动wpa_supplicant事件监听mWifiMonitor.startMonitoring(iface.name);onInterfaceStateChanged(iface, isInterfaceUp(iface.name));//获取WiFi支持的featureiface.featureSet = getSupportedFeatureSetInternal(iface.name);return iface.name;}}

(1)startHal方法内部调用

startHal()->startHal()->WifiVendorHal.startVendorHal()->HalDeviceManager.start()->HalDeviceManager.startWifi()

这里看下启动WiFi的方法“HalDeviceManager.startWifi()”。在这个方法中,将加载WiFi驱动。

private boolean startWifi() {... ... ... ...synchronized (mLock) {try {if (mWifi == null) {return false;} else {int triedCount = 0;//加载WiFi驱动将尝试4次,START_HAL_RETRY_TIMES=3。while (triedCount <= START_HAL_RETRY_TIMES) {WifiStatus status = mWifi.start();if (status.code == WifiStatusCode.SUCCESS) {initIWifiChipDebugListeners();managerStatusListenerDispatch();if (triedCount != 0) {}return true;} else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {try {Thread.sleep(START_HAL_RETRY_INTERVAL_MS);} catch (InterruptedException ignore) {// no-op}triedCount++;} else {// Should not retry on other failures.Log.e(TAG, "Cannot start IWifi: " + statusString(status));return false;}}... ... ... ...

在该方法startWifi,mWifi.start()方法是启动实际加载WiFi动作的调用,这里涉及HIDL机制调用。通过获取IWifi接口对象,调用其方法。这里IWifi接口对象是IWifi.hal文件中实现。

android/hardware/interfaces/wifi/1.0/IWifi.hal

在编译时,编译器会将IWifi.hal解析为IWifi.java文件,直接看该文件中的start方法实现即可。

android/out/soong//.intermediates/hardware/interfaces/wifi/1.0/android.hardware.wifi-V1.0-java_gen_java/gen/srcs/android/hardware/wifi/V1_0/IWifi.javapublic android.hardware.wifi.V1_0.WifiStatus start() throws android.os.RemoteException {try {... ... ... ...mRemote.transact(3 /* start */, _hidl_request, _hidl_reply, 0 /* flags */);_hidl_reply.verifySuccess();_hidl_request.releaseTemporaryStorage();return _hidl_out_status;} finally {_hidl_reply.release();}}

通过binder调用,将调用到wifi.cpp中的start()方法.

android/hardware/interfaces/wifi/1.4/default/wifi.cppReturn<void> Wifi::start(start_cb hidl_status_cb) {return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,&Wifi::startInternal, hidl_status_cb);}wifi.cpp->start() ==> wifi.cpp->startInternal() ==> wifi.cpp->initializeModeControllerAndLegacyHal()==> WifiModeController->initialize() ==> DriverTool->LoadDriver()

通过调用DriverTool->LoadDriver将返回到Android framework中。下面是LoadDriver()的实现。

android/frameworks/opt/net/wifi/libwifi_hal/include/wifi_hal/driver_tool.cppbool DriverTool::LoadDriver() {return ::wifi_load_driver() == 0;}

在wifi_load_driver()方法中,将调用系统接口加载WiFi驱动ko。关于系统insmod接口的调用,本文不做分析。到这里,已梳理完在WifiNative类中调用的startHal()方法。

android/frameworks/opt/net/wifi/libwifi_hal/wifi_hal_common.cppint wifi_load_driver() {... ... ... ...insmod(file,args);... ... ... ...}

(2)调用WifiNl80211Manager类的setupInterfaceForClientMode()方法。

该类的主要对WiFi 80211nl管理接口的封装,接口在WiFicond守护进程中呈现给WiFi框架。该类提供的接口仅使用与WiFi框架,访问权限受selinux权限保护。

setupInterfaceForClientMode()方法主要为Station模式设置接口。

android/frameworks/base/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.javapublic boolean setupInterfaceForClientMode(@NonNull String ifaceName,@NonNull @CallbackExecutor Executor executor,@NonNull ScanEventCallback scanCallback, @NonNull ScanEventCallback pnoScanCallback) {... ... ... ...// Refresh HandlersmClientInterfaces.put(ifaceName, clientInterface);try {IWifiScannerImpl wificondScanner = clientInterface.getWifiScannerImpl();mWificondScanners.put(ifaceName, wificondScanner);Binder.allowBlocking(wificondScanner.asBinder());ScanEventHandler scanEventHandler = new ScanEventHandler(executor, scanCallback);mScanEventHandlers.put(ifaceName, scanEventHandler);wificondScanner.subscribeScanEvents(scanEventHandler);PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(executor,pnoScanCallback);mPnoScanEventHandlers.put(ifaceName, pnoScanEventHandler);wificondScanner.subscribePnoScanEvents(pnoScanEventHandler);... ... ... ...}

到这里,ClientModeStateMachine状态机在IdleState状态成功处理完了CMD_START消息。状态机将转到“mScanOnlyModeState”状态,将会执行以下调用流程(具体原因可查看状态机机制)。

IdleState.exit()->StartedState.enter()->StartedState.exit()->ScanOnlyModeState.enter()。

在状态转时,在StartedState.exit()中,将调用setOperationalMode方法。

public void exit() {mClientModeImpl.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);}

【9】这里将触及开篇提到的ClientModeImpl类。首先看下其构造函数,除了其他对象赋值初始化外,又一个状态机将与我们见面。

android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeImpl.javapublic ClientModeImpl(.......){super(TAG, looper);... ... .... ....// CHECKSTYLE:OFF IndentationCheckaddState(mDefaultState);addState(mConnectModeState, mDefaultState);addState(mL2ConnectedState, mConnectModeState);addState(mObtainingIpState, mL2ConnectedState);addState(mConnectedState, mL2ConnectedState);addState(mRoamingState, mL2ConnectedState);addState(mDisconnectingState, mConnectModeState);addState(mDisconnectedState, mConnectModeState);// CHECKSTYLE:ON IndentationChecksetInitialState(mDefaultState);... ... .... ....}public void setOperationalMode(int mode, String ifaceName) {... ... ...//打开WiFi mode=2,因此状态机进入到mDefaultState状态if (mode != CONNECT_MODE) {// we are disabling client mode... need to exit connect mode nowtransitionTo(mDefaultState);} else {... ... ... ...}}

【10】目前,还遗留一个消息“ClientModeStateMachine.CMD_SWITCH_TO_CONNECT_MODE”待处理。此时,轮到该消息要被处理了。

ClientModeStateMachine状态机已处于“ScanOnlyModeState”状态,接收到该消息后,在processMessage方法中并未处理,而抛给父状态“StartedState”处理。在StartedState.processMessage()方法中对该消息进行了处理。

public boolean processMessage(Message message) {... ... ... ...case CMD_SWITCH_TO_CONNECT_MODE:mRole = message.arg1; // could be any one of possible connect mode roles.//更新WiFi打开状态,发送系统广播通知。updateConnectModeState(WifiManager.WIFI_STATE_ENABLING,WifiManager.WIFI_STATE_DISABLED);//切换设置clinent接口到连接模式。if (!mWifiNative.switchClientInterfaceToConnectivityMode(mClientInterfaceName)) {... ... ... ...mModeListener.onStartFailure();break;}... ... ... ...transitionTo(mConnectModeState);break;}

(1)WifiNative类中,mWifiNative.switchClientInterfaceToConnectivityMode()方法

public boolean switchClientInterfaceToConnectivityMode(@NonNull String ifaceName) {synchronized (mLock) {... ... ... ...//获取设置的接口final Iface iface = mIfaceMgr.getIface(ifaceName);if (iface == null) {return false;}if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY) {return true;}//调用启动wpa_supplicant服务进程if (!startSupplicant()) {teardownInterface(iface.name);mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();return false;}//注册设置接口if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {return false;}iface.type = Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY;iface.featureSet = getSupportedFeatureSetInternal(iface.name);... ... ... ...return true;}}
WifiNative.startSupplicant()->WifiNative.startAndWaitForSupplicantConnection()->
SupplicantStaIfaceHal.startDaemon()->SupplicantStaIfaceHal.startDaemon_V1_1()->
SupplicantStaIfaceHal.getSupplicantMockableV1_1()->
SupplicantStaIfaceHal.getSupplicantMockable()

这里看下getSupplicantMockable()方法,将在getService的时候启动wpa_supplicant进程。

通过HIDL调用获取wpa_supplicant服务。ISupplicant.getService(supplicantName)调用到ISupplicant.java。

protected ISupplicant getSupplicantMockable() throws RemoteException, NoSuchElementException {synchronized (mLock) {ISupplicant iSupplicant = ISupplicant.getService(supplicantName);if (iSupplicant == null) {throw new NoSuchElementException("Cannot get root service.");}return iSupplicant;}}
android/out/soong/intermediates/hardware/interfaces/wifi/supplicant/1.0/android.hardware.wifi.supplicant-V1.0-java_gen_java/gen/srcs/android/hardware/wifi/supplicant/V1_0/ISupplicant.java
public static ISupplicant getService(String serviceName) throws android.os.RemoteException {return ISupplicant.asInterface(android.os.HwBinder.getService("android.hardware.wifi.supplicant@1.0::ISupplicant", serviceName));}

在这个方法中将触发启动wpa_supplicant进程,这里需要注意,在manifest.xml中对其需要进行配置,运行时会将服务名称注册到hwservicemanager中。

wpa_supplicant目录下文件调用:

main.c ==> wpa_supplicant.c->wpa_supplicant_init() ==> notify.c->wpas_notify_supplicant_initialized() ==> hidl.cpp->wpas_hidl_init() ==> Hidl_manager.cpp->registerHidlService()
int HidlManager::registerHidlService(struct wpa_global *global){// Create the main hidl service object and register it.supplicant_object_ = new Supplicant(global);if (supplicant_object_->registerAsService("wpa_supplicant") != android::NO_ERROR) {return 1;}return 0;}

【11】将wpa_supplicant添加注册到hwservicemanager,SupplicantStaIfaceHal.getSupplicantMockable()执行完成返回。

这里再深入看下“supplicant_object_->registerAsService("wpa_supplicant")”是如何通过调用注册的呢?

android/out/soong/.intermediates/hardware/interfaces/wifi/supplicant/1.3/android.hardware.wifi.supplicant@1.3_genc++/gen/android/hardware/wifi/supplicant/1.3/SupplicantAll.cppandroid/system/libhidl/transport/ServiceManagement.cppandroid/system/hwservicemanager/ServiceManager.cpp
supplicant_object_->registerAsService("wpa_supplicant") ==> ISupplicant.hal
==> ISupplicantAll.cpp->registerAsService()
==> ::android::hardware::details::registerAsServiceInternal(this, serviceName)
==> ServiceManagement.cpp->registerAsServiceInternal()
==> ServiceManager->addWithChain()==> ServiceManager->addImpl()

【12】wpa_supplicant注册完成后,SupplicantStaIfaceHal类中将收到回调通知信息,

private final IServiceNotification mServiceNotificationCallback =new IServiceNotification.Stub() {public void onRegistration(String fqName, String name, boolean preexisting) {synchronized (mLock) {if (!initSupplicantService()) {supplicantServiceDiedHandler(mDeathRecipientCookie);} else {}}}};

返回通知的调用逻辑。

SupplicantStaIfaceHal.initSupplicantService() -> SupplicantStaIfaceHal.getSupplicantMockable()

经过一系列调用,wpa_supplicant进程服务已启动完成。现回到WifiNative类中switchClientInterfaceToConnectivityMode()方法。

在该方法中,wpa_supplicant启动完成后,将调用SupplicantStaIfaceHal.setupIface()方法设置接口。

设置成功将执行完WifiNative.switchClientInterfaceToConnectivityMode()方法并退出。

[关键log打印]:WifiNative: Successfully switched to connectivity mode on iface=Iface:{Name=wlan0,Id=1,Type=STA_CONNECTIVITY}

【13】ClientModeManager类中,状态机ClientModeStateMachine在StartedState状态成功处理完“CMD_SWITCH_TO_CONNECT_MODE”消息。状态将转到“mConnectModeState”,

调用mConnectModeState.enter()方法。

public void enter() {//设置客户端模式为连接模式mClientModeImpl.setOperationalMode(ClientModeImpl.CONNECT_MODE,mClientInterfaceName);mModeListener.onStarted();//发送系统广播,通知WiFi已打开。updateConnectModeState(WifiManager.WIFI_STATE_ENABLED,WifiManager.WIFI_STATE_ENABLING);//通知SAR管理着WiFi已打开mSarManager.setClientWifiState(WifiManager.WIFI_STATE_ENABLED);}

ClientModeImpl.setOperationalMode方法实现如下,设置模式为CONNECT_MODE。因此将走else流程。ClientModeImpl类中状态机将由DefaultState转到“DisconnectedState”状态。

状态机转到DisconnectedState状态,执行流程如下:

ConnectModeState.() ->disconnectedstate.enter()
public void setOperationalMode(int mode, String ifaceName) {mModeChange = true;if (mode != CONNECT_MODE) {transitionTo(mDefaultState);} else {if (ifaceName != null) {mInterfaceName = ifaceName;//更新设置是否支持80211ax。updateInterfaceCapabilities(ifaceName);//状态转到DisconnectedStatetransitionTo(mDisconnectedState);mWifiScoreReport.setInterfaceName(ifaceName);} else {transitionTo(mDefaultState);}}sendMessageAtFrontOfQueue(CMD_SET_OPERATIONAL_MODE);}

【14】在此过程中,ActiveModeWarden类中设置的ClientLister将被触发回调。 wifiScaner.setScanningEnabled()发送消息CMD_ENABLE,给到WiFiscanningSerivceimpl类中。

系统调用到这里,WiFi已处于打开状态,并将进行扫描网络,待连接。WiFi打开流程分析完成。

ActiveModeWarden.ClientListener -> ScanRequestProxy.enableScanning() ->
ScanRequestProxy.enableScanningInternal() -> wifiScaner.setScanningEnabled()

注:

对以上所述专业知识有修正意见或建议,可随时留言反馈。如感兴趣更多通信知识,可关注“通信之WLAN”微信公众号。

谢谢大家支持~!

Android 11 WiFi启动流程相关推荐

  1. (四十四)Android O WiFi启动流程梳理

    前言:最近又重新拿起来WiFi模块,从WiFi 各个流程梳理开始复习一下. 参考博客:https://blog.csdn.net/csdn_of_coder/article/details/51541 ...

  2. Android 11 WiFi开启流程

    从刚接触WiFi时跟过wifi的开启流程,当时还是android9.到了Android11代码架构有了不小的改动,在这里重新梳理一遍,便于在工作中更快速的跟踪代码. 一.Settings里改动不大,还 ...

  3. Android 11 WiFi扫描流程梳理

    上一篇我们梳理了WiFi的开启流程,Android11 WiFi开启流程,在最后我们说到ActiveModeWarden中注册了ClientListener监听器.我们接着这个逻辑继续梳理一下打开Wi ...

  4. 【Android 12.0】Android S WiFi启动业务流程分析(UML图)

    以下两张为Android S的WiFi启动(start)业务流程UML图,业务流程的过程详情因公司规定不可复制源码出来,所以想看业务流程详情的同学可以参考其他博主所发的博客.业务流程参考内容链接我会放 ...

  5. Android -- Wifi启动流程分析

    Android -- Wifi启动流程分析 Android网络各个模式中,Wifi应该是目前最常用的一种网络方式了:下面就简单介绍下Android中Wifi的启动流程. 当我在Setting菜单里点击 ...

  6. c++builder启动了怎么停止_App 竟然是这样跑起来的 —— Android App/Activity 启动流程分析...

    在我的上一篇文章: AJie:按下电源键后竟然发生了这一幕 -- Android 系统启动流程分析​zhuanlan.zhihu.com 我们分析了系统在开机以后的一系列行为,其中最后一阶段 AMS( ...

  7. 结合源码探讨Android系统的启动流程

    结合源码探讨Android系统的启动流程 由于本人能力有限,所考虑或者疏忽错漏的地方或多或少应该存在.同时,Android从启动过程开始,实际上就涉及多个技术难点和多种通信机制的知识点. 基于上面两个 ...

  8. Android Q 开机启动流程

    https://www.it610.com/article/1304931662924124160.htm Android Q 开机启动流程 开机启动概述: step 1: 上电开机 长按power键 ...

  9. Android平台WIFI启动流程之二

    http://blog.sina.com.cn/s/blog_13146f9590101wji1.html [摘要] 本文从用户界面出发,从应用层到硬件适配层,对Android平台wifi启动和关闭的 ...

最新文章

  1. Go 语言官网全新改版
  2. Objective-C 执行外部命令
  3. (1) freemarker入门实例
  4. SVN工作笔记002---svn提示上次操作有误,请执行cleanup
  5. spring作用域单例和global_面试必备 | 69道Spring面试题
  6. 机器学习(Andrew Ng)作业代码(Exercise 1~2)
  7. 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(九)第一个程序背后的C语言知识
  8. 胜为蓝牙适配器驱动_udc 324b蓝牙驱动下载|
  9. jenkins+Warnings Next Generation Plugin构建代码自动化检测
  10. Shape-Aware Meta-Learning 在模型泛化中引入形状约束
  11. 基于Android P版本PKMS详解二
  12. 西门子PLC1200学习之比较指令
  13. 基于机智云物联网平台的实验室智能安防报警系统
  14. [Django]MVT模式的详解
  15. 利用Linux主机创建NFS服务
  16. Win11系统怎么开启平板模式
  17. Jmeter中Python中文乱码
  18. UI(十)模拟服务器配置
  19. html制作windows桌面,用html5 canvas制作Windows7桌面图片
  20. 解决Picasa网络相册打不开

热门文章

  1. GDB调试指南(入门,看这篇够了)
  2. 3700万人在线见证梅西“圆梦”!火山引擎实力护航世界杯
  3. 简历:突出意向惹人爱
  4. html中设置背景图像填充,CSS-定位背景图像,添加填充
  5. Power up 键设计
  6. [unity3d][通过代码]改变材质球颜色,动态改变材质球颜色,动态改变模型颜色
  7. SQL中waitfor delay语句
  8. 进程互斥_PV操作原理和例题
  9. 全栈UI设计各类软件教程
  10. unity3d 凹凸贴图、法线贴图、置换贴图 (二)