Android 11 WiFi启动流程

       欢迎大家一起学习探讨通信之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.java

public 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打开WiFi

if (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.java

public 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支持的feature

iface.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.java

public 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.cpp

Return<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.cpp

bool 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.cpp

int 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.java

public boolean setupInterfaceForClientMode(@NonNull String ifaceName,

@NonNull @CallbackExecutor Executor executor,

@NonNull ScanEventCallback scanCallback, @NonNull ScanEventCallback pnoScanCallback) {

... ... ... ...

// Refresh Handlers

mClientInterfaces.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.java

public ClientModeImpl(.......){

super(TAG, looper);

... ... .... ....

// CHECKSTYLE:OFF IndentationCheck

addState(mDefaultState);

addState(mConnectModeState, mDefaultState);

addState(mL2ConnectedState, mConnectModeState);

addState(mObtainingIpState, mL2ConnectedState);

addState(mConnectedState, mL2ConnectedState);

addState(mRoamingState, mL2ConnectedState);

addState(mDisconnectingState, mConnectModeState);

addState(mDisconnectedState, mConnectModeState);

// CHECKSTYLE:ON IndentationCheck



setInitialState(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 now

transitionTo(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.cpp

android/system/libhidl/transport/ServiceManagement.cpp

android/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);

//状态转到DisconnectedState

transitionTo(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”微信公众号。

谢谢大家支持~!

 

 

 

 

 

  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值