網上對android WiFi源碼解讀的帖子也有很多,但大部分是android 2.3左右。最近研究了下android4.0 的WiFi源碼,發現跟2.3的仍是相差蠻大的,因此在此記錄下,以便跟你們一塊兒分享,探討。 html
本文主要討論的類及相關位置以下: java
02 |
packages/apps/Settings/src/com/android/settings/wifi |
03 |
(WifiEnabler.java、WifiSetting.java) |
06 |
frameworks/base/services/java/com/android/server |
07 |
(SystemServer.java、WifiService.java) |
10 |
frameworks/base/wifi/java/android/net/wifi |
11 |
(IWifiManager.aidl、WifiManager.java、WifiStateMachine.java、WifiNative.java) |
12 |
frameworks/base/services/java/com/android/server |
15 |
frameworks/base/core/jni/android_net_wifi_Wifi.cpp |
18 |
hardware/libhardware_legacy/wifi/wifi.c |
一、從SystemServer.java提及,系統剛啓動時,怎麼啓動wifi服務的 android
01 |
classServerThreadextendsThread { |
02 |
privatestaticfinalString TAG ="SystemServer"; |
07 |
wifi =newWifiService(context); |
08 |
ServiceManager.addService(Context.WIFI_SERVICE, wifi); |
10 |
connectivity =newConnectivityService( |
11 |
context, networkManagement, networkStats, networkPolicy); |
12 |
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity); |
13 |
wifi.checkAndStartWifi(); |
15 |
location =newLocationManagerService(context); |
16 |
ServiceManager.addService(Context.LOCATION_SERVICE, location); |
20 |
publicclassSystemServer { |
21 |
privatestaticfinalString TAG ="SystemServer"; |
22 |
nativepublicstaticvoidinit1(String[] args); |
24 |
publicstaticvoidmain(String[] args) { |
25 |
System.loadLibrary("android_servers"); |
28 |
publicstaticfinalvoidinit2() { |
29 |
Slog.i(TAG,"Entered the Android system server!"); |
30 |
Thread thr =newServerThread(); |
31 |
thr.setName("android.server.ServerThread"); |
在SystemThread中經過ServiceManager.addService()會添加註冊各類服務(wifi、location、connectivity、bluetooth、、)
其 中ConnectivityService鏈接服務,它跟全部手機的無線通訊都有聯繫,包括wifi,藍牙,2g網絡,3g網絡等。而後 SystemServer會加載"android servers"的本地庫(位於/frameworks/base/cmds/system server/library),其中會調用init2方法啓動SystemThread。 網絡
系統啓動時就完成以上動做,當全部服務正常啓動後,系統就開始作好運行新的應用程序的準備。 app
二、再到手機設置界面開啓Wifi ide
進入wifi設置界面,相關文件WifiSettings.java 函數
開啓Wifi的組件是一個CompoundButton,跟它關聯起來的是一個WifiEnabler.java類,它是在WifiSettings裏面初始化的 ui
1 |
publicvoidonActivityCreated(Bundle savedInstanceState) { |
2 |
mWifiEnabler =newWifiEnabler(activity, actionBarSwitch); |
當用戶點擊wifi的開啓按鈕時候,會觸發WifiEnabler裏面的onCheckedChanged函數 spa
1 |
publicvoidonCheckedChanged(CompoundButton buttonView,booleanisChecked) { |
3 |
if(mWifiManager.setWifiEnabled(isChecked)) { |
4 |
mSwitch.setEnabled(false); |
6 |
Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show(); |
在onCheckedChanged函數裏面,調用了WifiManager的setWifiEnabled方法 .net
1 |
publicbooleansetWifiEnabled(booleanenabled) { |
3 |
returnmService.setWifiEnabled(enabled); |
4 |
}catch(RemoteException e) { |
它返回的是mService.setWifiEnabled(enabled),這裏的mService是WifiService的代理,因此它實際調用的是wifiService裏面的setWifiEnabled函數
1 |
publicclassWifiServiceextendsIWifiManager.Stub |
咱們能夠看到WifiService繼承一個接口IWifiManager.Stub,凡是繼承了像這種形式寫法的接口服務,均可以進行遠程調用,這就是Android內部的aidl通訊。接下來進入wifiservice
1 |
publicsynchronizedbooleansetWifiEnabled(booleanenable) { |
3 |
mWifiStateMachine.setWifiEnabled(enable); |
能夠看到,又進入WifiStateMachine的setWifiEnabled方法,mWifiStateMachine是在Wifiservice的構造函數完成初始化 的
1 |
WifiService(Context context) { |
3 |
mWifiStateMachine =newWifiStateMachine(mContext, mInterfaceName); |
在android4.0中的Wifi啓動過程當中,WifiStateMachine是一個很是重要的類,下面咱們介紹一個這個類。
WifiStateMachine繼承了StateMachine這個類,它是一個wifi狀態機,其中包含了好多狀態:DefaultState、InitialState、DriverLoadingState、DriverLoadedState、DriverUnloadingState、DriverUnloadedState、DriverFailedState。每種狀態都有enter()、exit()、processMessage()3個函數,分別處理進入該狀態,退出該狀態的動做,以及消息處理。
關於WifiStateMachine詳細的解讀參考:WifiStateMachine詳細解讀
01 |
publicclassWifiStateMachineextendsStateMachine { |
03 |
publicWifiStateMachine(Context context, String wlanInterface) { |
04 |
addState(mDefaultState); |
05 |
addState(mInitialState, mDefaultState); |
06 |
addState(mDriverUnloadingState, mDefaultState); |
07 |
addState(mDriverUnloadedState, mDefaultState); |
08 |
addState(mDriverFailedState, mDriverUnloadedState); |
09 |
addState(mDriverLoadingState, mDefaultState); |
10 |
addState(mDriverLoadedState, mDefaultState); |
11 |
addState(mSupplicantStartingState, mDefaultState); |
12 |
addState(mSupplicantStartedState, mDefaultState); |
13 |
addState(mDriverStartingState, mSupplicantStartedState); |
14 |
addState(mDriverStartedState, mSupplicantStartedState); |
15 |
addState(mScanModeState, mDriverStartedState); |
16 |
addState(mConnectModeState, mDriverStartedState); |
17 |
addState(mConnectingState, mConnectModeState); |
18 |
addState(mConnectedState, mConnectModeState); |
19 |
addState(mDisconnectingState, mConnectModeState); |
20 |
addState(mDisconnectedState, mConnectModeState); |
21 |
addState(mWaitForWpsCompletionState, mConnectModeState); |
22 |
addState(mDriverStoppingState, mSupplicantStartedState); |
23 |
addState(mDriverStoppedState, mSupplicantStartedState); |
24 |
addState(mSupplicantStoppingState, mDefaultState); |
25 |
addState(mSoftApStartingState, mDefaultState); |
26 |
addState(mSoftApStartedState, mDefaultState); |
27 |
addState(mTetheredState, mSoftApStartedState); |
28 |
addState(mWaitForP2pDisableState, mDefaultState); |
30 |
setInitialState(mInitialState); |
34 |
//start the state machine |
在進入WifiStateMachine的初始狀態爲:setInitialState(mInitialState),下面是InitialState類:
01 |
classInitialStateextendsState { |
04 |
if(WifiNative.isDriverLoaded()) { |
05 |
transitionTo(mDriverLoadedState); |
08 |
transitionTo(mDriverUnloadedState); |
這裏經過WifiNative.isDriverLoaded()判斷wifi的驅動是已經加載,若是加載就將狀態轉到mDriverLoadedState,否則將狀態轉到mDriverUnloadedState。WifiNative這個類稍微講解。
下面回到:mWifiStateMachine.setWifiEnabled(enable);
1 |
publicvoidsetWifiEnabled(booleanenable) { |
3 |
sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING,0)); |
4 |
sendMessage(CMD_START_SUPPLICANT); |
6 |
sendMessage(CMD_STOP_SUPPLICANT); |
7 |
sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED,0)); |
無論enble爲什麼值,都會向狀態機發送兩個消息,一個是load/unload wifi驅動,一個是start/stop配置文件。因爲從WifiService進入WifiStateMachine時,構造函數先進入了 InitialState狀態,因爲最開始wifi驅動是沒有加載的,因此mDriverUnloadedState,
01 |
classDriverUnloadedStateextendsState { |
03 |
publicbooleanprocessMessage(Message message) { |
04 |
switch(message.what) { |
06 |
mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING); |
07 |
transitionTo(mWaitForP2pDisableState); |
09 |
caseWifiP2pService.P2P_ENABLE_PENDING: |
10 |
mReplyChannel.replyToMessage(message, P2P_ENABLE_PROCEED); |
這裏處理了剛纔setWifiEnabled發送的消息CMD_LOAD_DRIVER;而後轉向mWaitForP2pDisableState;
01 |
classWaitForP2pDisableStateextendsState { |
03 |
publicbooleanprocessMessage(Message message) { |
04 |
if(DBG) log(getName() + message.toString() +"\n"); |
05 |
switch(message.what) { |
06 |
caseWifiP2pService.WIFI_ENABLE_PROCEED: |
07 |
//restore argument from original message (CMD_LOAD_DRIVER) |
08 |
message.arg1 = mSavedArg; |
09 |
transitionTo(mDriverLoadingState); |
12 |
caseCMD_UNLOAD_DRIVER: |
13 |
caseCMD_START_SUPPLICANT: |
14 |
caseCMD_STOP_SUPPLICANT: |
17 |
deferMessage(message); |
而後繼續轉到狀態mDriverLoadingState;
01 |
classDriverLoadingStateextendsState { |
04 |
newThread(newRunnable() { |
08 |
switch(message.arg1) { |
09 |
caseWIFI_STATE_ENABLING: |
10 |
setWifiState(WIFI_STATE_ENABLING); |
12 |
caseWIFI_AP_STATE_ENABLING: |
13 |
setWifiApState(WIFI_AP_STATE_ENABLING); |
17 |
if(WifiNative.loadDriver()) { |
18 |
if(DBG) log("Driver load successful"); |
19 |
sendMessage(CMD_LOAD_DRIVER_SUCCESS); |
21 |
loge("Failed to load driver!"); |
完成兩個動做一、 setWifiState(WIFI_STATE_ENABLING);二、WifiNative.loadDriver();
下面講解WifiNative。
01 |
publicclassWifiNative { |
03 |
publicnativestaticbooleanloadDriver(); |
05 |
publicnativestaticbooleanisDriverLoaded(); |
07 |
publicnativestaticbooleanunloadDriver(); |
09 |
publicnativestaticbooleanstartSupplicant(); |
在WifiNative中的函數有好大一部分都是native函數,熟悉android JNI的同窗都知道,這些函數的實現都在本地實現。
這些函數的實現都在/frameworks/base/core/jni目錄下的 android_net_wifi_Wifi.cpp中。
01 |
staticjboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject) |
03 |
return(jboolean)(::is_wifi_driver_loaded() == 1); |
06 |
staticjboolean android_net_wifi_loadDriver(JNIEnv* env, jobject) |
08 |
return(jboolean)(::wifi_load_driver() == 0); |
11 |
staticjboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject) |
13 |
return(jboolean)(::wifi_unload_driver() == 0); |
16 |
staticjboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject) |
18 |
return(jboolean)(::wifi_start_supplicant() == 0); |
其中這些函數都調用的是系統範圍內的相應的函數,這些函數都位於:/hardware/libhardware_legacy/wifi下的wifi.c文件中
03 |
#ifdef WIFI_DRIVER_MODULE_PATH |
04 |
chardriver_status[PROPERTY_VALUE_MAX]; |
05 |
intcount = 100;/* wait at most 20 seconds for completion */ |
07 |
if(is_wifi_driver_loaded()) { |
11 |
if(insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) |
14 |
if(strcmp(FIRMWARE_LOADER,"") == 0) { |
15 |
/* usleep(WIFI_DRIVER_LOADER_DELAY); */ |
16 |
property_set(DRIVER_PROP_NAME,"ok"); |
19 |
property_set("ctl.start", FIRMWARE_LOADER); |
23 |
if(property_get(DRIVER_PROP_NAME, driver_status, NULL)) { |
24 |
if(strcmp(driver_status,"ok") == 0) |
26 |
elseif(strcmp(DRIVER_PROP_NAME,"failed") == 0) { |
33 |
property_set(DRIVER_PROP_NAME,"timeout"); |
37 |
property_set(DRIVER_PROP_NAME,"ok"); |
這個函數中會加載WIFI_DRIVER_MODULE_PATH路徑中的驅動模塊。這個模塊位於:/system/lib/modules/wlan.ko(進入android系統的終端能夠查看到,其中我本身的驅動模塊名爲:wl12xx_sdio.ko)
另外在函數int wifi_start_supplicant_common(const char *config_file)中會加載wifi的配置文件,位於:/data/misc/wifi/wpa_supplicant.conf
在android系統的終端截圖以下:
最後你能夠在終端上使用命令:lsmod 能夠查看當前的系統加載的模塊。
當關閉wifi的時候,你發現會少一個模塊名爲:wlan.ko(我手機上爲:wl12xx_sdio.ko),當你在設置界面啓動wifi後,你經過命令能夠查看發現系統中多加載了一個模塊:wlan.ko(我手機上爲:wl12xx_sdio.ko),截圖以下:
關閉wifi後,即沒加載wlan.ko(我手機上爲:wl12xx_sdio.ko)時:
啓動wifi後,即加載wlan.ko(我手機上爲:wl12xx_sdio.ko)後:
最後你能夠進入目錄:/proc/modules查看你係統全部可用的模塊(系統可能加載了,也可能沒加載)
寫了兩天終於寫完了,請各位大牛不吝賜教,以避免誤導像我這樣的菜鳥。