Android4.0 WiFi 源码解读

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

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


Wifi Application代码:
    packages/apps/Settings/src/com/android/settings/wifi 
    (WifiEnabler.java、WifiSetting.java)

Android系统启动过程
    frameworks/base/services/java/com/android/server 
    (SystemServer.java、WifiService.java)

Wifi Framework:
    frameworks/base/wifi/java/android/net/wifi  
    (IWifiManager.aidl、WifiManager.java、WifiStateMachine.java、WifiNative.java)
    frameworks/base/services/java/com/android/server

Wifi JNI:
    frameworks/base/core/jni/android_net_wifi_Wifi.cpp

Wifi Hardware:
    hardware/libhardware_legacy/wifi/wifi.c

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


class ServerThread extends Thread {
    private static final String TAG = "SystemServer";

    @Override
    public void run() {

        wifi = new WifiService(context);
        ServiceManager.addService(Context.WIFI_SERVICE, wifi);

        connectivity = new ConnectivityService(
                context, networkManagement, networkStats, networkPolicy);
        ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
        wifi.checkAndStartWifi();

        location = new LocationManagerService(context);
        ServiceManager.addService(Context.LOCATION_SERVICE, location);

        }
}
public class SystemServer {
    private static final String TAG = "SystemServer";
    native public static void init1(String[] args);

    public static void main(String[] args) {
        System.loadLibrary("android_servers");
        init1(args);
    }
    public static final void init2() {
        Slog.i(TAG, "Entered the Android system server!");
        Thread thr = new ServerThread();
        thr.setName("android.server.ServerThread");
        thr.start();
    }
}

在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里面初始化的


public void onActivityCreated(Bundle savedInstanceState) {
            mWifiEnabler = new WifiEnabler(activity, actionBarSwitch);

}

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


public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

    if (mWifiManager.setWifiEnabled(isChecked)) {
        mSwitch.setEnabled(false);
     } else {
            Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show();
}

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


public boolean setWifiEnabled(boolean enabled) {
    try {
        return mService.setWifiEnabled(enabled);
    } catch (RemoteException e) {
        return false;
    }
}

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


public class WifiService extends IWifiManager.Stub 

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


public synchronized boolean setWifiEnabled(boolean enable) {

    mWifiStateMachine.setWifiEnabled(enable);

}

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


WifiService(Context context) {

    mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);

}

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


    public class WifiStateMachine extends StateMachine {

    public WifiStateMachine(Context context, String wlanInterface) {
        addState(mDefaultState);
            addState(mInitialState, mDefaultState);
            addState(mDriverUnloadingState, mDefaultState);
            addState(mDriverUnloadedState, mDefaultState);
                addState(mDriverFailedState, mDriverUnloadedState);
            addState(mDriverLoadingState, mDefaultState);
            addState(mDriverLoadedState, mDefaultState);
            addState(mSupplicantStartingState, mDefaultState);
            addState(mSupplicantStartedState, mDefaultState);
                addState(mDriverStartingState, mSupplicantStartedState);
                addState(mDriverStartedState, mSupplicantStartedState);
                    addState(mScanModeState, mDriverStartedState);
                    addState(mConnectModeState, mDriverStartedState);
                        addState(mConnectingState, mConnectModeState);
                        addState(mConnectedState, mConnectModeState);
                        addState(mDisconnectingState, mConnectModeState);
                        addState(mDisconnectedState, mConnectModeState);
                        addState(mWaitForWpsCompletionState, mConnectModeState);
                addState(mDriverStoppingState, mSupplicantStartedState);
                addState(mDriverStoppedState, mSupplicantStartedState);
            addState(mSupplicantStoppingState, mDefaultState);
            addState(mSoftApStartingState, mDefaultState);
            addState(mSoftApStartedState, mDefaultState);
                addState(mTetheredState, mSoftApStartedState);
            addState(mWaitForP2pDisableState, mDefaultState);

        setInitialState(mInitialState);

        if (DBG) setDbg(true);

        //start the state machine
        start();
    }
}

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


class InitialState extends State {
    @Override
    public void enter() {
        if (WifiNative.isDriverLoaded()) {
            transitionTo(mDriverLoadedState);
        }
        else {
            transitionTo(mDriverUnloadedState);
        }
    }
}

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

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


public void setWifiEnabled(boolean enable) {
    if (enable) {
        sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0));
        sendMessage(CMD_START_SUPPLICANT);
    } else {
        sendMessage(CMD_STOP_SUPPLICANT);
        sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED, 0));
    }
}

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


class DriverUnloadedState extends State {
    @Override
    public boolean processMessage(Message message) {  
        switch (message.what) {
            case CMD_LOAD_DRIVER:
                mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING);
                transitionTo(mWaitForP2pDisableState);
                break;
            case WifiP2pService.P2P_ENABLE_PENDING:
                mReplyChannel.replyToMessage(message, P2P_ENABLE_PROCEED);
                break;
            default:
                return NOT_HANDLED;
        }
    }
}

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


class WaitForP2pDisableState extends State {
    @Override
    public boolean processMessage(Message message) {
        if (DBG) log(getName() + message.toString() + "\n");
        switch(message.what) {
            case WifiP2pService.WIFI_ENABLE_PROCEED:
               //restore argument from original message (CMD_LOAD_DRIVER)
                message.arg1 = mSavedArg;
                transitionTo(mDriverLoadingState);
                break;
            case CMD_LOAD_DRIVER:
            case CMD_UNLOAD_DRIVER:
            case CMD_START_SUPPLICANT:
            case CMD_STOP_SUPPLICANT:
            case CMD_START_AP:
            case CMD_STOP_AP:
                deferMessage(message);
                break;
            default:
                return NOT_HANDLED;
        }
    }
}

然后继续转到状态mDriverLoadingState;


class DriverLoadingState extends State {
    @Override
    public void enter() {
        new Thread(new Runnable() {
            public void run() {
                mWakeLock.acquire();
                //enabling state
                switch(message.arg1) {
                    case WIFI_STATE_ENABLING:
                        setWifiState(WIFI_STATE_ENABLING);
                        break;
                    case WIFI_AP_STATE_ENABLING:
                        setWifiApState(WIFI_AP_STATE_ENABLING);
                        break;
                }

                if(WifiNative.loadDriver()) {
                    if (DBG) log("Driver load successful");
                    sendMessage(CMD_LOAD_DRIVER_SUCCESS);
                } else {
                    loge("Failed to load driver!");

                mWakeLock.release();
            }
        }).start();
    }
}

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

下面讲解WifiNative。


public class WifiNative {

public native static boolean loadDriver();

public native static boolean isDriverLoaded();

public native static boolean unloadDriver();

public native static boolean startSupplicant();

、、、、、、、、、、、、
}

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

<!-- lang: cpp -->
    static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject)
    {
        return (jboolean)(::is_wifi_driver_loaded() == 1);
    }

    static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
    {
        return (jboolean)(::wifi_load_driver() == 0);
    }

    static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject)
    {
        return (jboolean)(::wifi_unload_driver() == 0);
    }

    static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject)
    {
        return (jboolean)(::wifi_start_supplicant() == 0);
    }

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

<!-- lang: cpp -->
 int wifi_load_driver()
{
#ifdef WIFI_DRIVER_MODULE_PATH
    char driver_status[PROPERTY_VALUE_MAX];
    int count = 100; /* wait at most 20 seconds for completion */

    if (is_wifi_driver_loaded()) {
        return 0;
    }

    if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
        return -1;

    if (strcmp(FIRMWARE_LOADER,"") == 0) {
        /* usleep(WIFI_DRIVER_LOADER_DELAY); */
        property_set(DRIVER_PROP_NAME, "ok");
    }
    else {
        property_set("ctl.start", FIRMWARE_LOADER);
    }
    sched_yield();
    while (count-- > 0) {
        if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
            if (strcmp(driver_status, "ok") == 0)
                return 0;
            else if (strcmp(DRIVER_PROP_NAME, "failed") == 0) {
                wifi_unload_driver();
                return -1;
            }
        }
        usleep(200000);
    }
    property_set(DRIVER_PROP_NAME, "timeout");
    wifi_unload_driver();
    return -1;
#else
    property_set(DRIVER_PROP_NAME, "ok");
    return 0;
#endif
}

这个函数中会加载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系统的终端截图如下:
wl12xx_sdio.ko
wpa_supplicant.conf

最后你可以在终端上使用命令: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查看你系统所有可用的模块(系统可能加载了,也可能没加载)

在此输入图片描述

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

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