Android4.0 WiFi 源码解读

网上对android WiFi源码解读的帖子也有不少,但大部分是android 2.3左右。最近研究了下android4.0 的WiFi源码,发现跟2.3的还是相差蛮大的,所以在此记录下,以便跟大家一起分享,探讨。

本文主要讨论的类及相关位置如下:

view source print ?
01 Wifi Application代码:
02     packages/apps/Settings/src/com/android/settings/wifi
03     (WifiEnabler.java、WifiSetting.java)
04  
05 Android系统启动过程
06     frameworks/base/services/java/com/android/server
07     (SystemServer.java、WifiService.java)
08  
09 Wifi Framework:
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
13  
14 Wifi JNI:
15     frameworks/base/core/jni/android_net_wifi_Wifi.cpp
16  
17 Wifi Hardware:
18     hardware/libhardware_legacy/wifi/wifi.c

1、从SystemServer.java说起,系统刚启动时,怎么启动wifi服务的

view source print ?
01 classServerThreadextendsThread {
02     privatestaticfinalString TAG ="SystemServer";
03  
04     @Override
05     publicvoidrun() {
06  
07         wifi =newWifiService(context);
08         ServiceManager.addService(Context.WIFI_SERVICE, wifi);
09  
10         connectivity =newConnectivityService(
11                 context, networkManagement, networkStats, networkPolicy);
12         ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
13         wifi.checkAndStartWifi();
14  
15         location =newLocationManagerService(context);
16         ServiceManager.addService(Context.LOCATION_SERVICE, location);
17  
18         }
19 }
20 publicclassSystemServer {
21     privatestaticfinalString TAG ="SystemServer";
22     nativepublicstaticvoidinit1(String[] args);
23  
24     publicstaticvoidmain(String[] args) {
25         System.loadLibrary("android_servers");
26         init1(args);
27     }
28     publicstaticfinalvoidinit2() {
29         Slog.i(TAG,"Entered the Android system server!");
30         Thread thr =newServerThread();
31         thr.setName("android.server.ServerThread");
32         thr.start();
33     }
34 }

在SystemThread中通过ServiceManager.addService()会添加注册各种服务(wifi、location、connectivity、bluetooth、、)
其 中ConnectivityService连接服务,它跟所有手机的无线通信都有联系,包括wifi,蓝牙,2g网络,3g网络等。然后 SystemServer会加载"android servers"的本地库(位于/frameworks/base/cmds/system server/library),其中会调用init2方法启动SystemThread。

系统启动时就完成以上动作,当所有服务正常启动后,系统就开始做好运行新的应用程序的准备。

2、再到手机设置界面开启Wifi

进入wifi设置界面,相关文件WifiSettings.java

开启Wifi的组件是一个CompoundButton,跟它关联起来的是一个WifiEnabler.java类,它是在WifiSettings里面初始化的

view source print ?
1 publicvoidonActivityCreated(Bundle savedInstanceState) {
2             mWifiEnabler =newWifiEnabler(activity, actionBarSwitch);
3  
4 }

当用户点击wifi的开启按钮时候,会触发WifiEnabler里面的onCheckedChanged函数

view source print ?
1 publicvoidonCheckedChanged(CompoundButton buttonView,booleanisChecked) {
2  
3     if(mWifiManager.setWifiEnabled(isChecked)) {
4         mSwitch.setEnabled(false);
5      }else{
6             Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show();
7 }

在onCheckedChanged函数里面,调用了WifiManager的setWifiEnabled方法

view source print ?
1 publicbooleansetWifiEnabled(booleanenabled) {
2     try{
3         returnmService.setWifiEnabled(enabled);
4     }catch(RemoteException e) {
5         returnfalse;
6     }
7 }

它返回的是mService.setWifiEnabled(enabled),这里的mService是WifiService的代理,所以它实际调用的是wifiService里面的setWifiEnabled函数

view source print ?
1 publicclassWifiServiceextendsIWifiManager.Stub

我们可以看到WifiService继承一个接口IWifiManager.Stub,凡是继承了像这种形式写法的接口服务,都可以进行远程调用,这就是Android内部的aidl通信。接下来进入wifiservice

view source print ?
1 publicsynchronizedbooleansetWifiEnabled(booleanenable) {
2  
3     mWifiStateMachine.setWifiEnabled(enable);
4  
5 }

可以看到,又进入WifiStateMachine的setWifiEnabled方法,mWifiStateMachine是在Wifiservice的构造函数完成初始化 的

view source print ?
1 WifiService(Context context) {
2  
3     mWifiStateMachine =newWifiStateMachine(mContext, mInterfaceName);
4  
5 }

在android4.0中的Wifi启动过程中,WifiStateMachine是一个非常重要的类,下面我们介绍一个这个类。
WifiStateMachine继承了StateMachine这个类,它是一个wifi状态机,其中包含了好多状态:DefaultState、InitialState、DriverLoadingState、DriverLoadedState、DriverUnloadingState、DriverUnloadedState、DriverFailedState。每种状态都有enter()、exit()、processMessage()3个函数,分别处理进入该状态,退出该状态的动作,以及消息处理。
关于WifiStateMachine详细的解读参考:WifiStateMachine详细解读

view source print ?
01 publicclassWifiStateMachineextendsStateMachine {
02  
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);
29  
30         setInitialState(mInitialState);
31  
32         if(DBG) setDbg(true);
33  
34         //start the state machine
35         start();
36     }
37

在进入WifiStateMachine的初始状态为:setInitialState(mInitialState),下面是InitialState类:

view source print ?
01 classInitialStateextendsState {
02     @Override
03     publicvoidenter() {
04         if(WifiNative.isDriverLoaded()) {
05             transitionTo(mDriverLoadedState);
06         }
07         else{
08             transitionTo(mDriverUnloadedState);
09         }
10     }
11 }

这里通过WifiNative.isDriverLoaded()判断wifi的驱动是已经加载,如果加载就将状态转到mDriverLoadedState,不然将状态转到mDriverUnloadedState。WifiNative这个类稍微讲解。

下面回到:mWifiStateMachine.setWifiEnabled(enable);

view source print ?
1 publicvoidsetWifiEnabled(booleanenable) {
2     if(enable) {
3         sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING,0));
4         sendMessage(CMD_START_SUPPLICANT);
5     }else{
6         sendMessage(CMD_STOP_SUPPLICANT);
7         sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED,0));
8     }
9 }

不管enble为何值,都会向状态机发送两个消息,一个是load/unload wifi驱动,一个是start/stop配置文件。由于从WifiService进入WifiStateMachine时,构造函数先进入了 InitialState状态,由于最开始wifi驱动是没有加载的,所以mDriverUnloadedState,

view source print ?
01 classDriverUnloadedStateextendsState {
02     @Override
03     publicbooleanprocessMessage(Message message) { 
04         switch(message.what) {
05             caseCMD_LOAD_DRIVER:
06                 mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING);
07                 transitionTo(mWaitForP2pDisableState);
08                 break;
09             caseWifiP2pService.P2P_ENABLE_PENDING:
10                 mReplyChannel.replyToMessage(message, P2P_ENABLE_PROCEED);
11                 break;
12             default:
13                 returnNOT_HANDLED;
14         }
15     }
16 }

这里处理了刚才setWifiEnabled发送的消息CMD_LOAD_DRIVER;然后转向mWaitForP2pDisableState;

view source print ?
01 classWaitForP2pDisableStateextendsState {
02     @Override
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);
10                 break;
11             caseCMD_LOAD_DRIVER:
12             caseCMD_UNLOAD_DRIVER:
13             caseCMD_START_SUPPLICANT:
14             caseCMD_STOP_SUPPLICANT:
15             caseCMD_START_AP:
16             caseCMD_STOP_AP:
17                 deferMessage(message);
18                 break;
19             default:
20                 returnNOT_HANDLED;
21         }
22     }
23 }

然后继续转到状态mDriverLoadingState;

view source print ?
01 classDriverLoadingStateextendsState {
02     @Override
03     publicvoidenter() {
04         newThread(newRunnable() {
05             publicvoidrun() {
06                 mWakeLock.acquire();
07                 //enabling state
08                 switch(message.arg1) {
09                     caseWIFI_STATE_ENABLING:
10                         setWifiState(WIFI_STATE_ENABLING);
11                         break;
12                     caseWIFI_AP_STATE_ENABLING:
13                         setWifiApState(WIFI_AP_STATE_ENABLING);
14                         break;
15                 }
16  
17                 if(WifiNative.loadDriver()) {
18                     if(DBG) log("Driver load successful");
19                     sendMessage(CMD_LOAD_DRIVER_SUCCESS);
20                 }else{
21                     loge("Failed to load driver!");
22  
23                 mWakeLock.release();
24             }
25         }).start();
26     }
27

完成两个动作1、 setWifiState(WIFI_STATE_ENABLING);2、WifiNative.loadDriver();

下面讲解WifiNative。

view source print ?
01 publicclassWifiNative {
02  
03 publicnativestaticbooleanloadDriver();
04  
05 publicnativestaticbooleanisDriverLoaded();
06  
07 publicnativestaticbooleanunloadDriver();
08  
09 publicnativestaticbooleanstartSupplicant();
10  
11 、、、、、、、、、、、、
12

在WifiNative中的函数有好大一部分都是native函数,熟悉android JNI的同学都知道,这些函数的实现都在本地实现。
这些函数的实现都在/frameworks/base/core/jni目录下的 android_net_wifi_Wifi.cpp中。

view source print ?
01 staticjboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject)
02     {
03         return(jboolean)(::is_wifi_driver_loaded() == 1);
04     }
05  
06     staticjboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
07     {
08         return(jboolean)(::wifi_load_driver() == 0);
09     }
10  
11     staticjboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject)
12     {
13         return(jboolean)(::wifi_unload_driver() == 0);
14     }
15  
16     staticjboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject)
17     {
18         return(jboolean)(::wifi_start_supplicant() == 0);
19     }

其中这些函数都调用的是系统范围内的相应的函数,这些函数都位于:/hardware/libhardware_legacy/wifi下的wifi.c文件中

view source print ?
01 intwifi_load_driver()
02 {
03 #ifdef WIFI_DRIVER_MODULE_PATH
04     chardriver_status[PROPERTY_VALUE_MAX];
05     intcount = 100;/* wait at most 20 seconds for completion */
06  
07     if(is_wifi_driver_loaded()) {
08         return0;
09     }
10  
11     if(insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
12         return-1;
13  
14     if(strcmp(FIRMWARE_LOADER,"") == 0) {
15         /* usleep(WIFI_DRIVER_LOADER_DELAY); */
16         property_set(DRIVER_PROP_NAME,"ok");
17     }
18     else{
19         property_set("ctl.start", FIRMWARE_LOADER);
20     }
21     sched_yield();
22     while(count-- > 0) {
23         if(property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
24             if(strcmp(driver_status,"ok") == 0)
25                 return0;
26             elseif(strcmp(DRIVER_PROP_NAME,"failed") == 0) {
27                 wifi_unload_driver();
28                 return-1;
29             }
30         }
31         usleep(200000);
32     }
33     property_set(DRIVER_PROP_NAME,"timeout");
34     wifi_unload_driver();
35     return-1;
36 #else
37     property_set(DRIVER_PROP_NAME,"ok");
38     return0;
39 #endif
40 }

这个函数中会加载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系统的终端截图如下:
Android4.0 WiFi 源码解读_第1张图片
Android4.0 WiFi 源码解读_第2张图片

最后你可以在终端上使用命令:lsmod 可以查看当前的系统加载的模块。
当关闭wifi的时候,你发现会少一个模块名为:wlan.ko(我手机上为:wl12xx_sdio.ko),当你在设置界面启动wifi后,你通过命令可以查看发现系统中多加载了一个模块:wlan.ko(我手机上为:wl12xx_sdio.ko),截图如下:
关闭wifi后,即没加载wlan.ko(我手机上为:wl12xx_sdio.ko)时:
Android4.0 WiFi 源码解读_第3张图片

启动wifi后,即加载wlan.ko(我手机上为:wl12xx_sdio.ko)后:

Android4.0 WiFi 源码解读_第4张图片

最后你可以进入目录:/proc/modules查看你系统所有可用的模块(系统可能加载了,也可能没加载)

Android4.0 WiFi 源码解读_第5张图片

写了两天终于写完了,请各位大牛不吝赐教,以免误导像我这样的菜鸟。


你可能感兴趣的:(Android4.0 WiFi 源码解读)