Android(安卓)O WiFi启动流程
版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/huangweiqing80/article/details/82384518
一. Android O wifi 架构:
由于Android O的Treble化,Android O上Wifi架构变动也比较大,尤其是JNI层、Hal层、HIDL层。
下图是Android O Treble HIDL大致结构:
下图是Android O wifi架构:
二.WiFi启动流程梳理
2.1 设置启动WiFi
设置这边说到底其实就是监控WiFi开关的变化,然后根据开关走对应的逻辑处理。
两个比较重要的类:
1)WifiSettings:设置中wifi主界面所对应的代码
2)WifiEnabler:设置中负责wifi开关打开和关闭事件处理的类
在wifisettings activity的onStart函数中,创建一个WifiEnabler对象,用于实现wifi开关功能。
packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java
public void onStart() { super.onStart(); // On/off switch is hidden for Setup Wizard (returns null) mWifiEnabler = createWifiEnabler(); mWifiTracker.startTracking(); if (mIsRestricted) { restrictUi(); return; } onWifiStateChanged(mWifiManager.getWifiState()); }
onStart函数调用createWifiEnabler:
/** * @return new WifiEnabler or null (as overridden by WifiSettingsForSetupWizard) */ private WifiEnabler createWifiEnabler() { final SettingsActivity activity = (SettingsActivity) getActivity(); return new WifiEnabler(activity, new SwitchBarController(activity.getSwitchBar()), mMetricsFeatureProvider); }
下面进入
/aosp/packages/apps/Settings/src/com/android/settings/widget/SwitchBarController.java
看看SwitchBarController这个类
public class SwitchBarController extends SwitchWidgetController implements SwitchBar.OnSwitchChangeListener { private final SwitchBar mSwitchBar; public SwitchBarController(SwitchBar switchBar) { mSwitchBar = switchBar; } . . . @Override public void startListening() { mSwitchBar.addOnSwitchChangeListener(this); } . . . @Override public void onSwitchChanged(Switch switchView, boolean isChecked) { if (mListener != null) { mListener.onSwitchToggled(isChecked); } } . . .}
上面的两个函数startListening和onSwitchChanged是重点,一个是启动SwitchBar的监听,一个监听到有变化之后的调用
然后我们再回到刚才的createWifiEnabler函数调用的WifiEnabler类
/aosp/packages/apps/Settings/src/com/android/settings/wifi/WifiEnabler.java
@VisibleForTesting WifiEnabler(Context context, SwitchWidgetController switchWidget, MetricsFeatureProvider metricsFeatureProvider, ConnectivityManagerWrapper connectivityManagerWrapper) { mContext = context; mSwitchWidget = switchWidget; mSwitchWidget.setListener(this); mMetricsFeatureProvider = metricsFeatureProvider; mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); mConnectivityManager = connectivityManagerWrapper; mIntentFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION); // The order matters! We really should not depend on this. :( mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); setupSwitchController(); }
WifiEnabler类我们重点看setupSwitchController这个函数
public void setupSwitchController() { final int state = mWifiManager.getWifiState(); handleWifiStateChanged(state); if (!mListeningToOnSwitchChange) { mSwitchWidget.startListening(); mListeningToOnSwitchChange = true; } mSwitchWidget.setupView(); }
在setupSwitchController函数中,我们看到有
if (!mListeningToOnSwitchChange) {
mSwitchWidget.startListening();
mListeningToOnSwitchChange = true;
}
这里是调用前面的启动监听将mListeningToOnSwitchChange设为true,这样当我们点击wifi开关按钮的时候就会调用前面的onSwitchChanged随即调用mListener.onSwitchToggled(isChecked);
下面再来看看onSwitchToggled这个函数
public boolean onSwitchToggled(boolean isChecked) { //Do nothing if called as a result of a state machine event if (mStateMachineEvent) { return true; } // Show toast message if Wi-Fi is not allowed in airplane mode if (isChecked && !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_WIFI)) { Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show(); // Reset switch to off. No infinite check/listenenr loop. mSwitchWidget.setChecked(false); return false; } // Disable tethering if enabling Wifi if (mayDisableTethering(isChecked)) { mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI); } if (isChecked) { mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_WIFI_ON); } else { // Log if user was connected at the time of switching off. mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_WIFI_OFF, mConnected.get()); } if (!mWifiManager.setWifiEnabled(isChecked)) { // Error mSwitchWidget.setEnabled(true); Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show(); } return true; }
我们可以看到WifiEnabler开关SwitchToggled中会调用WifiManager.setWifiEnabled方法。
看到这里其实发现应用层打开和关闭WiFi就是调用了WifiManager的setWifiEabled(boolean)接口。
2.2 WiFi framework
看下WifiManager的setWifiEabled(boolean)接口
framework/base/wifi/java/android/net/wifi/WifiManager.javapublic boolean setWifiEnabled(boolean enabled) { try { return mService.setWifiEnabled(mContext.getOpPackageName(), enabled); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
应用层的WifiManager都是怎么来的呢
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
2.2.1 mService是什么
而WifiManager.setWifiEnabled函数中的mService是啥呢
IWifiManager mService;
public WifiManager(Context context, IWifiManager service, Looper looper) { mContext = context; mService = service; mLooper = looper; mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion; }
其实WiFiManager使用aidl方式和WifiService进行通信。
frameworks/base/wifi/java/android/net/wifi/IWifiManager.aidl
boolean setWifiEnabled(String packageName, boolean enable);
2.3.最终调用的的是WifiServiceImpl中的setWifiEnabled方法:
WifiServiceImpl中实现WifiService的方法,像WifiController发消息:CMD_WIFI_TOGGLED.
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);
2.4. WifiController状态机处理消息:CMD_WIFI_TOGGLED
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiController.java
WifiController状态机的状态变化,这里我们只说softap关闭状态下打开sta的情况;有时间的话,可以跟一下softap打开状态下打开sta的流程。这里只需关注“Turn ON STA” .
2.4.1 ApStaDisabledState 状态下,不对CMD_WIFI_TOGGLED消息处理
2.4.2 转向StaEnabledState状态,在该状态的enter()函数中启动supplicant, processMessage中会根据扫描、sta/ap共存等条件做相应的状态处理。
class StaEnabledState extends State { @Override public void enter() { mWifiStateMachine.setSupplicantRunning(true); } @Override public boolean processMessage(Message msg) { switch (msg.what) { case CMD_WIFI_TOGGLED: if (! mSettingsStore.isWifiToggleEnabled()) { if (mSettingsStore.isScanAlwaysAvailable()) { transitionTo(mStaDisabledWithScanState); } else { transitionTo(mApStaDisabledState); } } break;
可以看到WifiController再让mWifiStateMachine状态机去启动Supplicant
下面看看mWifiStateMachine.setSupplicantRunning(true);
2.5. frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java
public void setSupplicantRunning(boolean enable) { if (enable) { sendMessage(CMD_START_SUPPLICANT); } else { sendMessage(CMD_STOP_SUPPLICANT); } }
从上面可以看到setSupplicantRunning发送了一个消息CMD_START_SUPPLICANT,那么我们就到WifiStateMachine的InitialState状态里面去看看processMessage函数
2.6. frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java
这里先简单给出wifi状态机WifiStateMachine的各状态及结构。
WifiStateMachine state: |- DefaultState |-- InitialState |-- SupplicantStartingState |-- SupplicantStartedState |--- ScanModeState |--- ConnectModeState |---- L2ConnectedState |----- ObtainingIpState |----- ConnectedState |----- RoamingState |---- DisconnectingState |---- DisconnectedState |---- WpsRunningState |---- FilsState |--- WaitForP2pDisableState |-- SupplicantStoppingState |-- SoftApstate
InitialState状态中处理消息:CMD_START_SUPPLICANT, 做加载驱动、启动supplicant操作,mWifiMonitor.startMonitoring然后转向SupplicantStartingState状态。
class InitialState extends State { @Override public boolean processMessage(Message message) { logStateAndMessage(message, this); switch (message.what) { case CMD_START_SUPPLICANT: ... mClientInterface = mWifiNative.setupForClientMode(); // loadDriver ... if (!mWifiNative.enableSupplicant()) { // start supplicant loge("Failed to start supplicant!"); setWifiState(WifiManager.WIFI_STATE_UNKNOWN); cleanup(); break; } if (mVerboseLoggingEnabled) log("Supplicant start successful"); mWifiMonitor.startMonitoring(mInterfaceName, true); //startMonitoring mWifiInjector.getWifiLastResortWatchdog().clearAllFailureCounts(); setSupplicantLogLevel(); transitionTo(mSupplicantStartingState); break;
2.7. frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
public Pair<Integer, IClientInterface> setupForClientMode() { if (!startHalIfNecessary(true)) { // start Hal Log.e(mTAG, "Failed to start HAL for client mode"); return Pair.create(SETUP_FAILURE_HAL, null); } IClientInterface iClientInterface = mWificondControl.setupDriverForClientMode(); if (iClientInterface == null) { return Pair.create(SETUP_FAILURE_WIFICOND, null); } return Pair.create(SETUP_SUCCESS, iClientInterface); }
//启动Hal层。如果支持STA/AP共存,startConcurrentVendorHal;如果不支持共存:isStaMode=true启动sta模式,isStaMode=false启动ap模式。
private boolean startHalIfNecessary(boolean isStaMode) if (mStaAndAPConcurrency) // start ap & sta Concurrent Hal return mWifiVendorHal.startConcurrentVendorHal(isStaMode); return mWifiVendorHal.startVendorHal(isStaMode); // start Hal. Here
2.8. 不同于android N,wifinative会调用JNI层com_android_server_wifi_WifiNative.cpp. Android O在framework增加了调用Hal层的相关接口及hal设备管理接口。
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiVendorHal.java
public boolean startVendorHal(boolean isStaMode) mHalDeviceManager.start() //start wifi vendor hal mIWifiStaIface = mHalDeviceManager.createStaIface(null, null); //loadDriver
2.9. 继续跟mIWifiStaIface = mHalDeviceManager.createStaIface(null, null);
frameworks/opt/net/wifi/service/java/com/android/server/wifi/HalDeviceManager.java
public IWifiStaIface createStaIface(InterfaceDestroyedListener destroyedListener, Looper looper) { return (IWifiStaIface) createIface(IfaceType.STA, destroyedListener, looper); }
private IWifiIface createIface(int ifaceType, InterfaceDestroyedListener destroyedListener, Looper looper) IWifiIface iface = createIfaceIfPossible(chipInfos, ifaceType, destroyedListener, looper);
private IWifiIface createIfaceIfPossible(WifiChipInfo[] chipInfos, int ifaceType, InterfaceDestroyedListener destroyedListener, Looper looper) IWifiIface iface = executeChipReconfiguration(bestIfaceCreationProposal, ifaceType);
private IWifiIface executeChipReconfiguration(IfaceCreationData ifaceCreationData, int ifaceType) WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip(ifaceCreationData.chipModeId);
2.10. Android O不在使用之前版本的JNI com_android_server_wifi_WifiNative.cpp。而是用HIDL,其实现在/hardware/interfaces/.
hardware/interfaces/wifi/1.1/default/wifi_chip.cpp
Return<void> WifiChip::configureChip(ChipModeId mode_id, configureChip_cb hidl_status_cb) return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::configureChipInternal, hidl_status_cb, mode_id);
WifiStatus WifiChip::configureChipInternal(ChipModeId mode_id) WifiStatus status = handleChipConfiguration(mode_id);
WifiStatus WifiChip::handleChipConfiguration(ChipModeId mode_id) if (mode_id == kStaChipModeId) { success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA); } else { success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP); }
2.11. hardware/interfaces/wifi/1.0/default/wifi_mode_controller.cpp
bool WifiModeController::changeFirmwareMode(IfaceType type) driver_tool_->LoadDriver() driver_tool_->ChangeFirmwareMode(convertIfaceTypeToFirmwareMode(type))
2.12. 最后调到hal层,android O的hal层也进行了重写。位置也从之前的版本中的hardware/libhardware_legacy/wifi/移到了frameworks/opt/net/wifi/libwifi_hal/
frameworks/opt/net/wifi/libwifi_hal/driver_tool.cpp
bool DriverTool::LoadDriver() return ::wifi_load_driver() == 0;
2.13 frameworks/opt/net/wifi/libwifi_hal/wifi_hal_common.cpp
int wifi_load_driver() if (is_wifi_driver_loaded()) return 0; insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG)
除了一些打开wifi时的消息通知、广播、状态变化,这里没有详细描述;至此,wifi打开的相关工作已经完成。
有些平台把加载wifi驱动的动作放在了开机时,在init.$(target).rc文件中:
insmod /vendor/lib/modules/wlan.ko
根据实际情况,可能需要将开机加载驱动改为原来的动态加载。只需要做两处改动:
A. init脚本中删除加载wlan driver的行
B. 确认如下几个宏是打开和正确定义,在产品平台对应的makefile文件中加入即可:
WIFI_DRIVER_MODULE_PATH := "/vendor/lib/modules/wlan.ko" WIFI_DRIVER_MODULE_NAME := "wlan" WIFI_DRIVER_MODULE_ARG := ""
参考https://blog.csdn.net/h784707460/article/details/79572861
更多相关文章
- 箭头函数的基础使用
- Python技巧匿名函数、回调函数和高阶函数
- 浅析android通过jni控制service服务程序的简易流程
- Android(安卓)Wifi模块分析(三)
- Android中dispatchDraw分析
- Android四大基本组件介绍与生命周期
- Android(安卓)Service AIDL
- Android(安卓)bluetooth介绍(四): a2dp connect流程分析
- Android调用天气预报的WebService简单例子