(BluetootOn)<----------------------<- 40 * | ^ -------------------->- | 41 * | | | | 42 * TURN_OFF | | SCAN_MODE_CHANGED m1 | | USER_TURN_ON 43 * AIRPLANE_MODE_ON | | | | 44 * V | | | 45 * (Switching) (PerProcessState) 46 * | ^ | | 47 * POWER_STATE_CHANGED & | | TURN_ON(_CONTINUE) | | 48 * ALL_DEVICES_DISCONNECTED | | m2 | | 49 * V |------------------------< | SCAN_MODE_CHANGED 50 * (HotOff)-------------------------->- PER_PROCESS_TURN_ON 51 * / ^ 52 * / | SERVICE_RECORD_LOADED 53 * | | 54 * TURN_COLD | (Warmup) 55 * ^ 56 * | TURN_HOT/TURN_ON 57 * | | AIRPLANE_MODE_OFF(when Bluetooth was on before) 58 * V | 59 * (PowerOff) <----- initial state
./frameworks/base/core/java/android/server/BluetoothAdapterStateMachine.java
./frameworks/base/core/java/com/android/internal/util/StateMachine.java
BluetoothAdapterStateMachine继承了StateMachine
先看状态机如何被启动的:
基本流程就是这样.
1.BluetoothAdapterStateMachine的初始化动作:
mBluetoothOn = new BluetoothOn(); mSwitching = new Switching(); mHotOff = new HotOff(); mWarmUp = new WarmUp(); mPowerOff = new PowerOff(); mPerProcessState = new PerProcessState(); addState(mBluetoothOn); addState(mSwitching); addState(mHotOff); addState(mWarmUp); addState(mPowerOff); addState(mPerProcessState); setInitialState(mPowerOff); mPublicState = BluetoothAdapter.STATE_OFF;
并设置了初始状态为PowerOff。有一个mPublicState的变量,这个变量保存状态机最终向外公布的状态。
由上面可以看出,添加的这几个状态都是独立的,没有父状态, 所以转换相对就比较简单了。
2.状态机的转换。
首先进入了PowerOff的状态, 有用户打打开蓝牙,或设置了了开机启动蓝牙,就会收到USER_TURN_ON的消息。这里以开机启动蓝牙为例, 阐释消息如何传递的。
SystemServer:bluetooth.enable();------>BluetoothService:enable()------>mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON, saveSetting);------>
StateMachine:sendMessage()------>mSmHandler.sendMessage(obtainMessage(what,obj));(SmHandler为StateMachine的内部类)--------->SmHandler:handleMessage-------->
SmHandler:processMsg()------->BluetoothAdapterStateMachine:PowerOff:processMessage()。(一)
在PowerOff:processMessage中处理USER_TURN_ON这个消息,做了一些蓝牙启动的准备的动作(调用prepareBluetooth()) ,并且transitionTo(mWarmUp);并且设置了目标状态为WarmUp,这个函数最终是给
SmHandler:mDestState赋值 赋值后SmHandler:mDestState = (mWarmUp)。并且deferMessage(obtainMessage(TURN_ON_CONTINUE));(这个函数会将消息放入SmHandle:mDeferredMessages
中,当实现状态切换的时候会全部派发出去。mDeferredMessages是一个ArrayList)。
接(一)。------->SmHandler:performTransitions----->BluetoothAdapterStateMachine:PowerOff:exit(),BluetoothAdapterStateMachine:WarmUp:enter()(进入了WarmUp了),moveDeferredMessageAtFrontOfQueue();(这个函数
会将mDeferredMessages中存放的消息全部发送出去并清空,比如在现在的流程这里有个TURN_ON_CONTINUE)。----->和上面USER_TURN_ON的消息传递流程一样------>BluetoothAdapterStateMachine:WarmUp:processMessage()(处理TURN_ON_CONTINUE)------>WarmUp:deferMessage(message)(该message为TURN_ON_CONTINUE);(这里是为了等待prepareBluetooth()
这个函数完成,当prepareBluetooth()函数完成后将会发送一个SERVICE_RECORD_LOADED的消息)------>SmHandler:performTransitions()------------->BluetoothAdapterStateMachine:Warmup:exit(),
BluetoothAdapterStateMachine:HotOff:enter()(进入了HotOff了),moveDeferredMessageAtFrontOfQueue();(将会发送TURN_ON_CONTINUE消息)------------>
BluetoothAdapterStateMachine:HotOff:processMessage()-------->mBluetoothService.switchConnectable(true);(这个函数里面发送了一个BluetoothAdapterStateMachine.SCAN_MODE_CHANGED的消息),transitionTo(mSwitching);(设置了目标状态SmHandler:mDestState的值为Switching)-------->SmHandler:performTransitions()---------->
BluetoothAdapterStateMachine:WarmUp:exit(),BluetoothAdapterStateMachine:HotOff:enter()(进入了HotOff了),moveDeferredMessageAtFrontOfQueue();---------->和上面USER_TURN_ON的消息传递流程一样------------->
BluetoothAdapterStateMachine:Switching:processMessage()(处理SCAN_MODE_CHANGED)-------->做一些蓝牙的启动工作后,transitionTo(mBluetoothOn);(目标状态为BluetoothOn)------->SmHandler:performTransitions()---->
BluetoothAdapterStateMachine:Switching:exit(),BluetoothAdapterStateMachine:BluetoothOn:enter()(进入了BluetoothOn状态了),moveDeferredMessageAtFrontOfQueue();。
蓝牙的整个启动过程状态机就是这样,由于不涉及到父状态,所以整个过程还是比较简单的,其他过程可以类比。对于这边文章大家可以参考我的前一篇 Android中的状态机。