Android4.4 WIFI开机启动流程详析

        之前看过android4.0版本的wifi启动流程,对比android4.4的版本启动还是有不少出入,下面将android4.4的wifi相关部分启动代码流程做如下分析:

软件平台:Android4.4

硬件平台:MTK6572


WifiService作为wifi的主service,也是从SystemServer的initAndLoop中启动:

    public void initAndLoop() {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN,
            SystemClock.uptimeMillis());
        /// M: BOOTPROF @{
        mMTPROF_disable = "1".equals(SystemProperties.get("ro.mtprof.disable"));
        addBootEvent(new String("Android:SysServerInit_START"));
        /// @}
        Looper.prepareMainLooper();
        ......

               try {
                    Slog.i(TAG, "Wi-Fi Service");
                    wifi = new WifiService(context);
                    ServiceManager.addService(Context.WIFI_SERVICE, wifi);
                } catch (Throwable e) {
                    reportWtf("starting Wi-Fi Service", e);
                }

         ......
}
根据代码我们得知调到了WifiService的构造函数中:
    public WifiService(Context context) {
        mContext = context;

        mInterfaceName =  SystemProperties.get("wifi.interface", "wlan0");

        mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);
        mWifiStateMachine.enableRssiPolling(true);
        mBatteryStats = BatteryStatsService.getService();
        mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);

        mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);
        mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);
        mSettingsStore = new WifiSettingsStore(mContext);

        HandlerThread wifiThread = new HandlerThread("WifiService");
        wifiThread.start();
        mClientHandler = new ClientHandler(wifiThread.getLooper());
        mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
        mWifiController = new WifiController(mContext, this, wifiThread.getLooper());
        mWifiController.start();

        mBatchedScanSupported = mContext.getResources().getBoolean(
                R.bool.config_wifi_batched_scan_supported);

        registerForScanModeChange();
        mContext.registerReceiver(
                new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        ///M: modify for timing issue to access Settings.Global.AIRPLANE_MODE_ON
                        boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
                        SXlog.i(TAG, "ACTION_AIRPLANE_MODE_CHANGED isAirplaneModeOn="+isAirplaneModeOn);

                        if (mSettingsStore.handleAirplaneModeToggled(isAirplaneModeOn)) {

                            mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
                        }
                    }
                },
                new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));

        // Adding optimizations of only receiving broadcasts when wifi is enabled
        // can result in race conditions when apps toggle wifi in the background
        // without active user involvement. Always receive broadcasts.
        registerForBroadcasts();

        ///M:
        initializeExtra();
    }

该构造函数首先是实例化一个WifiStateMachine,这个构造方法我们后续再做详细说明,之后创建了wifiThread线程,并调用了start方法开始执行此线程(实则是开启了Looper模式,java中每一个thread只能有一个Looper,一个Looper可以包含多个Handler和MQ,每一个Handler在添加到线程的Looper中时也都有自己相应的MQ,这样线程中的MQ就会按顺序的处理消息然后发送给与之绑定的Handler去处理msg),紧接着是把ClientHandler,WifiStateMachineHandler都添加到Looper中,后续实例化一个WifiController,并调用start,为什么它也有start?因为它继承自StateMachine。

接下来,WifiController的构造方法:

    WifiController(Context context, WifiService service, Looper looper) {
        super(TAG, looper);
        mContext = context;
        mWifiStateMachine = service.mWifiStateMachine;
        ......
        addState(mDefaultState);
            addState(mApStaDisabledState, mDefaultState);
            addState(mStaEnabledState, mDefaultState);
                addState(mDeviceActiveState, mStaEnabledState);
                addState(mDeviceInactiveState, mStaEnabledState);
                    addState(mScanOnlyLockHeldState, mDeviceInactiveState);
                    addState(mFullLockHeldState, mDeviceInactiveState);
                    addState(mFullHighPerfLockHeldState, mDeviceInactiveState);
                    addState(mNoLockHeldState, mDeviceInactiveState);
            addState(mStaDisabledWithScanState, mDefaultState);
            addState(mApEnabledState, mDefaultState);
            addState(mEcmState, mDefaultState);
        if (mSettingsStore.isScanAlwaysAvailable()) {
            setInitialState(mStaDisabledWithScanState);
        } else {
            setInitialState(mApStaDisabledState);
        }
        setLogRecSize(100);
        setLogOnlyTransitions(false);

        IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_DEVICE_IDLE);
        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        mContext.registerReceiver(
                new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        String action = intent.getAction();
                        if (action.equals(ACTION_DEVICE_IDLE)) {
                            sendMessage(CMD_DEVICE_IDLE);
                        } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                            mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
                                    WifiManager.EXTRA_NETWORK_INFO);
                        }
                    }
                },
                new IntentFilter(filter));

        initializeAndRegisterForSettingsChange(looper);
    }

将wifiservice中实例化的状态机赋值给本地状态机,然后调用addState方法添加了一系列的父子状态机状态,根据后续的if-else逻辑我们不难发现状态机被初始化为mApStaDisabledState状态(记住这是状态机第一个暂留的状态)。WifiController先说明到此,这一步主要的就是第一个初始化的状态机状态。

回过头我们继续看WifiService构造方法中的registerForBroadcast()方法:

    private void registerForBroadcasts() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
        intentFilter.addAction(Intent.ACTION_USER_PRESENT);
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
        intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
        mContext.registerReceiver(mReceiver, intentFilter);
    }
这其中有一个对ACTION_SCREEN_ON事件的广播侦听,在收到该广播之后:

            if (action.equals(Intent.ACTION_SCREEN_ON)) {
                mWifiController.sendMessage(CMD_SCREEN_ON);

向WifiController发送了CMD_SCREEN_ON的MSG,然后我们回到WifiController,在上一步将WifiController的时候,我们记住了一个状态:mApStaDisabledState,该MSG就是发送给了这个状态的processMessage()方法,然并卵,我们在此方法中并未看到对CMD_SCREEN_ON的处理,根据状态机的特点,我们看该状态的父状态有没有做处理。父状态为DefaultState,这里边果然有处理该消息的逻辑:

                case CMD_SCREEN_ON:
                    mAlarmManager.cancel(mIdleIntent);
                    mScreenOff = false;
                    mDeviceIdle = false;
                    ///M: @{
                    mWifiStateMachine.setDeviceIdle(mDeviceIdle);
                    ///@}
                    updateBatteryWorkSource();
                    break;

这里边我们着重记住一个变量的赋值,mDeviceIdle = false;后面我们继续WifiService的构造方法:

        mContext.registerReceiver(
                new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        ///M: modify for timing issue to access Settings.Global.AIRPLANE_MODE_ON
                        boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
                        SXlog.i(TAG, "ACTION_AIRPLANE_MODE_CHANGED isAirplaneModeOn="+isAirplaneModeOn);

                        if (mSettingsStore.handleAirplaneModeToggled(isAirplaneModeOn)) {

                            mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
                        }
                    }
                },
                new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));

这里注册了一个捕捉ACTION_AIRPLANE_MODE_CHANGED的广播,接收到这个广播后,通过mWifiController发送一个CMD_AIRPLANE_TOGGLED的消息,来看看接收到这个消息的地方,还是在WifiController的当前状态mApStaDisabledState实现类的 processMessage方法中:

                case CMD_AIRPLANE_TOGGLED:
                    ///M: add WifiIpoOff@{
                    boolean wifiIpoOff = (msg.arg1==1) ? true: false;
                    boolean ipoStateChange= false;
                    if(mWifiIpoOff!=wifiIpoOff) ipoStateChange=true;
                    mWifiIpoOff = wifiIpoOff;
                    if(wifiIpoOff ==true){
                        SXlog.d(TAG,"ipooff  don't enable wifi\n");
                        break;
                    }
                    if (mSettingsStore.isWifiToggleEnabled()) {
                    //@}
                        if (doDeferEnable(msg)) {
                            if (mHaveDeferredEnable) {
                                //  have 2 toggles now, inc serial number an ignore both
                                mDeferredEnableSerialNumber++;
                            }
                            mHaveDeferredEnable = !mHaveDeferredEnable;
                            break;
                        }
                       if (mDeviceIdle == false) {
                            transitionTo(mDeviceActiveState);
                        } else {
                            checkLocksAndTransitionWhenDeviceIdle();
                        }
                    ///M: check scan always avaliable only when ipo change from ipo on to off
                    } else if (ipoStateChange ==true && mSettingsStore.isScanAlwaysAvailable() && mSettingsStore.isAirplaneModeOn()==false ) {
                        SXlog.d(TAG,"ipoStateChange = "+ipoStateChange + "isAirplaneModeOn= "+mSettingsStore.isAirplaneModeOn());
                        transitionTo(mStaDisabledWithScanState);
                    }
                    break;
注意当中对mDeviceIdle的判断,之前确定了该值为false,因此这个时候涉及到一个状态机状态的切换,切换至mDeviceActiveState,首先是进入该状态机的父状态机,StaEnabledState,此状态的enter方法如下:

        @Override
        public void enter() {
            if (DBG) log(getName() + "\n");
            mWifiStateMachine.setSupplicantRunning(true);
        }

调用setSupplicantRunning(true),

    public void setSupplicantRunning(boolean enable) {
        if (enable) {
            sendMessage(CMD_START_SUPPLICANT);
        } else {
            sendMessage(CMD_STOP_SUPPLICANT);
        }    
    }  
发出了一个CMD_START_SUPPLICANT的MSG,那么当前WifiStateMachine处于什么状态呢?我们切看一开始滞后解析的WifiStateMachine构造方法,状态机最初始暂存的一个状态是
        setInitialState(mInitialState);
也就是InitialState状态的processMessage处理CMD_START_SUPPLICANT消息,

                case CMD_START_SUPPLICANT:
                    setWifiState(WIFI_STATE_ENABLING);
                    if (mWifiNative.loadDriver()) {
                        try {
                            mNwService.wifiFirmwareReload(mInterfaceName, "STA");
                        } catch (Exception e) {
                            loge("Failed to reload STA firmware " + e);
                            // continue
                        }

                        try {
                            // A runtime crash can leave the interface up and
                            // this affects connectivity when supplicant starts up.
                            // Ensure interface is down before a supplicant start.
                            mNwService.setInterfaceDown(mInterfaceName);
                            // Set privacy extensions
                            mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);

                           // IPv6 is enabled only as long as access point is connected since:
                           // - IPv6 addresses and routes stick around after disconnection
                           // - kernel is unaware when connected and fails to start IPv6 negotiation
                           // - kernel can start autoconfiguration when 802.1x is not complete
                            mNwService.disableIpv6(mInterfaceName);
                        } catch (RemoteException re) {
                            loge("Unable to change interface settings: " + re);
                        } catch (IllegalStateException ie) {
                            loge("Unable to change interface settings: " + ie);
                        }

                       /* Stop a running supplicant after a runtime restart
                        * Avoids issues with drivers that do not handle interface down
                        * on a running supplicant properly.
                        */
                        mWifiMonitor.killSupplicant(mP2pSupported);
                        if(mWifiNative.startSupplicant(mP2pSupported)) {

                            if (DBG) log("Supplicant start successful");
                            mWifiMonitor.startMonitoring();
                            transitionTo(mSupplicantStartingState);
                        } else {
                            loge("Failed to start supplicant!");
                        }
                    } else {
                        loge("Failed to load driver");
                    }
                    break;
调用WifiNative的loadDriver方法,该方法定义在frameworks/base/core/jni/android_net_wifi_WifiNative.cpp中:

static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
{
    ///M:@{
    g_pItemListMutex = new pthread_mutex_t;
    if (NULL == g_pItemListMutex) {
        XLOGE("Failed to allocate memory for g_pItemListMutex!");
        return JNI_FALSE;
    }   
    pthread_mutex_init(g_pItemListMutex, NULL);
    g_pCurrentSSID = new String8();
    if (NULL == g_pCurrentSSID) {
        XLOGE("Failed to allocate memory for g_pCurrentSSID!");
        return JNI_FALSE;
    }   
    char dbg[PROPERTY_VALUE_MAX] = {0};
    if (property_get("wifi.jni.dbg", dbg, NULL) && strcmp(dbg, "true") == 0) {
        DBG = true;
    } else {
        DBG = false;
    }   
    ///@}
    return (::wifi_load_driver() == 0); 
}
最后调到了hardware层的wifi.c中的接口:hardware/libhardware_legacy/wifi/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 */

    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
    ALOGD("enter -->%s\n, uid=%d, gid=%d", __func__, getuid(), getgid());
    property_set(DRIVER_PROP_NAME, "ok");
    /*fix wifi_send_commadn bug*/
    wifi_init_sync(&wifi_sync);
    return 0;
#endif
}
调用insmod方法去loading相应path的ko文件,成功的话设置相应的property,返回0,失败的话返回-1。
回到WifiStateMachine的CMD_START_SUPPLICANT的处理,在load完driver之后,会开启wpa服务。

               mWifiMonitor.killSupplicant(mP2pSupported);
                        if(mWifiNative.startSupplicant(mP2pSupported)) {

                            if (DBG) log("Supplicant start successful");
                            mWifiMonitor.startMonitoring();
                            transitionTo(mSupplicantStartingState);
                        } else {
                            loge("Failed to start supplicant!");
                        }

调用WifiNative的接口,间接调用hardware层的wifi_start_supplicant方法,该方法在此不再赘述,只是通过property设置开启spa_supplicant service。之后是调用WifiMonitor的startMonitoring方法,并把状态机切换至mSupplicantStartingState状态:

        public synchronized void startMonitoring(String iface) {
            WifiMonitor m = mIfaceMap.get(iface);
            if (m == null) {
                Log.e(TAG, "startMonitor called with unknown iface=" + iface);
                return;
            }    

            Log.d(TAG, "startMonitoring(" + iface + ") with mConnected = " + mConnected);

            if (mConnected) {
                m.mMonitoring = true;
                m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT);
            } else {
                if (DBG) Log.d(TAG, "connecting to supplicant");
                int connectTries = 0; 
                while (true) {
                    if (mWifiNative.connectToSupplicant()) {
                        m.mMonitoring = true;
                        m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT);
                        new MonitorThread(mWifiNative, this).start();
                        mConnected = true;
                        break;
                    }    
                    if (connectTries++ < 5) { 
                        try {
                            Thread.sleep(1000);
                       } catch (InterruptedException ignore) {
                        }
                    } else {
                    Log.d(TAG, "rmIfaceMap remove " + iface);
                        mIfaceMap.remove(iface);
                        ///M:@{
                        if (!m.mInterfaceName.equals("ap0")) {
                            m.mWifiStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
                        }
                        ///@}
                        Log.e(TAG, "startMonitoring(" + iface + ") failed! " );
                        break;
                    }
                }
            }
        }
第一次执行,mConnected为false,走else通路,调用WifiNative.connectToSupplicant()方法,继而到hal层wifi_connect_to_supplicant()方法,此方法最终调用到了 wpa层的代码:wpa_ctl_open打开了两个连接:ctrl_conn和monitor_conn。

后边开启一个MonitorThread,我们看一下这个构造方法:

        public MonitorThread(WifiNative wifiNative, WifiMonitorSingleton wifiMonitorSingleton) {
            super("WifiMonitor");
            mWifiNative = wifiNative;
            mWifiMonitorSingleton = wifiMonitorSingleton;
        }    
没有什么实质功能性实现,下面我们看其run方法:

        public void run() {
            //noinspection InfiniteLoopStatement
            for (;;) {
                String eventStr = mWifiNative.waitForEvent();

                // Skip logging the common but mostly uninteresting scan-results event
                if (DBG && eventStr.indexOf(SCAN_RESULTS_STR) == -1) {
                    Log.d(TAG, "Event [" + eventStr + "]");
                }

                String iface = "p2p0";
                WifiMonitor m = null;
                mStateMachine = null;

                if (eventStr.startsWith("IFNAME=")) {
                    int space = eventStr.indexOf(' ');
                    if (space != -1) {
                        iface = eventStr.substring(7,space);
                        Log.d(TAG, "iface " + iface);
                        m = mWifiMonitorSingleton.getMonitor(iface);
                        if(m==null)Log.d(TAG, "hcan get mm  " + iface);
                        if (m == null && iface.startsWith("p2p-")) {
                            // p2p interfaces are created dynamically, but we have
                            // only one P2p state machine monitoring all of them; look
                            // for it explicitly, and send messages there ..
                            m = mWifiMonitorSingleton.getMonitor("p2p0");
                        }
                        eventStr = eventStr.substring(space + 1);
                    }
                } else {
                    ///M: if ap0 exist, it could be hotspot event

                    m = mWifiMonitorSingleton.getMonitor("ap0");
                    if(m!=null){
                        if(m.mMonitoring){
                            //we find hotspot active
                        }else{
                            //try p2p0
                            m = mWifiMonitorSingleton.getMonitor("p2p0");
                        }
                     }else{
                        // events without prefix belong to p2p0 monitor
                        m = mWifiMonitorSingleton.getMonitor("p2p0");
                     }
                }

                if (m != null) {
                    if (m.mMonitoring) {
                        mStateMachine = m.mWifiStateMachine;
                    } else {
                        if (DBG) Log.d(TAG, "Dropping event because monitor (" + iface +
                                            ") is stopped");
                        continue;
                    }
                }

                if (mStateMachine != null) {
                    if (dispatchEvent(eventStr, m.mInterfaceName)) {
                        //M: when dispatchEvent=true means break from waitForEvent
                        //M: for hotspot clear hotspot data
                        if(m.mInterfaceName.equals("ap0")){
                            m.mMonitoring =false;
                            mWifiNative.closeSupplicantConnection();
                            Log.d(TAG, "ap0 get TEMINATING 1");
                        }
                        break;
                    }
                } else {
                    if (DBG) Log.d(TAG, "Sending to all monitors because there's no interface id");
                    boolean done = false;
                    Iterator<Map.Entry<String, WifiMonitor>> it =
                            mWifiMonitorSingleton.mIfaceMap.entrySet().iterator();
                    while (it.hasNext()) {
                        Map.Entry<String, WifiMonitor> e = it.next();
                        m = e.getValue();
                        mStateMachine = m.mWifiStateMachine;
                        if (dispatchEvent(eventStr,null)) {
                            done = true;
                        }
                    }

                    if (done) {

                        //M: for hotspot clear hotspot data
                        if(m.mInterfaceName.equals("ap0")){
                            m.mMonitoring =false;
                            mWifiNative.closeSupplicantConnection();
                            Log.d(TAG, "ap0 get TEMINATING 2");
                        }

                        // After this thread terminates, we'll no longer
                        // be connected to the supplicant
                        if (DBG) Log.d(TAG, "Disconnecting from the supplicant, no more events");
                        mWifiMonitorSingleton.mConnected = false;
                        break;
                    }
                }
            }
        }
这里调用了WifiNative的waitForEvent方法,这个方法通过jni调用本地方法读取wpa_supplicant的消息,并转发出去。

                    while (it.hasNext()) {
                        Map.Entry<String, WifiMonitor> e = it.next();
                        m = e.getValue();
                        mStateMachine = m.mWifiStateMachine;
                        if (dispatchEvent(eventStr,null)) {
                            done = true;
                        }
                    }
后面dispatchEvent的实现:

        /* @return true if the event was supplicant disconnection */
        private boolean dispatchEvent(String eventStr, String iface) {

            if (!eventStr.startsWith(EVENT_PREFIX_STR)) {
                if ((eventStr.startsWith(WPA_EVENT_PREFIX_STR) &&
                        0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR))
                        ///M:@{
                        || (eventStr.startsWith(AUTHENTICATION_TIMEOUT_PREFIX_STR)
                            && 0 < eventStr.indexOf(AUTHENTICATION_TIMEOUT_STR))) {
                        ///@}
                    mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
                } else if (eventStr.startsWith(WPS_SUCCESS_STR)) {
                    mStateMachine.sendMessage(WPS_SUCCESS_EVENT);
                } else if (eventStr.startsWith(WPS_FAIL_STR)) {
                    handleWpsFailEvent(eventStr);
                } else if (eventStr.startsWith(WPS_OVERLAP_STR)) {
                    mStateMachine.sendMessage(WPS_OVERLAP_EVENT);
                } else if (eventStr.startsWith(WPS_TIMEOUT_STR)) {
                    mStateMachine.sendMessage(WPS_TIMEOUT_EVENT);
                } else if (eventStr.startsWith(P2P_EVENT_PREFIX_STR)) {
                    handleP2pEvents(eventStr);
                } else if (eventStr.startsWith(HOST_AP_EVENT_PREFIX_STR)) {
                    handleHostApEvents(eventStr, iface);
                ///M:@{
                } else if (eventStr.startsWith(EAP_FAST_NEW_PAC_UPDATED)) {
                    mStateMachine.sendMessage(NEW_PAC_UPDATED_EVENT);
                ///M: whole chip reset fail
                } else if (eventStr.startsWith(WHOLE_CHIP_RESET_FAIL_STRING)){
                    mStateMachine.sendMessage(WHOLE_CHIP_RESET_FAIL_EVENT);
                /** M: NFC Float II @{ */
                } else if (eventStr.startsWith(WPS_ER_ENROLLEE_ADD_STR)) {
                    mStateMachine.sendMessage(WPS_ER_ENROLLEE_ADD_EVENT, eventStr);
                } else if (eventStr.startsWith(WPS_ER_AP_ADD_STR)) {
                    mStateMachine.sendMessage(WPS_ER_AP_ADD_EVENT, eventStr);
                /** } */
                }
                ///@}
                else {
                    if (DBG) Log.w(TAG, "couldn't identify event type - " + eventStr);
                }
                return false;
            }

            String eventName = eventStr.substring(EVENT_PREFIX_LEN_STR);
            int nameEnd = eventName.indexOf(' ');
            if (nameEnd != -1)
                eventName = eventName.substring(0, nameEnd);
            if (eventName.length() == 0) {
                if (DBG) Log.i(TAG, "Received wpa_supplicant event with empty event name");
                return false;
            }
            /*
             * Map event name into event enum
             */
            int event;
            if (eventName.equals(CONNECTED_STR))
                event = CONNECTED;
            else if (eventName.equals(DISCONNECTED_STR)) {
                event = DISCONNECTED;
                ///M: add
                handleP2pEvents(eventStr);
            } else if (eventName.equals(STATE_CHANGE_STR))
                event = STATE_CHANGE;
            else if (eventName.equals(SCAN_RESULTS_STR))
                event = SCAN_RESULTS;
            else if (eventName.equals(LINK_SPEED_STR))
                event = LINK_SPEED;
            else if (eventName.equals(TERMINATING_STR))
                event = TERMINATING;
            else if (eventName.equals(DRIVER_STATE_STR))
                event = DRIVER_STATE;
            else if (eventName.equals(EAP_FAILURE_STR))
                event = EAP_FAILURE;
            else if (eventName.equals(ASSOC_REJECT_STR))
                event = ASSOC_REJECT;
            ///M:@{
                                          else if (eventName.equals(WAPI_NO_CERTIFICATION_STRING))
                event = NO_CERTIFICATION;
            ///@}
            else
                event = UNKNOWN;

            String eventData = eventStr;
            if (event == DRIVER_STATE || event == LINK_SPEED)
                eventData = eventData.split(" ")[1];
            else if (event == STATE_CHANGE || event == EAP_FAILURE) {
                int ind = eventStr.indexOf(" ");
                if (ind != -1) {
                    eventData = eventStr.substring(ind + 1);
                }
            } else {
                int ind = eventStr.indexOf(" - ");
                if (ind != -1) {
                    eventData = eventStr.substring(ind + 3);
                }
            }
            if (event == STATE_CHANGE) {
                handleSupplicantStateChange(eventData);
            } else if (event == DRIVER_STATE) {
                handleDriverEvent(eventData);
            } else if (event == TERMINATING) {
                Log.d(TAG, "event == TERMINATING " );
                /**
                 * Close the supplicant connection if we see
                 * too many recv errors
                 */
                if (eventData.startsWith(WPA_RECV_ERROR_STR)) {
                    if (++mRecvErrors > MAX_RECV_ERRORS) {
                        if (DBG) {
                            Log.d(TAG, "too many recv errors, closing connection");
                        }
                    } else {
                        return false;
                    }
                }

                // notify and exit
                if(iface!=null && !iface.equals("ap0")){
                    mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
                }
                Log.d(TAG, "Exit because of receiving terminating for " + getName() + ", id:" + getId());
                return true;
            } else if (event == EAP_FAILURE) {
                if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) {
                    mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
                }
            } else if (event == ASSOC_REJECT) {
                mStateMachine.sendMessage(ASSOCIATION_REJECTION_EVENT);
            } else {
                handleEvent(event, eventData);
            }
            mRecvErrors = 0;
            return false;
        }

经过一系列处理调用handleEvent方法,
        void handleEvent(int event, String remainder) {
            switch (event) {
                case DISCONNECTED:
                    handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED, remainder);
                    break;

                case CONNECTED:
                    handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED, remainder);
                    break;

                case SCAN_RESULTS:
                    mStateMachine.sendMessage(SCAN_RESULTS_EVENT);
                    break;
                ///M: @{
                case NO_CERTIFICATION:
                    mStateMachine.sendMessage(WAPI_NO_CERTIFICATION_EVENT);
                    break;
                ///@}
                case UNKNOWN:
                    break;
            }
        }

以SCAN_RESULTS 为例,状态机发送SCAN_RESULTS_EVENT消息,这个状态机为WifiStateMachine对象,状态机此时为SupplicantStartedState,看下该状态下的processMessage方法:

                case WifiMonitor.SCAN_RESULTS_EVENT:
                    setScanResults();
                    if (mWifiFwkExt.hasCustomizedAutoConnect()) {
                        mShowReselectDialog = false;
                        Xlog.d(TAG, "SCAN_RESULTS_EVENT, mScanForWeakSignal:" + mScanForWeakSignal);
                        if (mScanForWeakSignal) {
                            showReselectionDialog();
                        }    
                        mDisconnectNetworkId = INVALID_NETWORK_ID;
                    }    

                    sendScanResultsAvailableBroadcast();
                    mScanResultIsPending = false;
                    break;

这里会把扫描的结果以广播的形式发送给接受者,sendScanResultsAvailableBroadcast()方法:

    private void sendScanResultsAvailableBroadcast() {
        noteScanEnd();
        Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        intent.putExtra(IWifiFwkExt.EXTRA_SHOW_RESELECT_DIALOG_FLAG, mShowReselectDialog);
        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
    }
至此,大体流程结束。。。













  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值