Android wifi開啟流程(Android O)
根據自己的理解整理了Android O的wifi啟動流程,為便於理解,繪製了Android O wifi架構圖。有理解不到之處和錯誤之處,請各位指出,一起學習。
一. Android O wifi 架構:
由於Android O的Treble化,Android O上Wifi架構變動也比較大,尤其是JNI層、Hal層、HIDL層。
下圖是Android O Treble HIDL大致結構:
下圖是Android O wifi架構:
下圖是Android Wlan架構(from android官網)
二. 函式呼叫流程:
1. 在wifisettings activity的onStart函式中,建立一個WifiEnabler物件,用於實現wifi開關功能。
packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java
onStart()
mWifiEnabler = createWifiEnabler();
2. WifiEnabler開關SwitchToggled中會呼叫WifiManager.setWifiEnabled方法。
packages/apps/Settings/src/com/android/settings/wifi/WifiEnabler.java
onSwithToggled(boolean isCkecked)
mWifiManager.setWifiEnabled(isChecked)
3. WifiManager呼叫WifiService的方法。
frameworks/base/wifi/java/android/net/wifi/WifiManager.java
setWifiEnabled(boolean enabled)
mService.setWifiEnabled(mContext.getOpPackageName(), enabled)
4. WiFiManager使用aidl方式和WifiService進行通訊。
frameworks/base/wifi/java/android/net/wifi/IWifiManager.aidl
boolean setWifiEnabled(String packageName, boolean enable);
5. 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);
6. WifiController狀態機處理訊息:CMD_WIFI_TOGGLED
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiController.java
WifiController狀態機的狀態變化,這裡我們只說softap關閉狀態下開啟sta的情況;有時間的話,可以跟一下softap開啟狀態下開啟sta的流程。這裡只需關注“Turn ON STA” .
* ------------------
* ApStaDisabledState
* ------------------
* / \
* -> Turn ON STA / \ Turn on SAP <-
* / \
* / \
* --------------- --------------
* StaEnabledState ApEnabledState
* --------------- --------------
* \ /
* \ /
* -> Turn ON SAP \ / Turn on STA <-
* \ /
* ---------------
* QcApStaEnablingState
* ---------------
* | |
* | |
* -> CMD_AP_STARTED | | CMD_STA_STARTED <-
*(SAP turn on completed) | | (STA turn on completed)
* | |
* ---------------------
* QcApStaEnabledState
* ----------------------
* / \
/ \
* -> Turn on OFF STA / \ Turn OFF SAP
* / \
* ------------------------
* QcApStaDisablingState
* ------------------------
* /\
* / \
* -> CMD_WIFI_DISABLED / \ CMD_AP_STOPPED <-
*(STA turn OFF completed)/ \ (SAP turn OFF completed)
* / \
* / \
* ------------------- -------------
* ApEnabledState StaEnabledState
* ------------------- ---------------
6.1 ApStaDisabledState 狀態下,不對CMD_WIFI_TOGGLED訊息處理
6.2 轉向StaEnabledState狀態,在該狀態的enter()函式中啟動supplicant, processMessage中會根據掃描、sta/ap共存等條件做相應的狀態處理。
class StaEnabledState extends State
enter()
mWifiStateMachine.setSupplicantRunning(true);
public boolean processMessage(Message msg)
case CMD_WIFI_TOGGLED:
7. frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java
public void setSupplicantRunning(boolean enable)
sendMessage(CMD_START_SUPPLICANT);
8. frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java
又是狀態機,這裡簡單給出wifi狀態機的各狀態及結構。感覺有必要專門講一下狀態機。
WifiStateMachine state:
|- DefaultState
|-- InitialState
|-- SupplicantStartingState
|-- SupplicantStartedState
|--- ScanModeState
|--- ConnectModeState
|---- L2ConnectedState
|----- ObtainingIpState
|----- ConnectedState
|----- RoamingState
|---- DisconnectingState
|---- DisconnectedState
|---- WpsRunningState
|---- FilsState
|--- WaitForP2pDisableState
|-- SupplicantStoppingState
|-- SoftApstate
InitialState狀態中處理訊息:CMD_START_SUPPLICANT, 做載入驅動、啟動supplicant操作,然後轉向SupplicantStartingState狀態。
class InitialState extends State
case CMD_START_SUPPLICANT:
mClientInterface = mWifiNative.setupForClientMode(); // loadDriver
mWifiNative.enableSupplicant() // start supplicant
transitionTo(mSupplicantStartingState);
9. frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
public IClientInterface setupForClientMode()
startHalIfNecessary(true)) // start Hal
IClientInterface iClientInterface = mWificondControl.setupDriverForClientMode();
//啟動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
10. 不同於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
11. 這個程式碼跟的有些凌亂
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);
12. 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);
}
13. hardware/interfaces/wifi/1.0/default/wifi_mode_controller.cpp
bool WifiModeController::changeFirmwareMode(IfaceType type)
driver_tool_->LoadDriver()
driver_tool_->ChangeFirmwareMode(convertIfaceTypeToFirmwareMode(type))
14. 最後調到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;
15 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開啟的相關工作已經完成。
Qcom平臺把載入wifi驅動的動作放在了開機時,在init.target.rc檔案中:
insmod /vendor/lib/modules/qca_cld3_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 := ""