版权声明:本文为博主原创文章,未经博主允许不得转载。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.java
public 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 := ""