安卓StateMachine分析举例---WifiStateMachine

本文详细解析了Wi-Fi状态机的创建过程及状态转换逻辑,包括各状态间的转换流程及关键函数的处理方式。

WifiStateMachine创建:

创建在构造方法WifiStateMachine(Context context, String wlanInterface) 中实施:

public WifiStateMachine(Context context, String wlanInterface) {
     /*调用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(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);

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

     /*开始状态机*/
     start();

}

在start方法中,调用completeConstruction方法完成构造,这个方法之前已经分析过,主要是完成状态机棧的搭建,并发送启动完成的消息,将状态机运行起来。状态机起来后,分别运行mDefaultState和mInitialState的状态的enter方法,在mDefaultState的方法中do nothing,在mInitialState的enter方法中,进行了wifi相关的初始化,这里不做关注:

public void enter() {
    mWifiNative.unloadDriver();
    if (mWifiP2pChannel == null) {
       mWifiP2pChannel = new AsyncChannel();
       mWifiP2pChannel.connect(mContext, getHandler(), mWifiP2pManager.getMessenger());
    }

    if (mWifiApConfigChannel == null) {
        mWifiApConfigChannel = new AsyncChannel();
        WifiApConfigStore wifiApConfigStore = WifiApConfigStore.makeWifiApConfigStore(
                        mContext, getHandler());
        wifiApConfigStore.loadApConfiguration();
        mWifiApConfigChannel.connectSync(mContext, getHandler(),wifiApConfigStore.getMessenger());
    }
}

至此WifiStateMachine创建成功,运行在InitialState状态,罗列一下各个状态之间的关系:
这里写图片描述

WifiStateMachine状态切换举例–开启AP:

调用setHostApRunning方法,开启AP功能,此方法发送CMD_START_AP消息
状态机启动后处于InitialState状态,收到CMD_START_AP消息后:

 public boolean processMessage(Message message) {
      switch (message.what) {
       /*省略代码*/
       case CMD_START_AP:
            if (mWifiNative.loadDriver()) {
                /*设置AP状态*/
                setWifiApState(WIFI_AP_STATE_ENABLING);
                /*状态切换mSoftApStartingState*/
                transitionTo(mSoftApStartingState);
            } else {
                loge("Failed to load driver for softap");
            }
            /*省略代码*/
      }
 }

此消息处理函数处理完后,跳转到mSoftApStartingState
进入mSoftApStartingState的enter方法:

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

startSoftApWithConfig开启AP成功后,会发送CMD_START_AP_SUCCESS消息,
SoftApStartingState状态下,处理此消息:

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

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

开启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状态。如果在超时消息之前收到CMD_TETHER_STATE_CHANGE消息,则走如下 处理:

 public boolean processMessage(Message message) {

    switch(message.what) {
        /*省略代码*/
        case CMD_TETHER_STATE_CHANGE:
                TetherStateChange stateChange = (TetherStateChange) message.obj;
                if (isWifiTethered(stateChange.active)) {
                    transitionTo(mTetheredState);
                }
                return HANDLED;
                /*省略代码*/
}

如果isWifiTethered返回成功则跳转到mTetheredState状态,并执行其enter方法。否则,超时消息到达后关闭ap。

至此整个状态机的状态历经如下切换,稳定在mThertheredState
mInitialState->mSoftApStartingState->mSoftApStartedState->mThetheringState->mThertheredState

若在mThertheredState状态下关闭AP,则按照如下流程切换
mThertheredState->mUntetheringState->mSoftApStartedState->mInitialState
这个流程中用到了deferMessage来实现相同消息的反复发送。在StateMachine章节已论述。

根据源码分析,弄清一个状态机代码流程的关键点是根据源码画出状态关系图,再根据状态逐个进行推演。如果是定位问题,可以重点使用dump功能,将状态迁徙的过程dump出来,再结合logcat进行分析。

要查找 `spring-statemachine-boot-starter` 的官方文档,可以通过以下途径获取: 1. **Spring 官方网站**:访问 [Spring 官方项目页面](https://spring.io/projects/spring-statemachine) 可以找到 Spring State Machine 的概览信息,其中包含与 Spring Boot 集成的说明[^1]。 2. **Spring State Machine 文档**:完整的 Spring State Machine 官方文档可以在 [Spring Docs](https://docs.spring.io/spring-statemachine/docs/) 上找到。在该页面中,可以选择与 `spring-statemachine-boot-starter` 兼容的版本(例如 2.x 或 3.x),并查看详细的使用指南和 API 说明。 3. **Maven Central**:`spring-statemachine-boot-starter` 的依赖信息和版本历史可以在 [Maven Central](https://search.maven.org/artifact/org.springframework.statemachine/spring-statemachine-boot-starter) 上查询。每个版本通常附带其对应的文档链接,便于查阅具体版本的功能和变更。 4. **GitHub 仓库**:Spring State Machine 的源代码和示例项目托管在 [GitHub](https://github.com/spring-projects/spring-statemachine) 上,可以通过阅读示例代码和项目 Wiki 获取更深入的实现细节。 5. **Spring Boot 自动配置说明**:由于 `spring-statemachine-boot-starter` 是 Spring Boot 的 starter 模块,其自动配置行为可以在 Spring Boot 的官方文档中查找,尤其是与 `application.properties` 或 `application.yml` 配置相关的部分。 以下是一个典型的 `pom.xml` 依赖配置示例: ```xml <dependency> <groupId>org.springframework.statemachine</groupId> <artifactId>spring-statemachine-boot-starter</artifactId> <version>3.0.1</version> </dependency> ``` ### 示例配置类 下面是一个简单的 Spring State Machine 配置示例,展示如何定义状态和事件: ```java import org.springframework.statemachine.config.StateMachineConfigurerAdapter; import org.springframework.statemachine.config.builders.StateMachineStateBuilder; import org.springframework.statemachine.config.builders.StateMachineTransitionBuilder; public class StateMachineConfig extends StateMachineConfigurerAdapter<String, String> { @Override public void configure(StateMachineStateBuilder<String, String> states) throws Exception { states.withStates() .initial("START") .state("PROCESSING") .end("END"); } @Override public void configure(StateMachineTransitionBuilder<String, String> transitions) throws Exception { transitions .withExternal() .source("START").target("PROCESSING") .event("BEGIN") .and() .withExternal() .source("PROCESSING").target("END") .event("FINISH"); } } ``` ### 自动装配与使用 在 Spring Boot 应用中,可以通过注入 `StateMachine` 实例来控制状态流转: ```java import org.springframework.statemachine.StateMachine; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class StateMachineController { private final StateMachine<String, String> stateMachine; public StateMachineController(StateMachine<String, String> stateMachine) { this.stateMachine = stateMachine; } @GetMapping("/start") public String startProcess() { stateMachine.start(); stateMachine.sendEvent("BEGIN"); stateMachine.sendEvent("FINISH"); return "State Machine Final State: " + stateMachine.getState().getId(); } } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值