wifi 启动流程

系统启动时,会在SystemServer中创建一个WifiService的对象,并把这个对象保存在系统服务中

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

看看WiFiService的构造方法

public WifiService(Context context) {
        mContext = context;
 
        mInterfaceName =  SystemProperties.get("wifi.interface", "wlan0");
 
        <span style="color:#FF0000;">mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);</span>
        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());
        <span style="color:#FF0000;">mWifiController = new WifiController(mContext, this, wifiThread.getLooper());</span>
        <span style="color:#FF0000;">mWifiController.start();</span>
 
        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和一个WifiController,并且调用了WifiController 的start方法,WifiController 继承至StateMachine状态机,

class WifiController extends StateMachine {

我们先来看看WifiController这个状态机的构造方法

WifiController(Context context, <span style="color:#FF0000;">WifiService service</span>, Looper looper) {
        super(TAG, looper);
        mContext = context;
       <span style="color:#FF0000;"> mWifiStateMachine = service.mWifiStateMachine;</span>
        mSettingsStore = service.mSettingsStore;
        mLocks = service.mLocks;
        mWifiCsmClient = service.mWifiCsmClient;

        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
        Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
        mIdleIntent = PendingIntent.getBroadcast(mContext, IDLE_REQUEST, idleIntent, 0);
<span style="color:#FF0000;">
        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);</span>

        boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();
        boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();
        boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();

        log("isAirplaneModeOn = " + isAirplaneModeOn +
                ", isWifiEnabled = " + isWifiEnabled +
                ", isScanningAvailable = " + isScanningAlwaysAvailable);

        if (isWifiEnabled && isScanningAlwaysAvailable) {
            setInitialState(mStaDisabledWithScanState);
        } else {
           <span style="color:#FF0000;"> setInitialState(mApStaDisabledState);</span>
        }

        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));
        mContext.registerReceiver(
                new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        ArrayList<String> active = intent.getStringArrayListExtra(
                                ConnectivityManager.EXTRA_ACTIVE_TETHER);
                        if (active != null) updateTetherUsbState(active);
                    }
                },new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));

        initializeAndRegisterForSettingsChange(looper);
    }

这里参数service就是WifiService,并且通过service得到了WifiService中的WifiStateMachine对象,然后添加了一些状态对象,设置了初始状态,

这个start方法是父类的方法,表示启动一个状态机。

    /**
     * Start the state machine.
     */
    public void start() {
        // mSmHandler can be null if the state machine has quit.
        SmHandler smh = mSmHandler;
        if (smh == null) return;

        /*Complete the construction of the state machine, Send the complete construction message */
        smh.completeConstruction(); 
    }

调用start方法后,WifiController首先进入mDefaultState状态,然后进入mApStaDisabledState状态(先父状态后子状态),此时,WifiController状态机的状态为mApStaDisabledState状态。

让我们回到WifiService的构造方法中,倒数第二行有个registerForBroadcasts方法

registerForBroadcasts();

    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);
        intentFilter.addAction(WifiStateMachine.SHUT_DOWN_WIFI_ACTION);
        intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
        mContext.registerReceiver(mReceiver, intentFilter);
    }

这个方法注册了一个广播,那我们看看接收到注册的这些action后,会有哪些处理

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(<span style="color:#FF0000;">Intent.ACTION_SCREEN_ON</span>)) {
                mWifiController.sendMessage(CMD_SCREEN_ON);
            } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
                mWifiController.sendMessage(CMD_USER_PRESENT);
            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
                mWifiController.sendMessage(CMD_SCREEN_OFF);
            } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                int pluggedType = intent.getIntExtra("plugged", 0);
                mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null);
            } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
                        BluetoothAdapter.STATE_DISCONNECTED);
                mWifiStateMachine.sendBluetoothAdapterStateChange(state);
            } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
                boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false);
                mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0);
            } else if (action.equals(WifiStateMachine.SHUT_DOWN_WIFI_ACTION)) {
                mWifiController.sendMessage(CMD_DEVICE_IDLE);
            } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
                String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
                if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)) {
                    if (DBG) Slog.d(TAG, "SIM Card inserted");
                    updateIccNetworks(true);
                } else if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)
                        || IccCardConstants.INTENT_VALUE_ICC_NOT_READY.equals(stateExtra)) {
                    if (DBG) Slog.d(TAG, "SIM Card removed or not ready");
                    updateIccNetworks(false);
                }
            }
        }
    };
当接收到的广播为ACTION_SCREEN_ON时,利用mWifiController对象发送一个CMD_SCREEN_ON消息,此时,mWifiController状态机的状态为mApStaDisabledState状态,我们看看这个状态实现类的processMessage方法子状态没处理的消息,将由父状态处理,mApStaDisabledState的父状态为mDefaultState状态,看看它的processMessage方法
class DefaultState extends State {
        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                case CMD_SCREEN_ON:
                    mAlarmManager.cancel(mIdleIntent);
                    mScreenOff = false;
                    mDeviceIdle = false;
                    updateBatteryWorkSource();
                    break;
                case CMD_SCREEN_OFF:
                    mScreenOff = true;
                    /*
                    * Set a timer to put Wi-Fi to sleep, but only if the screen is off
                    * AND the "stay on while plugged in" setting doesn't match the
                    * current power conditions (i.e, not plugged in, plugged in to USB,
                    * or plugged in to AC).
                    */
                    if (!shouldWifiStayAwake(mPluggedType)) {
                     // Apply sleep policy only if usb tethering is disabled
                        if (!mTetherUsbOn) {
                            //Delayed shutdown if wifi is connected
                            if (mNetworkInfo.getDetailedState() ==
                                    NetworkInfo.DetailedState.CONNECTED) {
                                if (DBG) Slog.d(TAG, "set idle timer: " + mIdleMillis + " ms");
                                mAlarmManager.set(AlarmManager.RTC_WAKEUP,
                                        System.currentTimeMillis() + mIdleMillis, mIdleIntent);
                            } else {
                                sendMessage(CMD_DEVICE_IDLE);
                            }
                        }
                    }
                    break;
                case CMD_DEVICE_IDLE:
                    mDeviceIdle = true;
                    updateBatteryWorkSource();
                    break;
                case CMD_BATTERY_CHANGED:
                    /*
                    * Set a timer to put Wi-Fi to sleep, but only if the screen is off
                    * AND we are transitioning from a state in which the device was supposed
                    * to stay awake to a state in which it is not supposed to stay awake.
                    * If "stay awake" state is not changing, we do nothing, to avoid resetting
                    * the already-set timer.
                    */
                    int pluggedType = msg.arg1;
                    if (DBG) Slog.d(TAG, "battery changed pluggedType: " + pluggedType);
                    if (mScreenOff && shouldWifiStayAwake(mPluggedType) &&
                            !shouldWifiStayAwake(pluggedType)) {
                        long triggerTime = System.currentTimeMillis() + mIdleMillis;
                        if (mNetworkInfo.getDetailedState() == DetailedState.CONNECTED
                                && !mTetherUsbOn) {
                            if (DBG) Slog.d(TAG, "set idle timer for " + mIdleMillis + "ms");
                            mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
                        } else {
                            sendMessage(CMD_DEVICE_IDLE);
                        }
                    }

                    mPluggedType = pluggedType;
                    break;
                case CMD_SET_AP:
                case CMD_SCAN_ALWAYS_MODE_CHANGED:
                case CMD_LOCKS_CHANGED:
                case CMD_WIFI_TOGGLED:
                case CMD_AIRPLANE_TOGGLED:
                case CMD_EMERGENCY_MODE_CHANGED:
                    break;
                case CMD_USER_PRESENT:
                    mFirstUserSignOnSeen = true;
                    break;
                case CMD_DEFERRED_TOGGLE:
                    log("DEFERRED_TOGGLE ignored due to state change");
                    break;
                default:
                    throw new RuntimeException("WifiController.handleMessage " + msg.what);
            }
            return HANDLED;
        }

    }
再一次回到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(<span style="color:#FF0000;">Intent.ACTION_AIRPLANE_MODE_CHANGED</span>));
这里注册了一个捕捉ACTION_AIRPLANE_MODE_CHANGED的广播,接收到这个广播后,通过mWifiController发送一个CMD_AIRPLANE_TOGGLED的消息,来看看接收到这个消息的地方,还是在WifiController的当前状态mApStaDisabledState实现类的 processMessage方法中
public boolean processMessage(Message msg) {
            switch (msg.what) {
                case CMD_WIFI_TOGGLED:
                case <span style="color:#FF0000;">CMD_AIRPLANE_TOGGLED</span>:
                    if (mSettingsStore.isWifiToggleEnabled()) {
                        if (doDeferEnable(msg)) {
                            if (mHaveDeferredEnable) {
                                //  have 2 toggles now, inc serial number an ignore both
                                mDeferredEnableSerialNumber++;
                            }
                            mHaveDeferredEnable = !mHaveDeferredEnable;
                            break;
                        }
                      <span style="color:#FF0000;">  if (mDeviceIdle == false) {
                            transitionTo(mDeviceActiveState);</span>
                        } else {
                            checkLocksAndTransitionWhenDeviceIdle();
                        }
                    }
                    else{ // wifi is Off, check Scan state
                        if (mSettingsStore.isScanAlwaysAvailable()) {
                            transitionTo(mStaDisabledWithScanState);
                        }
                    }
                    break;
                case CMD_SCAN_ALWAYS_MODE_CHANGED:
                    if (mSettingsStore.isScanAlwaysAvailable()) {
                        transitionTo(mStaDisabledWithScanState);
                    }
                    break;
                case CMD_SET_AP:
                    if (msg.arg1 == 1) {
                        mWifiStateMachine.setHostApRunning((WifiConfiguration) msg.obj,
                                true);
                        transitionTo(mApEnabledState);
                    }
                    break;
                case CMD_DEFERRED_TOGGLE:
                    if (msg.arg1 != mDeferredEnableSerialNumber) {
                        log("DEFERRED_TOGGLE ignored due to serial mismatch");
                        break;
                    }
                    log("DEFERRED_TOGGLE handled");
                    sendMessage((Message)(msg.obj));
                    break;
                default:
                    return NOT_HANDLED;
            }
            return HANDLED;
        }
当系统Wifi为开时,并且mDeviceIdle为false时,会把当前状态转换为mDeviceActiveState状态,mDeviceActiveState的父状态为mStaEnabledState状态,所以会先进入mStaEnabledState然后进入mDeviceActiveState状态,我们看看mStaEnabledState状态的实现类的enter方法

    class StaEnabledState extends State {
        @Override
        public void enter() {
            <span style="color:#FF0000;">mWifiStateMachine.setSupplicantRunning(true);</span>
        }
这里调用了WifiService中的WifiStateMachine对象的setSupplicantRunning方法

public void setSupplicantRunning(boolean enable) {
       if (enable) {
           sendMessage(CMD_START_SUPPLICANT);
       } else {
           sendMessage(CMD_STOP_SUPPLICANT);
       }
   }
当参数为true时,发送一个CMD_START_SUPPLICANT消息,那么WifiStateMachine当前的状态是什么呢?看看它的构造方法吧,其中添加状态和初始状态的代码为

addState(mDefaultState);
            addState(mInitialState, mDefaultState);
            addState(mSupplicantStartingState, mDefaultState);
            addState(mSupplicantStartedState, mDefaultState);
                addState(mDriverStartingState, mSupplicantStartedState);
                addState(mDriverStartedState, mSupplicantStartedState);
                    addState(mScanModeState, mDriverStartedState);
                    addState(mConnectModeState, mDriverStartedState);
                        addState(mL2ConnectedState, mConnectModeState);
                            addState(mObtainingIpState, mL2ConnectedState);
                            addState(mVerifyingLinkState, mL2ConnectedState);
                            addState(mCaptivePortalCheckState, mL2ConnectedState);
                            addState(mConnectedState, mL2ConnectedState);
                        addState(mDisconnectingState, mConnectModeState);
                        addState(mDisconnectedState, mConnectModeState);
                        addState(mWpsRunningState, mConnectModeState);
                addState(mWaitForP2pDisableState, mSupplicantStartedState);
                addState(mDriverStoppingState, mSupplicantStartedState);
                addState(mDriverStoppedState, mSupplicantStartedState);
            addState(mSupplicantStoppingState, mDefaultState);
            addState(mSoftApStartingState, mDefaultState);
            addState(mSoftApStartedState, mDefaultState);
                addState(mTetheringState, mSoftApStartedState);
                addState(mTetheredState, mSoftApStartedState);
                addState(mUntetheringState, mSoftApStartedState);
 
        <span style="color:#FF0000;">setInitialState(mInitialState);</span>
初始状态为mInitialState,看看它的实现类的processMessage方法

public boolean processMessage(Message message) {
            switch (message.what) {
                case <span style="color:#FF0000;">CMD_START_SUPPLICANT</span>:
                    if (mWifiNative.<span style="color:#FF0000;">loadDriver</span>()) {
                        try {
                            mNwService.wifiFirmwareReload(mInterfaceName, "STA");
                        } catch (Exception e) {
                            loge("Failed to reload STA firmware " + e);
                            // continue
                        }

                        try {
                       /* Stop a running supplicant after a runtime restart
                        * Avoids issues with drivers that do not handle interface down
                        * on a running supplicant properly.
                        */
                       if (DBG) log("Kill any running supplicant");
                       mWifiNative.killSupplicant(mP2pSupported);
                       // A runtime crash can leave the interface up and
                       // this affects connectivity when supplicant starts up.
                       // Ensure interface is down before a supplicant start.
                        if (mP2pSupported) {
                            // Ensure  p2p and p2p-p20-X interfaces are down
                            if (DBG) log("Set P2P interfaces down");
                            String[] ifaces = new String[0];
                            try {
                                ifaces =  mNwService.listInterfaces();
                            } catch (Exception e) {
                                loge("Error listing Interfaces");
                            }
                            for (String iface : ifaces) {
                                if (isP2p(iface)) {
                                    if (DBG) log("P2P group iface: " + iface);
                                    mNwService.setInterfaceDown(iface);
                                }
                            }
                            mNwService.setInterfaceDown(mP2pInterfaceName);
                        }
                            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);
                        }

                        if(mWifiNative.startSupplicant(mP2pSupported)) {
                            setWifiState(WIFI_STATE_ENABLING);
                            if (DBG) log("Supplicant start successful");
                            <span style="color:#FF0000;">mWifiMonitor.startMonitoring();
                            transitionTo(mSupplicantStartingState);</span>
                        } else {
                            loge("Failed to start supplicant!");
                        }
                    } else {
                        loge("Failed to load driver");
                    }
                    break;
                case CMD_START_AP:
                    if (mWifiNative.loadDriver()) {
                        setWifiApState(WIFI_AP_STATE_ENABLING);
                        transitionTo(mSoftApStartingState);
                    } else {
                        loge("Failed to load driver for softap");
                        if (mSoftApErrorDetected.get()) {
                            mSoftApErrorDetected.set(false);
                            if (mLastWifiApConfig != null &&
                                    !mLastWifiApConfig.getWifiApConfigurationAdv().isRadioDefault())
                            {
                                if (DBG) log("Restart softAP with default radio configuration");
                                mLastWifiApConfig.getWifiApConfigurationAdv().resetRadioConfig();
                                setHostApRunning(mLastWifiApConfig, true);
                            }
                        }
                    }
                default:
                    return NOT_HANDLED;
            }
            return HANDLED;
        }
    }
接收到CMD_START_SUPPLICANT消息后,首先会调用mWifiNative的loadDriver方法,loadDriver是一个本地方法,其作用是加载相应的Wifi驱动,如果驱动加载成功,会调用mWifiMonitor的startMonitoring方法,并且把当前的 状态转为mSupplicantStartingState状态。我们来看看mWifiMonitor这个对象,mWifiMonitor是一个WifiMonitor对象,它负责从wpa_supplicant接收消息,运行在一个独立的线程中。看看构造方法

public WifiMonitor(StateMachine wifiStateMachine, WifiNative wifiNative) {
        if (DBG) Log.d(TAG, "Creating WifiMonitor");
        <span style="color:#FF0000;">mWifiNative = wifiNative;</span>
        mInterfaceName = wifiNative.mInterfaceName;
        <span style="color:#FF0000;">mWifiStateMachine = wifiStateMachine;</span>
        mMonitoring = false;
 
        WifiMonitorSingleton.getMonitor().registerInterfaceMonitor(mInterfaceName, this);
    }
这里传入了StateMachine对象和WifiNative对象,接着我们看看startMonitoring方法

public void startMonitoring() {
        WifiMonitorSingleton.getMonitor().startMonitoring(mInterfaceName);
    }
这里调用WifiMonitor内部类WifiMonitorSingleton的startMonitoring方法

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);
                        <span style="color:#FF0000;">new MonitorThread(mWifiNative, this).start();</span>
                        mConnected = true;
                        break;
                    }
                    if (connectTries++ < 5) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException ignore) {
                        }
                    } else {
                        mIfaceMap.remove(iface);
                        m.mWifiStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
                        Log.e(TAG, "startMonitoring(" + iface + ") failed!");
                        break;
                    }
                }
            }
        }
这里会启动一个MonitorThread线程,看看这个线程的构造方法
    private static class MonitorThread extends Thread {
        private final WifiNative mWifiNative;
        private final WifiMonitorSingleton mWifiMonitorSingleton;
        private int mRecvErrors = 0;
        private StateMachine mStateMachine = null;

        public MonitorThread(WifiNative wifiNative, WifiMonitorSingleton wifiMonitorSingleton) {
            super("WifiMonitor");
            mWifiNative = wifiNative;
            mWifiMonitorSingleton = wifiMonitorSingleton;
        }
没做什么,再看run方法

public void run() {
            //noinspection InfiniteLoopStatement
            for (;;) {
                <span style="color:#FF0000;">String eventStr = mWifiNative.waitForEvent();</span>

                // 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);
                        m = mWifiMonitorSingleton.getMonitor(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 {
                    // 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) {
                   <span style="color:#FF0000;"> if (dispatchEvent(eventStr))</span> {
                        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)) {
                            done = true;
                        }
                    }

                    if (done) {
                        // 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;
                    }
                }
            }
        }
这里调用了mWifiNative的waitForEvent方法,这个方法通过jni调用本地方法读取wpa_supplicant的消息,接着转发出去。

看看dispatchEvent方法

private boolean dispatchEvent(String eventStr) {

            if (!eventStr.startsWith(EVENT_PREFIX_STR)) {
                if (eventStr.startsWith(WPA_EVENT_PREFIX_STR) &&
                        0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR)) {
                    mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
                } else if (eventStr.startsWith(AUTH_TIMEOUT_STR)) {
                    mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
                } else if (eventStr.startsWith(SME_EVENT_PREFIX_STR) &&
                        0 < eventStr.indexOf(AUTH_REQ_FAILED_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);
                }
                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;
            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;
            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) {
                /**
                 * 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
                mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
                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 {
                <span style="color:#FF0000;">handleEvent(event, eventData);</span>
            }
            mRecvErrors = 0;
            return false;
        }
经过一系列处理调用handleEvent方法
        /**
         * Handle all supplicant events except STATE-CHANGE
         * @param event the event type
         * @param remainder the rest of the string following the
         * event name and " — "
         */
        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;

                case UNKNOWN:
                    break;
            }
        }
以SCAN_RESULTS_EVENT为例,状态机发送一个SCAN_RESULTS_EVENT消息,这个状态机是WifiStateMachine对象,WifiStateMachine当前的状态为SupplicantStartedState(中间的过程暂时忽略),看看processMessage方法相关代码

case WifiMonitor.SCAN_RESULTS_EVENT:
                    setScanResults();
                    sendScanResultsAvailableBroadcast();
                    mScanResultIsPending = false;
                    break;
这里会调用sendScanResultsAvailableBroadcast发送广播,把扫描到的Wifi热点信息发送给广播接收者

    private void sendScanResultsAvailableBroadcast() {
        noteScanEnd();
        Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
    }
至此,Wifi启动的一个大概流程就先分析到这里!

















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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值