Android4.4(MT8685)源码WIFI--初始化2

上一章我们讲到在SystemServer中会初始化一个WifiService对象,那么我们来看看这个WifiService的构造方法,路径:./frameworks/base/services/java/com/android/server/wifi/WifiService.java

<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> 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();
    }</span></span></span>

这里主要创建一个WifiStateMachine,然后新建一个HandlerThread来处理消息,还创建了一个WifiController。接下来我们先分析WifiStateMachine。

WifiStateMachine用于控制整个Wifi的开启、关闭、连接、断开的状态切换,它继承了StateMachine,来看看构造方法的关键代码,路径为:./frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java

<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;">public WifiStateMachine(Context context, String wlanInterface) {
        super("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);

        setInitialState(mInitialState);

        //start the state machine
        start();
    }</span></span></span>

这里添加了各种状态,并且调用了父类的start方法,说明此时,WifiStateMachine的状态为其初始状态,也就是mInitialState状态。

回到WifiService的构造方法中,还有一个WifiController对象被创建,WifiController类也是StateMachine的子类,看看其构造方法,路径:./frameworks/base/services/java/com/android/server/wifi/WifiController.java

<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;">WifiController(Context context, WifiService service, Looper looper) {
        super(TAG, looper);
        mContext = context;
        mWifiStateMachine = service.mWifiStateMachine;
        mSettingsStore = service.mSettingsStore;
        mLocks = service.mLocks;

        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
        Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
        mIdleIntent = PendingIntent.getBroadcast(mContext, IDLE_REQUEST, idleIntent, 0);

        ///M: add plugin
        mWifiFwkExt = MediatekClassFactory.createInstance(IWifiFwkExt.class, mContext);

        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);
    }</span></span></span>

这里把WifiService中的WifiStateMachine对象传递进来了,并且添加了各种状态,并且设置了初始状态。

在WifiService构造方法中创建了WifiController对象了就立即调用了它的start方法,所以此时WifiController所在状态为它的初始状态,那么它的初始状态为什么呢?我们可以看到当系统在Wifi关闭的状态下仍然可以扫描时,那么初始状态为mStaDisabledWithScanState,否则为mApStaDisabledState,目前我们的系统的初始状态应该属于后者,也就是mApStaDisabledState,那我们进入到其enter方法中

<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;">@Override
        public void enter() {
            if (DBG) log(getName() + "\n");

            mWifiStateMachine.setSupplicantRunning(false);
            // Supplicant can't restart right away, so not the time we switched off
            mDisabledTimestamp = SystemClock.elapsedRealtime();
            mDeferredEnableSerialNumber++;
            mHaveDeferredEnable = false;
        }</span></span></span>

其实这里没做什么特别的操作。此时WifiService的初始化分析完成。

在之前的SystemServer中,在WifiService对象创建之后,我们还调用了它的checkAndStartWifi方法,这个方法就是用来检测是否可以启动Wifi了

<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> /**
     * Check if Wi-Fi needs to be enabled and start
     * if needed
     *
     * This function is used only at boot time
     */
    public void checkAndStartWifi() {

        ///M:
        mWifiStateMachine.autoConnectInit();

        /* Check if wi-fi needs to be enabled */
        boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();

        ///M: @{
        if (mWifiStateMachine.hasCustomizedAutoConnect() && mSettingsStore.isAirplaneModeOn()) {
            SXlog.i(TAG, "Don't enable wifi when airplane mode is on for customization.");
        } else {
        ///@}
            Slog.i(TAG, "WifiService starting up with Wi-Fi " +
                        (wifiEnabled ? "enabled" : "disabled"));

            // If we are already disabled (could be due to airplane mode), avoid changing persist
            // state here
            if (wifiEnabled) setWifiEnabled(wifiEnabled);

        }
        mWifiWatchdogStateMachine = WifiWatchdogStateMachine.
               makeWifiWatchdogStateMachine(mContext);

    }</span></span></span>

这里获取到上一次系统的Wifi状态,根据状态来决定是否开启Wifi,我们看看setWifiEnabled这个方法

<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> /**
     * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)}
     * @param enable {@code true} to enable, {@code false} to disable.
     * @return {@code true} if the enable/disable operation was
     *         started or is already in the queue.
     */
    public synchronized boolean setWifiEnabled(boolean enable) {
        Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
                    + ", uid=" + Binder.getCallingUid());
        enforceChangePermission();
        ///M: @{
        if (mWifiStateMachine.hasCustomizedAutoConnect() && enable &&  mSettingsStore.isAirplaneModeOn()) {
            SXlog.i(TAG, "Can't enable wifi when airplane mode is on for customization.");
            return false;
        }
        ///@}

        if (DBG) {
            Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");
        }

        if (FeatureOption.MTK_MOBILE_MANAGEMENT) {
            if (enable == true) {
                if (mMobileManagerService == null) {
                    mMobileManagerService = IMobileManagerService.Stub.asInterface(
                            ServiceManager.getService(Context.MOBILE_SERVICE));
                }
                try {
                    mMobileManagerService.checkPermissionAsync(SubPermissions.CHANGE_WIFI_STATE_ON,
                            Binder.getCallingUid(), new wifiOnPermissionCheckCallback());
                } catch (RemoteException e) {
                    Slog.e(TAG, "checkPermissionAsync() failed", e);
                }
                return true;
            }
        }

        /*
        * Caller might not have WRITE_SECURE_SETTINGS,
        * only CHANGE_WIFI_STATE is enforced
        */

        long ident = Binder.clearCallingIdentity();
        try {
            if (! mSettingsStore.handleWifiToggled(enable)) {
                // Nothing to do if wifi cannot be toggled
                return true;
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }

        ///M: put extra mWifiIpoOff
        Log.e("dd","mWifiIpoOff1="+String.valueOf(mWifiIpoOff));
        mWifiController.obtainMessage(CMD_WIFI_TOGGLED, mWifiIpoOff ? 1 : 0 ).sendToTarget();
        return true;
    }</span></span></span>

这里主要就是想WifiController发送一个CMD_WIFI_TOGGLED消息,我们看看接收消息的地方,找到ApStaDisabledState类的processMessage方法

<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> @Override
        public boolean processMessage(Message msg) {
            SXlog.d(TAG, getName() + msg.toString() + "\n");
            switch (msg.what) {
                case CMD_WIFI_TOGGLED:
                case CMD_AIRPLANE_TOGGLED:
                    ///M: add [email protected]{
                    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) {
							Log.e("dd","ApStaDisabledState to mDeviceActiveState");
                            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;
default:
                    return NOT_HANDLED;
            }
            return HANDLED;
        }</span></span></span>

这里只是简单的跳转状态到mDeviceActiveState,mDeviceActiveState状态的父状态是mStaEnabledState,所以分别会进入它们的enter方法:

<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;">    class StaEnabledState extends State {
        @Override
        public void enter() {
            mWifiStateMachine.setSupplicantRunning(true);
        }

    class DeviceActiveState extends State {
        @Override
        public void enter() {
            mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
            mWifiStateMachine.setDriverStart(true);
            mWifiStateMachine.setHighPerfModeEnabled(false);
        }</span></span></span>

这里都是向WifiStateMachine发送消息CMD_START_SUPPLICANT、SET_OPERATIONAL_MODE、CMD_START_DRIVER和SET_HTGH_PERF_MODE

先来看看处理CMD_START_SUPPLICANT消息的地方

<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;">@Override
        public boolean processMessage(Message message) {
            if (DBG) log(getName() + message.toString() + "\n");
            switch (message.what) {
                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;

                default:
                    return NOT_HANDLED;
            }
            return HANDLED;
        }
    }</span></span></span>

这里主要调用WifiNative的loadDriver和startSupplicant两个函数去加载wifi driver和启动wpa_supplicant,当启动成功wpa_supplicant后,就会调用WifiMonitor的startMonitoring去和wpa_supplicant建立socket连接,并不断的从wpa_supplicant收event。wpa_supplicant是一个独立的运行程序,它和应用程序之间通过socket来通信,主要存在两个socket连接,一个用来向wpa_supplicant发送命令,另一个是wpa_supplicant用来向应用程序通知event,应用程序在收到event后可以知道当前的连接状态来进行下一步动作。我们进入到WifiMonitor.startMonitoring这个函数看看:

<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> 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;
                    }
                }
            }
        </span></span></span>

这个方法里面主要调用WifiNative的connenctToSupplicant去和wpa_supplicant建立socket连接,然后给WifiStateMachine发送一个SUP_CONNECTION_EVENT消息,最后新建一个MonitorThread运行,MonitorThread就是一个循环,不断的从wpa_supplicant收event,然后进行解析,并dispatch到不同的函数去处理,后面我们再来分析MonitorThread的流程。回到WifiStateMachine的InitialState中去看看如何处理CMD_START_SUPPLICANT的流程中来,当startMonitoring结束后,WifiStateMachine就跳转到SupplicantStartingState。

接着来看当WifiStateMachine处理完SUP_CONNECTION_EVENT消息后,马上会收到SET_OPERATIONAL_MODE和CMD_START_DRIVER消息,这两个消息都会被SupplicantStartingState延迟处理,SET_HTGH_PERF_MODE会被DefaultState处理。接着SupplicantStartingState会收到SUP_CONNECTION_EVENT,处理代码如下:

<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> @Override
        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);
                    mSupplicantRestartCount = 0;
                    /* Reset the supplicant state to indicate the supplicant
                     * state is not known at this time */
                    mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
                    /* Initialize data structures */
                    mLastBssid = null;
                    mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
                    mLastSignalLevel = -1;

                    mWifiInfo.setMacAddress(mWifiNative.getMacAddress());
                    mWifiConfigStore.loadAndEnableAllNetworks();
                    initializeWpsDetails();
                    mStopSupplicantScan = false;
                    mConnectNetwork = false;
                    mLastExplicitNetworkId = INVALID_NETWORK_ID;
                    mOnlineStartTime = 0;
                    mUsingPppoe = false;

                    if (mWifiFwkExt.hasCustomizedAutoConnect()) {
                        mWifiNative.setBssExpireAge(IWifiFwkExt.BSS_EXPIRE_AGE);
                        mWifiNative.setBssExpireCount(IWifiFwkExt.BSS_EXPIRE_COUNT);
                        mDisconnectOperation = false;
                        mScanForWeakSignal = false;
                        mShowReselectDialog = false;
                        if (!mWifiFwkExt.shouldAutoConnect()) {
                            disableAllNetworks(false);
                        }
                    }

                    if (FeatureOption.MTK_EAP_SIM_AKA) {
                        if (isAirplaneModeOn()) {
                            List<WifiConfiguration> networks = mWifiConfigStore.getConfiguredNetworks();
                            if (null != networks) {
                               for (WifiConfiguration network : networks) {
                                    int value = network.enterpriseConfig.getEapMethod();
                                    Xlog.d(TAG, "EAP value:" + value);
                                    if (value == WifiEnterpriseConfig.Eap.SIM || value == WifiEnterpriseConfig.Eap.AKA) {
                                        mWifiConfigStore.disableNetwork(network.networkId,
                                            WifiConfiguration.DISABLED_UNKNOWN_REASON);
                                    }
                                }
                            } else {
                                Xlog.d(TAG, "Check for EAP_SIM_AKA, networks is null!");
                            }
                        }
                    }

                    sendSupplicantConnectionChangedBroadcast(true);
                    transitionTo(mDriverStartedState);
                    break;
                case WifiMonitor.SUP_DISCONNECTION_EVENT:
                    if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) {
                        loge("Failed to setup control channel, restart supplicant");
                        mWifiMonitor.killSupplicant(mP2pSupported);
                        transitionTo(mInitialState);
                        sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
                    } else {
                        loge("Failed " + mSupplicantRestartCount +
                                " times to start supplicant, unload driver");
                        mSupplicantRestartCount = 0;
                        setWifiState(WIFI_STATE_UNKNOWN);
                        transitionTo(mInitialState);
                    }
                    break;
                case CMD_START_SUPPLICANT:
                case CMD_STOP_SUPPLICANT:
                case CMD_START_AP:
                case CMD_STOP_AP:
                case CMD_START_DRIVER:
                case CMD_STOP_DRIVER:
                case CMD_SET_OPERATIONAL_MODE:
                case CMD_SET_COUNTRY_CODE:
                case CMD_SET_FREQUENCY_BAND:
                case CMD_START_PACKET_FILTERING:
                case CMD_STOP_PACKET_FILTERING:
                    deferMessage(message);
                    break;
                default:
                    return NOT_HANDLED;
            }
            return HANDLED;
        }</span></span></span>

在SUP_CONNECTION_EVENT的处理流程中,主要是调用WifiConfigStore的loadAndEnableAllNetworks函数来加载并enable用户之前连接过并保存的AP,然后会初始化一些Wps相关的信息,最后transition到DriverStartedState上。再来看DriverStartedState的enter函数,这里面有一些重要的流程:

<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;">    class DriverStartedState extends State {
        @Override
        public void enter() {

            /* set country code */
            setCountryCode();
            /* set frequency band of operation */
            setFrequencyBand();
            /* initialize network state */
            setNetworkDetailedState(DetailedState.DISCONNECTED);

            mDhcpActive = false;

            startBatchedScan();

            if (mOperationalMode != CONNECT_MODE) {
                mWifiNative.disconnect();
                mWifiConfigStore.disableAllNetworks();
                if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) {
                    setWifiState(WIFI_STATE_DISABLED);
                }
                transitionTo(mScanModeState);
            } else {
                /* Driver stop may have disabled networks, enable right after start */
                mWifiConfigStore.enableAllNetworks();

                if (DBG) log("Attempting to reconnect to wifi network ..");
                mWifiNative.reconnect();

                // Status pulls in the current supplicant state and network connection state
                // events over the monitor connection. This helps framework sync up with
                // current supplicant state
                mWifiNative.status();
                transitionTo(mDisconnectedState);
            }</span></span></span>

enter函数的代码比较多,上面是精简后的代码,上面主要分为两条分支,一是OperationalMode != CONNECT_MODE,一种是OperationalMode = CONNECT_MODE,根据官方的解释,OperationalMode一共有三种,分别如下:

1.CONNECT_MODE,这种模式下,STA可以scan并连接热点

2.SCAN_ONLY_MODE,这种模式下,STA只能扫描热点

3.SCAN_ONLY_WIFI_OFF_MODE,在这种模式下,当wifi是toggle off的情况下,也可以进行scan

这三种模式默认的是CONNECT_MODE,后面两种模式现在用到的不多,但按照Google的设计,后面可能会有很多的app会用到,比如利用热点来进行点位,这个应用其实这需要能够scan,并不需要链接热点。那我们接看这OperationalMode = CONNECT_MODE的流程,它直接transition 到DisconnectedState,如上图中的Figure
4,在transition到DisconnectedState之前,还会向WifiNative下reconnect的命令,用于重新连接上次连接但没有forget的AP,即开机后自动连上AP。

接着会进入mDisconnectedState状态,由于mDisconnectedState的父状态为mConnectedState状态,所以会先进入mConnectedState状态再进入mDisconnectedState状态,在这两个状态的enter方法中都没有什么特别的操作。

分析到这里,系统启动Wifi的初始化分析已经完成。

时间: 2024-09-14 12:37:39

Android4.4(MT8685)源码WIFI--初始化2的相关文章

Android4.4.2源码分析之WiFi模块(二)

接着上一篇继续对WiFi源码的分析 Android4.4.2源码分析之WiFi模块(一) onResume方法中 6>,首先是调用WiFiEnabler的resume方法对switch进行管理 接下来注册广播 getActivity().registerReceiver(mReceiver, mFilter); 广播监听的action如下 //wifi状态改变的action mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); //W

Android4.4.2源码分析之WiFi模块(一)

由对Androidsetting的源码分析之WiFi模块的界面fragment为WiFisettings.java,关于setting模块的源码分析可以参考 Android系统源码剖析(一)---Settings 已经写了几篇关于Android源码的,源码代码量太大,所以如果想分析某个模块可能不知如何下手,说一下思路 1,分析源码英文阅读能力要够,想要分析某个模块一般找模块对应的英文,就是模块 2,找到之后首先查看清单配置文件Androidmani.fest,找到程序主界面activity 3,

编译android-4.3.1_r源码并刷到自己的Galaxy Nexus I9250真机上

编译android-4.3.1_r源码并刷到自己的Galaxy Nexus I9250真机上 作者:雨水  日期:2014-04-30 编译源代码的目的还是为了自己修改源代码,然后还能够运行在相应的手机上,只有这样才有意义.  我手上有一部三星的Galaxy Nexus I9250, 代号为maguro.但是在目前google的官方未提供针对android4.4.2版本所对应的硬件驱动,最新只提供到Android4.3,具体可以在https://developers.google.com/and

Android4.4系统源码百度网盘下载

众所周知.Android如今非常火,肯定也有非常多android开发人员像我一样想研究android系统的源码.可是假设依照Google官方站点http://source.android.com/source/downloading.html上面说的步骤下载.因为在国内连接谷歌的server网速实在太慢,可是android系统的源码非常大.超过8G.我在网上看到有哥们说他下了一个多月才下载完.更让人难以接受的是,下载过程中网络连接差点儿一定会多次中断.而假设连接超时,就会报错.我在下载过程中就报

[tomcat7源码学习]初始化之catalina.home和catalina.base(转)

我们在代码中为了获取某个配置文件路径下的文件经常会这么写 String tomcatPath = System.getProperty("catalina.home") + "/webapps/axis2/WEB-INF/conf/"; tomcatPath = tomcatPath.replace("/", File.separator); //使用此方法是为了区分unix系统与windows, //File.separator UNIX中为/

Ubuntu12.04编译Android4.0.1源码全过程-----附wubi安装ubuntu编译android源码硬盘空间不够的问题解决

本文转至  http://blog.csdn.net/yanzi1225627/article/details/9263097 昨晚在编译源码,make一段时间之后报错如下: [html] view plaincopyprint? # A fatal error has been detected by the Java Runtime Environment: # #  SIGSEGV (0xb) at pc=0x40362d33, pid=12195, tid=2835454784 # # 

[Bootstrap 源码]——bootstrap源码之初始化

bootstrap源码之初始化 我们先来分析normalize.less编译后的源码,我们知道normalize.css是一个专门将不同浏览器的默认css特性设置为统一效果的css库,它和reset.css还是有区别的,normalize.css并不是简单的重置了所有的样式,而是有针对的修改,同时也保留了标签的语义化. 技能一: html { font-family: sans-serif; -webkit-text-size-adjust: 100%; //防止IOS系统方向改变(特别是手持设

Ubuntu12.04下载Android4.0.1源码全过程,附若干问题解决[转]

学校里一直在做应用层开发,考虑到日后就业问题,这次决定研究源码和驱动,并进行编译.没想到就下载源码这一步折腾了我整整两天,期间遇到很多问题,哎,记录于此,希望日后再下源码的人不要再走无谓的弯路了.事实上可以在这里http://zhu.im/Android/下载源码,但是google推荐用repo来下载,为了多学东西就学下repo吧,毕竟下现成的也太么含量了.最初我参考的是老罗的博客http://blog.csdn.net/luoshengyang/article/details/6559955

Android4.4 蓝牙源码部分分析

最近GOOGLE发布了Android4.4,看了一下源码:4.4的蓝牙打开流程这一部分还是有些变化的,从界面上看蓝牙开关就是设置settings里那个switch开关,widget开关当然也可以,起点不同后续的流程是一样的.先来看systemServer.java的代码,蓝牙服务开启的地方,真机情况下我们关心的是最后一个else分支. if (SystemProperties.get("ro.kernel.qemu").equals("1")) {Slog.i(TA

[2013.7.5新鲜出炉] Ubuntu12.04下载Android4.0.1源码全过程----------------折腾两天,终于下好,附若干问题解决

本文转至 http://blog.csdn.net/yanzi1225627/article/details/9255457 下载源码这一步折腾了我整整两天,期间遇到很多问题,哎,记录于此,希望日后再下源码的人不要再走无谓的弯路了.事实上可以在这里http://zhu.im/Android/下载源码,但是google推荐用repo来下载,为了多学东西就学下repo吧,毕竟下现成的也太么含量了.最初我参考的是老罗的博客http://blog.csdn.net/luoshengyang/articl