欢迎大家一起学习探讨通信之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()
注:
对以上所述专业知识有修正意见或建议,可随时留言反馈。
谢谢大家支持~!