wifi状态机工作原理

版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/huangweiqing80/article/details/82494498
1. WifiController状态机
WifiController 是高级别的wifi状态机,它管理的状态是wifi开关,wifi热点开关等状态。只有在wifi开关等具体状态下,判断wifi处于启动扫描附近热点状态等才是有意义的。

1.1 WifiController状态机的创建

mWifiController = new WifiController(mContext, mWifiStateMachine, mSettingsStore,
                mLockManager, mWifiServiceHandlerThread.getLooper(), mFrameworkFacade); 

状态机初始化三部曲:

addState
setInitialState
start

状态机无非就是一个定义了很多状态的机器,它收到消息后,会根据消息来切换这个机器的状态。WifiController 的状态构造在它的构造方法中。当我们创建一个状态机时,需要使用addState方法给状态机添加状态
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiController.java

    WifiController(Context context, WifiStateMachine wsm, WifiSettingsStore wss,
            WifiLockManager wifiLockManager, Looper looper, FrameworkFacade f) {
    ...

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

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

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

        if (isScanningAlwaysAvailable) {
            setInitialState(mStaDisabledWithScanState);
        } else {
            setInitialState(mApStaDisabledState);
        }

从WifiController的构造函数中,我们可以看到使用addState方法给状态机添加了状态,用setInitialState给状态机设置了初始状态mApStaDisabledState

而WifiController的start方法是由WifiService的onBootPhase方法调用WifiServiceImpl的checkAndStartWifi调用的:

    /**
     * Check if we are ready to start wifi.
     *
     * First check if we will be restarting system services to decrypt the device. If the device is
     * not encrypted, check if Wi-Fi needs to be enabled and start if needed
     *
     * This function is used only at boot time.
     */
    public void checkAndStartWifi() {
        ...
        mWifiController.start();
        ...
    }

WifiController状态机的状态结构图如下
这里写图片描述

2 mWifiStateMachine状态机
WifiStateMachine状态机的创建

        mWifiStateMachine = new WifiStateMachine(mContext, mFrameworkFacade,
                wifiStateMachineLooper, UserManager.get(mContext),
                this, mBackupManagerProxy, mCountryCode, mWifiNative,
                new WrongPasswordNotifier(mContext, mFrameworkFacade));

mWifiStateMachine 则表述wifi更加细致的状态,它的状态构建也是在构造函数中:
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java

public WifiStateMachine(Context context, FrameworkFacade facade, Looper looper,
                        UserManager userManager, WifiInjector wifiInjector,
                        BackupManagerProxy backupManagerProxy, WifiCountryCode countryCode,
                        WifiNative wifiNative,
                        WrongPasswordNotifier wrongPasswordNotifier) {
  ...
    // CHECKSTYLE:OFF IndentationCheck
    addState(mDefaultState);
        addState(mInitialState, mDefaultState);
        addState(mSupplicantStartingState, mDefaultState);
        addState(mSupplicantStartedState, mDefaultState);
                addState(mScanModeState, mSupplicantStartedState);
                addState(mConnectModeState, mSupplicantStartedState);
                    addState(mL2ConnectedState, mConnectModeState);
                        addState(mObtainingIpState, mL2ConnectedState);
                        addState(mConnectedState, mL2ConnectedState);
                        addState(mRoamingState, mL2ConnectedState);
                    addState(mDisconnectingState, mConnectModeState);
                    addState(mDisconnectedState, mConnectModeState);
                    addState(mWpsRunningState, mConnectModeState);
            addState(mWaitForP2pDisableState, mSupplicantStartedState);
        addState(mSupplicantStoppingState, mDefaultState);
        addState(mSoftApState, mDefaultState);
    // CHECKSTYLE:ON IndentationCheck

    setInitialState(mInitialState);

    setLogRecSize(NUM_LOG_RECS_NORMAL);
    setLogOnlyTransitions(false);

    //start the state machine
    start();

从WifiStateMachine的构造函数中,我们可以看到使用addState方法给状态机添加了状态,用setInitialState给状态机设置了初始状态mInitialState,用start()启动状态机
WifiStateMachine状态机的状态结构图如下
这里写图片描述

以上Android wifi框架中两个重要的状态机,那么状态机的工作机制是怎么样的呢?

3 状态机工作原理简介:
状态机中会有多种状态,状态机中的每一个状态是由State类的实例表示,State实例必须实现processMessage方法用来处理消息。并且可选的实现enter/exit/getName三个方法,enter/exit 等价于类的构造方法和销毁方法,本例用于初始化和清理一个状态。getName方法返回State的名字,默认的实现是返回类名。
当我们创建一个状态机时,需要使用addState方法给状态机添加状态,正如前面所展示的那样。 用于初始化一个状态机的初始状态。构建好一个状态机以后,我们需要调用start方法启动这个状态机,它就像一个机器,造好以后,加油或者充电,然后发动它,它就进入工作状态了。这个过程会调用初始化状态的enter方法初始化初始状态,如果初始状态由父状态,就会递归调用父状态,直到所有父状态的enter方法被调用。这样才算是完全初始化好了一个状态机,start方法还会使状态机进入已经构造结束阶段,这个时候,当有消息到来时,状态机就可以处理消息了。
处理消息的过程和初始化类似。当消息到来以后,当前状态就会调用processMessage来处理消息,如果当前消息能够处理消息,那么消息处理过程就结束了,此时会根据具体情况选择切换或者不切换状态机的状态。如果当前State不能处理消息,那么就会递交父State的processMessage来处理,父状态如果还不能处理就继续往上递交。如果一个消息从未被处理,unhandledMessage方法会被调用,这是最后处理这个消息的机会了。
如果我们期望停止状态机,可以调用quitNow或者quit方法。
当我们切换状态时,旧State的exit方法会被调用而新State的enter方法会被调用,同时他们父State也会做相同的事情。但是如果两个状态由相同的父状态,那么这个时候他们父状态就没有必要做任何操作了,因为它的状态其实并没有变。
以上就是一个状态机的工作原理的简要概述。下面我举个例子,当应用程序需要扫描附近的热点时,如果wifi状态机正处于开启状态,那么上层的操作会导致wifi状态机接收到一个消息,开启的状态对它处理后,发现需要把wifi状态机切换到scan状态,(在processMessage中调用transitionTo切换状态)于是开启状态的exit方法被调用,scan状态的enter方法被调用。切换不应该只是wifi状态机状态的切换,这个过程应该会调用底层的代码真正的把wifi的状态切换到对应的状态。切换过去以后底层kernel会返回响应的事件,这又会导致响应的消息被wifi状态机接受,从而又促使wifi状态机状态的切换。

start()方法用于启动状态机,transitionTo()方法用于设置新状态performTransitions()是去切换新状态,sendMessage()方法用于向mSmHandler发送消息,mSmHandler的handleMessage方法会把消息抛个当前状态的proccessMessage()方法处理。

猜你喜欢

转载自blog.csdn.net/huangweiqing80/article/details/82494498