zoukankan      html  css  js  c++  java
  • Android:StateMachine 之 WifiStateMachine

    一、状态图:

      

      

    二、代码分析: frameworksopt etwifiservicejavacomandroidserverwifiWifiStateMachine.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来实现相同消息的反复发送。

  • 相关阅读:
    NET中的类型和装箱/拆箱原理
    转 C# 装箱和拆箱[整理]
    理解线程同步
    IsBackground的理解
    赛马会面试题
    FTP上传类
    FTPS加密上传
    转载WPF SDK研究 之 AppModel
    SQL Server查看错误日志存档编号及其详情
    Hive基础编程入门(一)
  • 原文地址:https://www.cnblogs.com/blogs-of-lxl/p/11740536.html
Copyright © 2011-2022 走看看