sheldon_blogs

Android:StateMachine 之 WifiStateMachine

一、状态图:

  

  

 

二、代码分析: \frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiStateMachine.java

  1.创建WifiStateMachine的构造函数中添加各个状态:

复制代码
/*调用stateMachine类的构造方法完成状态机的构造,名字为WifiStateMachine*/ 
 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(mConnectedState, mL2ConnectedState);
                            addState(mRoamingState, 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);

/*设置状态日志记录*/
setLogRecSize(2000);
setLogOnlyTransitions(false);

/*开始状态机*/
start();
复制代码

  2.状态切换-开启AP (access point:热点)

    (1)TetheredState监听中收到CMD_TETHER_STATE_CHANGE消息后调用setHostApRunning() 开启AP功能,此方法发送CMD_START_AP消息:

    public void setHostApRunning(WifiConfiguration wifiConfig, boolean enable) {
        if (enable) {
            sendMessage(CMD_START_AP, wifiConfig);
        } else {
            sendMessage(CMD_STOP_AP);
        }
    }

    (2)状态机启动后处于InitialState状态,processMessage()中处理CMD_START_AP消息:

复制代码
case CMD_START_AP:  if (enableSoftAp() == true) {
    /*设置AP状态*/     setWifiApState(WIFI_AP_STATE_ENABLING,
0);
    /*状态切换mSoftApStartingState*/     transitionTo(mSoftApStartingState);   }
else {     setWifiApState(WIFI_AP_STATE_FAILED,     WifiManager.SAP_START_FAILURE_GENERAL);     transitionTo(mInitialState);   } break;
复制代码

    (3)CMD_START_AP消息处理完后,跳转到mSoftApStartingState进入mSoftApStartingState的enter方法:

复制代码
    class SoftApStartingState extends State {
        @Override
        public void enter() {
            final Message message = getCurrentMessage();
            if (message.what == CMD_START_AP) {
                final WifiConfiguration config = (WifiConfiguration) message.obj;

                if (config == null) {
                    mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG);
                } else {
                    mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);
            /*开启AP*/
                    startSoftApWithConfig(config);
                }
            } else {
                throw new RuntimeException("Illegal transition to SoftApStartingState: " + message);
            }
        }
     ......      
}
复制代码

    (4)startSoftApWithConfig开启AP成功后,会发送CMD_START_AP_SUCCESS:

复制代码
        // Start hostapd on a separate thread
        new Thread(new Runnable() {
            public void run() {
                try {
                    mNwService.startAccessPoint(config, mInterfaceName);
                } catch (Exception e) {
                    loge("Exception in softap start " + e);
                    try {
               // 重置热点       mNwService.stopAccessPoint(mInterfaceName); mNwService.startAccessPoint(config, mInterfaceName); }
catch (Exception e1) { loge("Exception in softap re-start " + e1); sendMessage(CMD_START_AP_FAILURE, WifiManager.SAP_START_FAILURE_GENERAL); return; } } if (DBG) log("Soft AP start successful");
          // 发送消息 sendMessage(CMD_START_AP_SUCCESS); } }).start(); }
复制代码

  SoftApStartingState中处理CMD_START_AP_SUCCESS消息:

复制代码
public boolean processMessage(Message message) {
    switch(message.what) {         case CMD_START_AP_SUCCESS:
            /*设置AP状态*/
            setWifiApState(WIFI_AP_STATE_ENABLED);
            /*跳转到mSoftApStartedState*/
            transitionTo(mSoftApStartedState);
            break;

         case CMD_START_AP_FAILURE:
            setWifiApState(WIFI_AP_STATE_FAILED, message.arg1);
            transitionTo(mInitialState);
            break;
default: return NOT_HANDLED; } }
复制代码

    (5)CMD_START_AP_SUCCESS消息处理完后,跳转到mSoftApStartedState状态,执行该状态的enter方法。

        此状态下收到CMD_TETHER_STATE_CHANGE消息后做进一步处理:

复制代码
public boolean processMessage(Message message) {
    switch(message.what) {
        //
           case CMD_TETHER_STATE_CHANGE:
               TetherStateChange stateChange = (TetherStateChange) message.obj;
               /*开启tethering*/
              if (startTethering(stateChange.available)) {
                  transitionTo(mTetheringState);
              }
            break;
      }
}
复制代码

    (6)开启startTethering成功后,跳转到mTetheringState状态,执行其enter方法:

 public void enter() {            
        /*发送延时消息,超时时间5s*/
        sendMessageDelayed(obtainMessage(CMD_TETHER_NOTIFICATION_TIMED_OUT,
                    ++mTetherToken, 0), TETHER_NOTIFICATION_TIME_OUT_MSECS);
}

      mTetheringState状态下,收到CMD_TETHER_NOTIFICATION_TIMED_OUT超时消息,则启动tether失败,一步步切回到init状态。

复制代码
           switch(message.what) {
                case CMD_TETHER_STATE_CHANGE:
                    TetherStateChange stateChange = (TetherStateChange) message.obj;
                    if (isWifiTethered(stateChange.active)) {
                        transitionTo(mTetheredState);
                    }
                    return HANDLED;
                case CMD_TETHER_NOTIFICATION_TIMED_OUT:
                    if (message.arg1 == mTetherToken) {
                        loge("Failed to get tether update, shutdown soft access point");
                        transitionTo(mSoftApStartedState);
                        // Needs to be first thing handled
                        sendMessageAtFrontOfQueue(CMD_STOP_AP);
                    }
                    break;
   ......
            }
复制代码

    如果在超时消息之前收到CMD_TETHER_STATE_CHANGE消息,则跳转到 TetheredState 中:

复制代码
   class TetheredState extends State {
        @Override
        public boolean processMessage(Message message) {
            logStateAndMessage(message, getClass().getSimpleName());

            switch(message.what) {
                case CMD_TETHER_STATE_CHANGE:
                    TetherStateChange stateChange = (TetherStateChange) message.obj;
                    if (!isWifiTethered(stateChange.active)) {
                        loge("Tethering reports wifi as untethered!, shut down soft Ap");
               // 开启热点 setHostApRunning(
null, false); setHostApRunning(null, true); } return HANDLED; ...... } }
复制代码

    其中setHostApRunning方法中发送CMD_START_AP消息:

    public void setHostApRunning(WifiConfiguration wifiConfig, boolean enable) {
        if (enable) {
            sendMessage(CMD_START_AP, wifiConfig);
        } else {
            sendMessage(CMD_STOP_AP);
        }
    }

  上面发送的CMD_START_AP消息会传到DefaultState中处理。


  至此整个状态机的状态历经如下切换,稳定在mThertheredState:

    mInitialState->mSoftApStartingState->mSoftApStartedState->mThetheringState->mThertheredState

  若在mThertheredState状态下关闭AP,则按照如下流程切换:

    mThertheredState->mUntetheringState->mSoftApStartedState->mInitialState

  这个流程中用到了deferMessage来实现相同消息的反复发送。

 

posted on   sheldon_blogs  阅读(1601)  评论(0编辑  收藏  举报

编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示