Android 4.0 WIFI初始化與啓動流程

這幾天閒着沒事,我就隨便拿起Android源碼看看。如下要講的是在ICS中wifi初始化的一些流程。 java

涉及的文件有: android

SystemServer.java 網絡

WifiSettings.java ide

WifiEnabler.java 函數

WifiManager.java ui

WifiService.java 代理

WifiStateMachine.java rest

android_net_wifi_wifi.cpp blog

wifi.c 繼承


首先從SystemServer.java開始,它作了3個動做:

1.添加註冊ConnectivityService鏈接服務,它跟全部手機的無線通訊都有聯繫,包括wifi,藍牙,2g網絡,3g網絡等

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

2.管理開機wifi開啓與否的問題

wifi.checkAndStartWifi();

    public void checkAndStartWifi() {
        mAirplaneModeOn.set(isAirplaneModeOn());
        mPersistWifiState.set(getPersistedWifiState());
        boolean wifiEnabled = shouldWifiBeEnabled() || testAndClearWifiSavedState();
        setWifiEnabled(wifiEnabled);
        mWifiWatchdogStateMachine = WifiWatchdogStateMachine.
               makeWifiWatchdogStateMachine(mContext);

    }

3.添加註冊wifi的核心服務wifiservice

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

好了,機器啓動的時候動做就這些。要開啓wifi,還須要人在設置界面進行開啓。·

下面將一步步介紹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);

    }

先介紹一下WifiStateMachine這個類,光看名字就知道wifi狀態機,它裏面記錄了wifi的各類狀 態,driverUnloadedstate、mDriverUnloadingState、mDriverLoadingState、 mDriverLoadedState、mSupplicantStartingState,每種狀態都有enter()、exit()、 processMessage()3個函數,分別處理進入該狀態,退出該狀態的動做,以及消息處理。在WifiStateMachine構造函數裏面,它 把全部狀態都添加進狀態機去,造成一個狀態樹,並在結尾出啓動這個狀態機工做。

    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(mTetheringState, mSoftApStartedState);
                addState(mTetheredState, mSoftApStartedState);
            addState(mSoftApStoppingState, mDefaultState);
            addState(mWaitForP2pDisableState, mDefaultState);

    。。。。。。。。。。

         start();

    }

具體狀態機是如何工做的,這篇文章有很詳細的介紹,我就不累贅了。

http://archive.cnblogs.com/a/2424626/

咱們再回到mWifiStateMachine.setWifiEnabled(enable)函數;

    public void setWifiEnabled(boolean enable) {
        mLastEnableUid.set(Binder.getCallingUid());
        if (enable) {
            /* Argument is the state that is entered prior to load */
            sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0));
            sendMessage(CMD_START_SUPPLICANT);
        } else {
            sendMessage(CMD_STOP_SUPPLICANT);
            /* Argument is the state that is entered upon success */
            sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED, 0));
        }
    }

它作了兩個動做,向狀態機發送了2個消息

sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0));加載驅動

sendMessage(CMD_START_SUPPLICANT);開啓supplicant

它在哪裏處理的呢?

狀態機構造函數初始化時候,設置有個一個初始狀態

        setInitialState(mInitialState);

咱們進入mInitialState狀態看看

        public void enter() {
            if (WifiNative.isDriverLoaded()) {
                transitionTo(mDriverLoadedState);
            }
            else {
                transitionTo(mDriverUnloadedState);
            }
由於最開始驅動都是沒有加載的,因此進入transitionTo(mDriverUnloadedState);

transitionTo函數是狀態切換的函數。

繼續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;
            }
            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
            return HANDLED;
        }
    }

這裏會處理剛纔的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;

    }

狀態繼續切換到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!");
                        switch(message.arg1) {
                            case WIFI_STATE_ENABLING:
                                setWifiState(WIFI_STATE_UNKNOWN);
                                break;
                            case WIFI_AP_STATE_ENABLING:
                                setWifiApState(WIFI_AP_STATE_FAILED);
                                break;
                        }
                        sendMessage(CMD_LOAD_DRIVER_FAILURE);
                    }
                    mWakeLock.release();
                }
            }).start();
        }

這裏回調用WifiNative.loadDriver()加載驅動,成功後發送消息CMD_LOAD_DRIVER_SUCCESS,不然CMD_LOAD_DRIVER_FAILURE,進入JNI

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

會繼續到wifi.c處理

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 */
    int status = -1;

    if (is_wifi_driver_loaded()) {
        return 0;
    }
    /* ensure that wlan driver config file exists (if specified) */
    if (ensure_wlan_driver_config_file_exists()) {
        return -1;
    }
    property_set(DRIVER_PROP_NAME, "loading");

    if(system(SDIO_POLLING_ON))
        LOGW("Couldn't turn on SDIO polling: %s", SDIO_POLLING_ON);

    if ('\0' != *DRIVER_SDIO_IF_MODULE_PATH) {
       if (insmod(DRIVER_SDIO_IF_MODULE_PATH, DRIVER_SDIO_IF_MODULE_ARG) < 0) {
           goto end;
       }
    }

    if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) {
        if ('\0' != *DRIVER_SDIO_IF_MODULE_NAME) {
           rmmod(DRIVER_SDIO_IF_MODULE_NAME);
        }
        goto end;
    }

    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) {
                status = 0;
                goto end;
            }
            else if (strcmp(driver_status, "failed") == 0) {
                _wifi_unload_driver();
                goto end;
            }
        }
        usleep(200000);
    }
    property_set(DRIVER_PROP_NAME, "timeout");
    wifi_unload_driver();
end:
    system(SDIO_POLLING_OFF);
    return status;
#else
    property_set(DRIVER_PROP_NAME, "ok");
    return 0;
#endif
}

這裏有幾個比較重要的宏

#define WIFI_DRIVER_MODULE_PATH         "/system/lib/modules/wlan.ko"驅動模塊地址

static const char SUPP_CONFIG_FILE[]    = "/data/misc/wifi/wpa_supplicant.conf";  supplicant配置文件

在這裏wifi.c會跟wpa_supplicant通訊,加載驅動


來看另外一個消息sendMessage(CMD_START_SUPPLICANT);在DriverLoadedState處理

    class DriverLoadedState extends State {
        @Override
        public boolean processMessage(Message message) {
        
                case CMD_START_SUPPLICANT:
                    try {
                        mNwService.wifiFirmwareReload(mInterfaceName, "STA");
                    } catch (Exception e) {
                        loge("Failed to reload STA firmware " + e);
                        // continue
                    }
                   try {
                         mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
                    } catch (RemoteException re) {
                        loge("Unable to change interface settings: " + re);
                    } catch (IllegalStateException ie) {
                        loge("Unable to change interface settings: " + ie);
                    }

                    if(WifiNative.startSupplicant()) {
                        if (DBG) log("Supplicant start successful");
                        mWifiMonitor.startMonitoring();
                        transitionTo(mSupplicantStartingState);
                    } else {
                        loge("Failed to start supplicant!");
                        sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
                    }
                    break;


繼續調用JNI,WifiNative.startSupplicant(),過程差很少最後在wifi.c處理

int wifi_start_supplicant()
{
    return wifi_start_supplicant_common(SUPP_CONFIG_FILE);
}

int wifi_start_supplicant_common(const char *config_file)

。。。。。。。

最後也是在這裏跟Wpa_supplicant驅動通訊

在wifi狀態發生改變的時候,wifistatemachine會經過setwifistate發送WIFI_STATE_CHANGED_ACTION消息通知外面

    private void setWifiState(int wifiState) {

        final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState);
        intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState);
        mContext.sendStickyBroadcast(intent);

}


例如在驅動加載狀態

    class DriverLoadingState extends State {

            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;
                    }

    }


    class SupplicantStartingState extends State {

        public boolean processMessage(Message message) {
            if (DBG) log(getName() + message.toString() + "\n");
            switch(message.what) {
                case WifiMonitor.SUP_CONNECTION_EVENT:
                    if (DBG) log("Supplicant connection established");
                    setWifiState(WIFI_STATE_ENABLED);

   }


在wifisettings裏面也有廣播監聽器

    public WifiSettings() {
        mFilter = new IntentFilter();
        mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
        mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
        mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
        mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
        mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
        mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
        mFilter.addAction(WifiManager.ERROR_ACTION);

        mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                handleEvent(context, intent);
            }
        };

        mScanner = new Scanner();
    }

當接受到廣播會相應處理handleEvent

    private void handleEvent(Context context, Intent intent) {
        String action = intent.getAction();
        if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
            updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                    WifiManager.WIFI_STATE_UNKNOWN));
        }
    }


更新wifi狀態

    private void updateWifiState(int state) {
        getActivity().invalidateOptionsMenu();

        switch (state) {
            case WifiManager.WIFI_STATE_ENABLED:
                mScanner.resume();
                return; // not break, to avoid the call to pause() below

            case WifiManager.WIFI_STATE_ENABLING:
                addMessagePreference(R.string.wifi_starting);
                break;

            case WifiManager.WIFI_STATE_DISABLED:
                addMessagePreference(R.string.wifi_empty_list_wifi_off);
                break;
        }

        mLastInfo = null;
        mLastState = null;
        mScanner.pause();
    }

        好比 case WifiManager.WIFI_STATE_ENABLED:當WIFI可用通知接受到的時候
                mScanner.resume();

Scanner resume函數

        void resume() {
            if (!hasMessages(0)) {
                sendEmptyMessage(0);
            }
        }

再看處理

        @Override
        public void handleMessage(Message message) {
            if (mWifiManager.startScanActive()) {
                mRetry = 0;
            } else if (++mRetry >= 3) {
                mRetry = 0;
                Toast.makeText(getActivity(), R.string.wifi_fail_to_scan,
                        Toast.LENGTH_LONG).show();
                return;
            }
            sendEmptyMessageDelayed(0, WIFI_RESCAN_INTERVAL_MS);
        }
    }

會調用mWifiManager.startScanActive()進行ap的掃描

因此當你點擊wifi按鈕,到驅動加載完成,發出WIFI_STATE_ENABLED消息的時候,

設置裏面會進行掃描ap的動做
相關文章
相關標籤/搜索