Android P相比于Android O的变化
- 多了WifiStateMachinePrime(状态机的前处理机制),wifiService的相关cmd 不再是直接send 给WifiStateMachine,而是被送到WifiStateMachinePrime先进行处理后,再送往WifiStateMachine
- 也多了一层ClientModeManager处理(将之前初始化wpa_supplicant专门抽出一层类在这里面来做),详细看后面的代码
Wifi 整体流程框架图
- 基本与Android O Wifi 主体框架一致
- 三板斧的套路还是被传承下来(1. Application <–> 2. WiFiService(WifiStateMachine) <–> 3. WifiNative(wpa_supplicant – wlan drv))
代码流程
1. WifiSettings --> WifiManager
点击 wifi button 开启wifi 触发的代码流程如下,
- wifiSettings 响应onPreferenceTreeClick 送往WifiEnable
- WifiEnabler 根据传入的状态,call WifiManager 设置wifi状态 (开启跳转到WifiServiceImpl)
packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java
public boolean onPreferenceTreeClick(Preference preference){
.....
return super.onPreferenceTreeClick(preference);
}
packages/apps/Settings/src/com/android/settings/wifi/WifiEnabler.java
public boolean onSwitchToggled(boolean isChecked){
....
mWifiManager.setWifiEnabled(isChecked); // wifiManager 设置wifi 状态
}
2. WifiManager --> WifiService --> WifiServiceImpl -->WifiController
- 还是老套路,逐级进入WifiService,WifiServiceImpl ,WifiController,WifiStateMachinePrime,WifiNative 等完成CMD_WIFI_TOGGLED的火炬传递
- 注意随着Android 版本升级后,接递火炬CMD_WIFI_TOGGLED的顺序也发生了变化
- Android P 版本WifiServiceImpl 将CMD_WIFI_TOGGLED 先送到了WifiController处理,这里稍微有点儿复杂的状态机(都会涉及到处理此cmd),具体根据设备所处状态来跟就可以。(这里以设备从开机状态第一次打开wifi为场景进行说明,此case 直接会进入)
frameworks/base/wifi/java/android/net/wifi/WifiManager.java
public boolean setWifiEnabled(boolean enabled){
return mService.setWifiEnabled(mContext.getOpPackageName(), enabled); // jump to WifiServiceImpl
}
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
public synchronized boolean setWifiEnabled(String packageName, boolean enable){
....
mWifiController.sendMessage(CMD_WIFI_TOGGLED);
}
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiController.java
class StaDisabledState extends State {
....
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
.....
transitionTo(mDeviceActiveState); // jump to DeviceActiveState
}
}
class DeviceActiveState extends State {
public void enter() {
mWifiStateMachinePrime.enterClientMode(); // jump to WifiStateMachinePrime
mWifiStateMachine.setHighPerfModeEnabled(false);
}
}
3. WifiController --> WifiStateMachinePrime
- WifiStateMachinePrime 传递CMD_START_CLIENT_MODE,先在内部状态机完成一轮转动
- ModeStateMachine --> ClientModeActiveState
- 送往ClientModeManager 创建WifiClientModeManager 实例
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachinePrime.java
public void enterClientMode() {
changeMode(ModeStateMachine.CMD_START_CLIENT_MODE);
}
private class ModeStateMachine extends StateMachine {
...
private boolean checkForAndHandleModeChange(Message message) {
case ModeStateMachine.CMD_START_CLIENT_MODE:
mModeStateMachine.transitionTo(mClientModeActiveState); //跳转到ClientModeActiveState
}
}
class ClientModeActiveState extends ModeActiveState {
public void enter() {
mManager = mWifiInjector.makeClientModeManager(mListener); //创建ClientModeManager实例
mManager.start(); //
mActiveModeManagers.add(mManager);
updateBatteryStatsWifiState(true);
}
}
4. WifiStateMachinePrime --> ClientModeManager
- ClientModeManager 传递ClientModeStateMachine.CMD_START 开始wpa_supplicant初始化信号
- 更新 wifiState updateWifiState
- 通过WifiNative初始化Client Mode
frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeManager.java
public void start() {
mStateMachine.sendMessage(ClientModeStateMachine.CMD_START);
}
private class IdleState extends State {
public boolean processMessage(Message message) {
case CMD_START:
updateWifiState(WifiManager.WIFI_STATE_ENABLING,
WifiManager.WIFI_STATE_DISABLED);
mClientInterfaceName = mWifiNative.setupInterfaceForClientMode(
false /* not low priority */, mWifiNativeInterfaceCallback);
if (TextUtils.isEmpty(mClientInterfaceName)) {
Log.e(TAG, "Failed to create ClientInterface. Sit in Idle");
updateWifiState(WifiManager.WIFI_STATE_UNKNOWN,
WifiManager.WIFI_STATE_ENABLING);
updateWifiState(WifiManager.WIFI_STATE_DISABLED,
WifiManager.WIFI_STATE_UNKNOWN);
break;
}
sendScanAvailableBroadcast(false); //send wifi Scan Available Broadcast
mScanRequestProxy.enableScanningForHiddenNetworks(false);
mScanRequestProxy.clearScanResults();
transitionTo(mStartedState);
}
}
5. ClientModeManager --> WifiNative
- ClientModeManager 通过CMD_START 将启动传递给WifiNative
- WifiNative 启动wpa_supplicant service
- wifiNative 通过SupplicantStaHal 建立与 wpa_supplicant/hidl/1.1 的sta_iface.cpp 关联(ifaceName)
- wifiNative 向NetworkManagementService 注册NetworkObserverInternal 实例,用于监视 设备iface一举一动
- wifiNative 开启wifiMonitor , 其开始接手所有的事项(消息以及事件),一有变化就上报framework(wifiStateMachine、wifiServiceImpl、SupplicantStaIfaceHal等等),就像是东厂的小兵,监视着下面的一举一动,一有变化马上上报头头
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
public String setupInterfaceForClientMode(boolean lowPrioritySta, @NonNull InterfaceCallback interfaceCallback) {
...
startSupplicant(); // 启动 wpa_supplicant
..
mWificondControl.setupInterfaceForClientMode(iface.name); // 初始化与wificondcontrol 关联(用于后续wificond 作为framework与 wpa_supplicant 之间的通信信使
..
mSupplicantStaIfaceHal.setupIface(iface.name); //
mWifiMonitor.startMonitoring(iface.name); // 启动WifiMonitor 上报所有的wpa_supplicant msg&event
initializeNwParamsForClientInterface(iface.name);
}
6. WifiNative–> WificondControl
- WificondControl 通过 binder 连接到wificond (server.cpp),创建ClientInterface
- WificondControl 通过binder 连接到 client_interface_binder.cpp 获取 wificondScaner ,用于wifi scan(上报scan results)
- WificondControl 创建 pnoScan + Scan Event Handler , 且将之与设备 ifaceName 关联
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WificondControl.java
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WificondControl.java
public IClientInterface setupInterfaceForClientMode(@NonNull String ifaceName){
...
clientInterface = mWificond.createClientInterface(ifaceName); //创建ClientInterface
..
mClientInterfaces.put(ifaceName, clientInterface);
IWifiScannerImpl wificondScanner = clientInterface.getWifiScannerImpl(); // 获取WifiScannerImpl
PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(ifaceName);
mPnoScanEventHandlers.put(ifaceName, pnoScanEventHandler);
wificondScanner.subscribePnoScanEvents(pnoScanEventHandler);
}