Android状态机(蓝牙)

简介:

http://blog.csdn.net/wsb1321/article/details/8021620

Android系统中对于WIFI,蓝牙模块运用了状态机来管理状态。搜索了下4.0中的状态机有以下文件:

./frameworks/base/wifi/java/android/net/wifi/WpsStateMachine.java
./frameworks/base/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
./frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java
./frameworks/base/core/java/android/net/dhcp/DhcpStateMachine.java
./frameworks/base/core/java/android/net/DhcpStateMachine.java
./frameworks/base/core/java/android/server/BluetoothAdapterStateMachine.java

以上的类都是继承于./frameworks/base/core/java/com/android/internal/util/StateMachine.java。

系统为了好管理,将一个模块的不同状态封装成State,而StateMachine就是用来管理这些State的。

看一下State类中提供的主要方法有:

 @Override
    public void enter() {
    }

    /* (non-Javadoc)
     * @see com.android.internal.util.IState#exit()
     */
    @Override
    public void exit() {
    }

    /* (non-Javadoc)
     * @see com.android.internal.util.IState#processMessage(android.os.Message)
     */
    @Override
    public boolean processMessage(Message msg) {
        return false;
    }

 @Override
    public String getName() {
        String name = getClass().getName();
        int lastDollar = name.lastIndexOf('$');
        return name.substring(lastDollar + 1);
    }

再回到StateMachine.java这个文件,在这个文件开始有一大堆的英文说明该类的作用和实现过程。下面结合自己的理解梳理下这段内容:


用法准备条件:首先根据需要要生成我们的State, 比如  private class PowerOff extends State{}(引用源代码中管理Bt的一个状态),我们定义的这个类必须继承State这个类并根据需要实现相应的方法,其中的processMessage这个方法必须实现(如果不重写这个方法,那我们的状态机将没有任何意义)。enter()方法是当我们进入该状态的时候第需要调用的(像程序代码中的构造函数),exit()是退出该状态的时候调用(像析构函数)。


当准备好State后,就在调用addState(State state, State parent)将我们的状态添加进StateMachine。


到这里首先看下StateMachine还有些什么内容。

内部类:SmHandler(大部分处理都是通过这个类完成),ProcessedMessageInfo,ProcessedMessages。在SmHandler中又包含内部类StateInfo,成员StateMachine(mSm),HashMap<State, StateInfo> mStateInfo,mStateStack,mDeferredMessages,State mInitialState,  State mDestState, rivate ArrayList<Message> mDeferredMessages。

启动状态机的步骤:

1.首先需要通过addState添加上面准备好的State实例,每一个State都可以添加一个自身的State和一个parentState。add的方法最中是通过调用SmHandler的StateInfo addState(State state, State parent)方法。这个方法会将他的状态以及他的父状态的信息取出来并放到mStateInfo这个hashMap表中的(首先会从mStateInfo中通过State找一下是否存在该状态的相关信息,不存在才会put)。

2.添加完所有的状态后就调用setInitialState设置一个初始状态, 最终调用的是SmHandler的setInitialState给mInitialState赋值。

3当经过1,2步骤后就要调用StateMachine:start()函数启动状态机机,start函数最终调用的是SmHandler:completeConstruction ,这个函数主要是调用exit退出当前状态并更新记录的State的堆栈信息(mStateStack中的State)并掉用State的enter函数,正式进入新的状态。

4.当我们通过StateMachine:sendMessage发送消息的时候,StateMachine就会找到当前的State调用其processMessage来做相应的处理动作。如果当前状态在处理完相应的事务后需要切换到新的状态就需要调用transitionTo(IState destState)设置mDestState的值。

注意:上面说过一个State可能包含一个Parent State,如果在当前的State中没有能处理发送来的msg的时候,就要向上找其父State来处理,依次向上遍历,如果所有的State都不能处理的话就会调用SmHandler:unhandledMessage来处理。


另外两个方法:deferMessage和sendMessageAtFrontOfQueue,在代码中可以通过deferMessage向mDeferredMessages这种存放暂时不处理的消息。在每此处理完新旧状态更新的时候就要调用sendMessageAtFrontOfQueue将mDeferredMessages中的消息优先发送出去(有可能是在A状态deferMessage的消息,切换到B状态后才发送出去,此时就应该B状态去处理这个消息),每次发送完就会清空mDeferredMessages一次。


图表解释:

        mP0

        /        \

       mP1   mS0

      /         \

    mS2     mS1

    /         \        \

   mS3  mS4  mS5 ---> initial state


如上图,添加了mS5至mP0的8个状态, 其中mS1是mS5的父状态,mP1是mS1的父状态,依次类推。上图可以看出mS5是初始状态,当启用状态机的收回调用StateMachine:start()----->SmHandler:completeConstruction(),这函数里面会调用invokeEnterMethods从而依次调用mP0--mP1--mS1--mS5的enter函数,并将他们每一个对应的StateInfo的active置为true。最后调用的是mS5,所以当前的状态进入mS5。此时如果外面有消息通过StateMachine:sendMessage发送进来,首先就会mS5----mP0依次调用processMessage的方法来出来当前消息直到处理成功(如果mS5就处理成功就跳出了,就不会进入mS1, 以此类推)。


假设现在mP0----mS5处理发送来的消息成功,并且transitionTo(mS4),往上遍历发现有共同祖先mP1,那么就会依次调用mS5---mS1的exit函数,依次调用mS2---mS4的enter函数从而进入mS4状态。现在处于active的状态就是mS4,mS2,mP1,mP0了,下次来消息的时候就该mS4来处理了。


StateMachine的基本原理就是这样,StateMachine基本线路就在SmHandler的中handleMessage函数。 下一篇将会结合蓝牙状态机的转换进行具体的介绍。







相关文章
|
Android开发 开发者
【Android 高性能音频】AAudio 状态机 ( 创建 | 打开 Open | 开始 Started | 暂停 Paused | 刷写 Flushed | 停止 Stopped | 关闭 )
【Android 高性能音频】AAudio 状态机 ( 创建 | 打开 Open | 开始 Started | 暂停 Paused | 刷写 Flushed | 停止 Stopped | 关闭 )
349 0
|
存储 Java API
一文详解 Android状态机StateMachine 使用方式及实现原理
`StateMachine`不是`Android SDK`中的相关API,是存在于`frameworks`层源码中的一个Java类。通过这篇文章探究一下其使用方式以及实现原理。
952 0
一文详解 Android状态机StateMachine 使用方式及实现原理
|
Android开发 文件存储
|
17天前
|
Java Android开发
Android 开发获取通知栏权限时会出现两个应用图标
Android 开发获取通知栏权限时会出现两个应用图标
12 0
|
1月前
|
XML 缓存 Android开发
Android开发,使用kotlin学习多媒体功能(详细)
Android开发,使用kotlin学习多媒体功能(详细)
89 0
|
1月前
|
设计模式 人工智能 开发工具
安卓应用开发:构建未来移动体验
【2月更文挑战第17天】 随着智能手机的普及和移动互联网技术的不断进步,安卓应用开发已成为一个热门领域。本文将深入探讨安卓平台的应用开发流程、关键技术以及未来发展趋势。通过分析安卓系统的架构、开发工具和框架,本文旨在为开发者提供全面的技术指导,帮助他们构建高效、创新的移动应用,以满足不断变化的市场需求。
17 1
|
1月前
|
机器学习/深度学习 调度 Android开发
安卓应用开发:打造高效通知管理系统
【2月更文挑战第14天】 在移动操作系统中,通知管理是影响用户体验的关键因素之一。本文将探讨如何在安卓平台上构建一个高效的通知管理系统,包括服务、频道和通知的优化策略。我们将讨论最新的安卓开发工具和技术,以及如何通过这些工具提高通知的可见性和用户互动性,同时确保不会对用户造成干扰。
31 1
|
8天前
|
XML 开发工具 Android开发
构建高效的安卓应用:使用Jetpack Compose优化UI开发
【4月更文挑战第7天】 随着Android开发不断进化,开发者面临着提高应用性能与简化UI构建流程的双重挑战。本文将探讨如何使用Jetpack Compose这一现代UI工具包来优化安卓应用的开发流程,并提升用户界面的流畅性与一致性。通过介绍Jetpack Compose的核心概念、与传统方法的区别以及实际集成步骤,我们旨在提供一种高效且可靠的解决方案,以帮助开发者构建响应迅速且用户体验优良的安卓应用。
|
17天前
|
Android开发
Android开发小技巧:怎样在 textview 前面加上一个小图标。
Android开发小技巧:怎样在 textview 前面加上一个小图标。
10 0