android中的一个层次状态机:HierarchicalStateMachine(A2DP)
2011-10-27 14:20
483 查看
介绍的仅是代码跟踪,不是结构描述。感觉结构的话就是通过HierarchicalStateMachine.HsmHandler.StateInfo来维持的吧。子状态上面是父状态,于是形成了类似树一样的结构,每个字节点都只有一个父节点,于是便可以通过类似迷宫算法的逆向遍历来取得状态分支了。
源自跟踪A2dp的连接方法connectSink:在类BluetoothService,
view plainprint?
1. public boolean connectSink(String address) { BluetoothDeviceProfileState state = mDeviceProfileState.get(address); if (state != null) { Message msg = new Message(); msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING; msg.obj = state; mA2dpProfileState.sendMessage(msg); return true; } return false; }
mA2dpProfileState是BluetoothProfileState的实例,而BluetoothProfileState继承自HierarchicalStateMachine。
下面看一下HierarchicalStateMachine类:
这个类只有几个表示名字或状态的常数,除此之外还有一个名为HsmHandler的内部类实例,这个类是Handler的子类,里面有大堆的方法和参数,而HierarchicalStateMachine的真正成员方法里面都是调用这个handler里面的方法。所以此状态机的实现都在这个 handler的类中,因此只需跟踪这个子类的代码即可。
众所周知,直接看代码不如分析流程,所以现在回到主题,跟踪一下
view plainprint?
2.mA2dpProfileState.sendMessage(msg);
这段代码。
mA2dpProfileState初始化在BluetoothService中:
view plainprint?
3.mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP); //... mA2dpProfileState.start();
类BluetoothProfileState构造方法:
view plainprint?
4.public BluetoothProfileState(Context context, int profile) { //... addState(mStableState); addState(mPendingCommandState); setInitialState(mStableState); //... }
addState()是调用的HierarchicalStateMachine中的方法,实际调用:HsmHandler类的addState方法:
view plainprint?
5.private final StateInfo addState(HierarchicalState state, HierarchicalState parent){ //... stateInfo = new StateInfo(); mStateInfo.put(state, stateInfo); //... }
就是把一个状态放在mStateInfo中。我们可以想象,每一个状态机构造的不同state都放到这个HashMap中以供选择了。
在HsmHandler类:
view plainprint?
6.private HashMap<HierarchicalState, StateInfo> mStateInfo = new HashMap<HierarchicalState, StateInfo>();
另外一个方法:
view plainprint?
7.setInitialState(HierarchicalState initialState){mInitialState = initialState;}
这个方法把mInitialState置为传入的状态。
所以,BluetoothProfileState的初始化,做了两件事情:
a>把mStableState和mPendingCommandState这两个HierarchicalState加入到mStateInfo中。
b>把mInitialState设为mStableState。
下面回到 代码3 的mA2dpProfileState.start();
调用的就是HierarchicalStateMachine的start方法,实际调用HsmHandler的方法completeConstruction:
view plainprint?
8.private final void completeConstruction() {
if (mDbg) Log.d(TAG, "completeConstruction: E");
/**
* Determine the maximum depth of the state hierarchy
* so we can allocate the state stacks.
*/
int maxDepth = 0;
for (StateInfo si : mStateInfo.values()) {
int depth = 0;
for (StateInfo i = si; i != null; depth++) {
i = i.parentStateInfo;
}
if (maxDepth < depth) {
maxDepth = depth;
}
}
if (mDbg) Log.d(TAG, "completeConstruction: maxDepth=" + maxDepth);
mStateStack = new StateInfo[maxDepth];
mTempStateStack = new StateInfo[maxDepth];
setupInitialStateStack();
/**
* Construction is complete call all enter methods
* starting at the first entry.
*/
mIsConstructionCompleted = true;
mMsg = obtainMessage(HSM_INIT_CMD);
invokeEnterMethods(0);
/**
* Perform any transitions requested by the enter methods
*/
performTransitions();
if (mDbg) Log.d(TAG, "completeConstruction: X");
}
首先,从mStateInfo中查找长度最长的(状态最多的那条分支),该长度作为数组mStateStack的大小。而本例中所有状态都没有父状态所以最大长度应为1.
mStateStack这个东西就是一个数组,里面装的是某个状态(StateInfo)(这个状态在状态机初始化的时候取值为mInitialState)
的分支(状态的父状态或者子状态的父状态或者子状态 ..and so on)。
setupInitialStateStack().//这个方法显然就是从mStateInfo中取出某个状态然后把这个状态的分支放在了mStateStack数组中了。
invokeEnterMethods(0);//这个方法就是调用当前mStateStack中所有状态的enter方法并且把active设为true。
performTransitions();//由于初始状态mDestState为null,所以此时不做任何处理。
然后初始化完成,等待接收新状态了。
此时完成的内容是:
a>把mInitialState即mStableState放到了mStateStack中。
b>调用mStateStack中所有状态的enter方法。本例中则调用类:BluetoothProfileState.StableState的enter方法:
view plainprint?
9.mPendingDevice = null;
现在BluetoothProfileState这个状态机初始化完了。开始接收消息了。为了跟上面的初始化过程衔接起来,假设我们A2dp的连接请求是初始化之后的第一次请求。回到代码1:
首先构造了一个Message,然后调用状态机的SendMessage方法。回到BluetoothProfileState中并未找到该方法,
说明没有覆盖,则调用的是HierarchicalStateMachine的相同方法:
类HierarchicalStateMachine:
view plainprint?
10.public final void sendMessage(Message msg) {
mHsmHandler.sendMessage(msg);
}
类:HsmHandler
view plainprint?
11.public final void handleMessage(Message msg) {//msg.what = null
if (mDbg) Log.d(TAG, "handleMessage: E msg.what=" + msg.what);
/** Save the current message */
mMsg = msg;
/**
* Check that construction was completed
*/
if (!mIsConstructionCompleted) {
Log.e(TAG, "The start method not called, ignore msg: " + msg);
return;
}
/**
* Process the message abiding by the hierarchical semantics
* and perform any requested transitions.
*/
processMsg(msg);
performTransitions();
if (mDbg) Log.d(TAG, "handleMessage: X");
}
首先设置mMsg为传入msg,调用processMsg();
类 HsmHandler:
view plainprint?
12.private final void processMsg(Message msg) {
StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
if (mDbg) {
Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
}
while (!curStateInfo.state.processMessage(msg)) {//it is true, skip this scope
/**
* Not processed
*/
curStateInfo = curStateInfo.parentStateInfo;
if (curStateInfo == null) {
/**
* No parents left so it's not handled
*/
mHsm.unhandledMessage(msg);
if (isQuit(msg)) {
transitionTo(mQuittingState);
}
break;
}
if (mDbg) {
Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
}
}
/**
* Record that we processed the message
*/
if (curStateInfo != null) {
HierarchicalState orgState = mStateStack[mStateStackTopIndex].state;
mProcessedMessages.add(msg, curStateInfo.state, orgState);
} else {
mProcessedMessages.add(msg, null, null);
}
}
看这句话:curStateInfo.state.processMessage(msg);curStateInfo是mStateStack中的栈顶元素,从刚才初始化中我们知道,此时mStateStack中装的是mStableState。
因此调用BluetoothProfileState.StableState.processMessage(msg);
类BluetoothProfileState.StableState:
view plainprint?
13.protected boolean processMessage(Message msg) {
if (msg.what != TRANSITION_TO_STABLE) {
transitionTo(mPendingCommandState);//it is the mDestState in HierarchicalStateMachine,the initState is mStableState
}
return true;
}
从代码1中知道,msg.what显然不是TRANSITION_TO_STABLE,所以调用了
transitionTo(mPendingCommandState),transitionTo方法在
HierarchicalStateMachine.HsmHandler类中;
把mDestState这个成员变量设为mPendingCommandState。完了。没有了,可能是忘了。
回到代码11,发现还有一个方法没有执行呢。刚才我们处理的是processMsg方法。那么接下来,方法:HierarchicalStateMachine.HsmHandler.performTransitions():
view plainprint?
14.private void performTransitions() { /** * If transitionTo has been called, exit and then enter * the appropriate states. We loop on this to allow * enter and exit methods to use transitionTo. */ HierarchicalState destState = null; while (mDestState != null) { if (mDbg) Log.d(TAG, "handleMessage: new destination call exit"); /** * Save mDestState locally and set to null * to know if enter/exit use transitionTo. */ destState = mDestState; mDestState = null; /** * Determine the states to exit and enter and return the * common ancestor state of the enter/exit states. Then * invoke the exit methods then the enter methods. */ StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState); invokeExitMethods(commonStateInfo); int stateStackEnteringIndex = moveTempStateStackToStateStack(); invokeEnterMethods(stateStackEnteringIndex); /** * Since we have transitioned to a new state we need to have * any deferred messages moved to the front of the message queue * so they will be processed before any other messages in the * message queue. */ moveDeferredMessageAtFrontOfQueue(); }
[b]那么这一次这条原因则不成立,因为刚才我们通过transitionTo方法把mDestState已经变成了mPendingCommandState。[/b]
[b]这个方法做了什么呢?
>把mDestState赋给临时状态,然后置空;
>调用setupTempStateStackWithStatesToEnter(destState);把destState的状态分支都放到临时状态栈:mTempStateStack中,[/b]
[b]刚才忘记说了,这个临时栈跟mStateStack结构相同,每次有不同时序的处理的时候起到辅助作用,[/b]
[b]由于在本例中作用不明显未做深究;
>然后mStateStack中的所有状态调用exit方法,active置为false;
>调用mStateStack中所有状态的enter方法。本例中即调用:BluetoothProfileState.PendingCommandState.enter():[/b]
view plainprint?
15.protected void enter() { log("Entering PendingCommandState State"); dispatchMessage(getCurrentMessage());// log(getCurrentMessage()); }
getCurrentMessage得到的就是mMsg即 代码11 中传入的消息,也就是本次调用要处理的消息。然后调用BluetoothProfileState.PendingCommandState.dispatchMessage():
view plainprint?
16.private void dispatchMessage(Message msg) { BluetoothDeviceProfileState deviceProfileMgr = (BluetoothDeviceProfileState)msg.obj; int cmd = msg.arg1; if (mPendingDevice == null || mPendingDevice.equals(deviceProfileMgr.getDevice())) { mPendingDevice = deviceProfileMgr.getDevice(); deviceProfileMgr.sendMessage(cmd); } else { Message deferMsg = new Message(); deferMsg.arg1 = cmd; deferMsg.obj = deviceProfileMgr; deferMessage(deferMsg); } }
首先,BluetoothDeviceProfileState deviceProfileMgr;回到代码1 查看msg.obj发现这个变量的值为
mDeviceProfileState.get(address);
address则为要连接音频设备的mac,mDeviceProfileState是一个hashMap储存了不同设备mac地址及设备协议状态。
它的初始化及赋值什么的都在BluetoothService中,这个hashMap里的值来自两个方面:
一是在蓝牙打开时把已经配对的设备,加到里面;
二是配对成功后,把相应设备加到这个hashMap中。
因此,每个设备对应了一个deviceProfileMgr,即BluetoothDeviceProfileState,这也是个状态机,先放在这里,我们等会再看。
接下来判断:if (mPendingDevice == null || mPendingDevice.equals(deviceProfileMgr.getDevice()))
哦,记得之前把mPengingDevice置为空过,在 代码 9中:
[b]判断条件符合mPendingDevice置为当前device,然后deviceProfileMgr.sendMessage(cmd);[/b]
然后,没了。
只剩下了 deviceProfileMgr.sendMessage(cmd);
不过这个形式挺眼熟,之前好想见到过,见 代码1.
mA2dpProfileState.sendMessage(msg);
只不过mA2dpProfileState换成了deviceProfileMgr,状态机由BluetoothProfileState换成了BluetoothDeviceProfileState。
其他的真的一点变化都没有,于是也就不用分析了。跟上面一样。
追到最后发现,其实connectSink方法最后调用:
BluetoothA2dpService.connectSinkInternal(BluetoothDevice device)
-------------------------------------------------
总结:状态机发送一个msg,通过父类HierarchicalStateMachine的成员handler中的handleMessage处理,
然后调用processMsg,实际调用的是mStateStack中存储的state的processMessage方法,然后调用performTransitions方法,
检测mDestState是否为空,不为空则将当前mStateStack的状态全部调用exit方法且avtive置为false,
然后把mDestState的状态分支都放进mStateStack中,调用这些状态的enter方法,且把active置为true。
更简单一点就是,状态机发送msg--->mStateStack--当前状态分支的exit方法--->调用mDestState状态分支的enter方法
-->其中msg里面的参数,会存在mMsg中可以通过getCurrentMsg来取得之。
源自跟踪A2dp的连接方法connectSink:在类BluetoothService,
view plainprint?
1. public boolean connectSink(String address) { BluetoothDeviceProfileState state = mDeviceProfileState.get(address); if (state != null) { Message msg = new Message(); msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING; msg.obj = state; mA2dpProfileState.sendMessage(msg); return true; } return false; }
1. public boolean connectSink(String address) { BluetoothDeviceProfileState state = mDeviceProfileState.get(address); if (state != null) { Message msg = new Message(); msg.arg1 = BluetoothDeviceProfileState.CONNECT_A2DP_OUTGOING; msg.obj = state; mA2dpProfileState.sendMessage(msg); return true; } return false; }
mA2dpProfileState是BluetoothProfileState的实例,而BluetoothProfileState继承自HierarchicalStateMachine。
下面看一下HierarchicalStateMachine类:
这个类只有几个表示名字或状态的常数,除此之外还有一个名为HsmHandler的内部类实例,这个类是Handler的子类,里面有大堆的方法和参数,而HierarchicalStateMachine的真正成员方法里面都是调用这个handler里面的方法。所以此状态机的实现都在这个 handler的类中,因此只需跟踪这个子类的代码即可。
众所周知,直接看代码不如分析流程,所以现在回到主题,跟踪一下
view plainprint?
2.mA2dpProfileState.sendMessage(msg);
2.mA2dpProfileState.sendMessage(msg);
这段代码。
mA2dpProfileState初始化在BluetoothService中:
view plainprint?
3.mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP); //... mA2dpProfileState.start();
3.mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP); //... mA2dpProfileState.start();
类BluetoothProfileState构造方法:
view plainprint?
4.public BluetoothProfileState(Context context, int profile) { //... addState(mStableState); addState(mPendingCommandState); setInitialState(mStableState); //... }
4.public BluetoothProfileState(Context context, int profile) { //... addState(mStableState); addState(mPendingCommandState); setInitialState(mStableState); //... }
addState()是调用的HierarchicalStateMachine中的方法,实际调用:HsmHandler类的addState方法:
view plainprint?
5.private final StateInfo addState(HierarchicalState state, HierarchicalState parent){ //... stateInfo = new StateInfo(); mStateInfo.put(state, stateInfo); //... }
5.private final StateInfo addState(HierarchicalState state, HierarchicalState parent){ //... stateInfo = new StateInfo(); mStateInfo.put(state, stateInfo); //... }
就是把一个状态放在mStateInfo中。我们可以想象,每一个状态机构造的不同state都放到这个HashMap中以供选择了。
在HsmHandler类:
view plainprint?
6.private HashMap<HierarchicalState, StateInfo> mStateInfo = new HashMap<HierarchicalState, StateInfo>();
6.private HashMap<HierarchicalState, StateInfo> mStateInfo = new HashMap<HierarchicalState, StateInfo>();
另外一个方法:
view plainprint?
7.setInitialState(HierarchicalState initialState){mInitialState = initialState;}
7.setInitialState(HierarchicalState initialState){mInitialState = initialState;}
这个方法把mInitialState置为传入的状态。
所以,BluetoothProfileState的初始化,做了两件事情:
a>把mStableState和mPendingCommandState这两个HierarchicalState加入到mStateInfo中。
b>把mInitialState设为mStableState。
下面回到 代码3 的mA2dpProfileState.start();
调用的就是HierarchicalStateMachine的start方法,实际调用HsmHandler的方法completeConstruction:
view plainprint?
8.private final void completeConstruction() {
if (mDbg) Log.d(TAG, "completeConstruction: E");
/**
* Determine the maximum depth of the state hierarchy
* so we can allocate the state stacks.
*/
int maxDepth = 0;
for (StateInfo si : mStateInfo.values()) {
int depth = 0;
for (StateInfo i = si; i != null; depth++) {
i = i.parentStateInfo;
}
if (maxDepth < depth) {
maxDepth = depth;
}
}
if (mDbg) Log.d(TAG, "completeConstruction: maxDepth=" + maxDepth);
mStateStack = new StateInfo[maxDepth];
mTempStateStack = new StateInfo[maxDepth];
setupInitialStateStack();
/**
* Construction is complete call all enter methods
* starting at the first entry.
*/
mIsConstructionCompleted = true;
mMsg = obtainMessage(HSM_INIT_CMD);
invokeEnterMethods(0);
/**
* Perform any transitions requested by the enter methods
*/
performTransitions();
if (mDbg) Log.d(TAG, "completeConstruction: X");
}
8.private final void completeConstruction() { if (mDbg) Log.d(TAG, "completeConstruction: E"); /** * Determine the maximum depth of the state hierarchy * so we can allocate the state stacks. */ int maxDepth = 0; for (StateInfo si : mStateInfo.values()) { int depth = 0; for (StateInfo i = si; i != null; depth++) { i = i.parentStateInfo; } if (maxDepth < depth) { maxDepth = depth; } } if (mDbg) Log.d(TAG, "completeConstruction: maxDepth=" + maxDepth); mStateStack = new StateInfo[maxDepth]; mTempStateStack = new StateInfo[maxDepth]; setupInitialStateStack(); /** * Construction is complete call all enter methods * starting at the first entry. */ mIsConstructionCompleted = true; mMsg = obtainMessage(HSM_INIT_CMD); invokeEnterMethods(0); /** * Perform any transitions requested by the enter methods */ performTransitions(); if (mDbg) Log.d(TAG, "completeConstruction: X"); }
首先,从mStateInfo中查找长度最长的(状态最多的那条分支),该长度作为数组mStateStack的大小。而本例中所有状态都没有父状态所以最大长度应为1.
mStateStack这个东西就是一个数组,里面装的是某个状态(StateInfo)(这个状态在状态机初始化的时候取值为mInitialState)
的分支(状态的父状态或者子状态的父状态或者子状态 ..and so on)。
setupInitialStateStack().//这个方法显然就是从mStateInfo中取出某个状态然后把这个状态的分支放在了mStateStack数组中了。
invokeEnterMethods(0);//这个方法就是调用当前mStateStack中所有状态的enter方法并且把active设为true。
performTransitions();//由于初始状态mDestState为null,所以此时不做任何处理。
然后初始化完成,等待接收新状态了。
此时完成的内容是:
a>把mInitialState即mStableState放到了mStateStack中。
b>调用mStateStack中所有状态的enter方法。本例中则调用类:BluetoothProfileState.StableState的enter方法:
view plainprint?
9.mPendingDevice = null;
9.mPendingDevice = null;
现在BluetoothProfileState这个状态机初始化完了。开始接收消息了。为了跟上面的初始化过程衔接起来,假设我们A2dp的连接请求是初始化之后的第一次请求。回到代码1:
首先构造了一个Message,然后调用状态机的SendMessage方法。回到BluetoothProfileState中并未找到该方法,
说明没有覆盖,则调用的是HierarchicalStateMachine的相同方法:
类HierarchicalStateMachine:
view plainprint?
10.public final void sendMessage(Message msg) {
mHsmHandler.sendMessage(msg);
}
10.public final void sendMessage(Message msg) { mHsmHandler.sendMessage(msg); }调用了Handler的sendMessage,原来是Handler机制,所以,该消息由类HsmHandler的handleMessage()方法来处理此消息:
类:HsmHandler
view plainprint?
11.public final void handleMessage(Message msg) {//msg.what = null
if (mDbg) Log.d(TAG, "handleMessage: E msg.what=" + msg.what);
/** Save the current message */
mMsg = msg;
/**
* Check that construction was completed
*/
if (!mIsConstructionCompleted) {
Log.e(TAG, "The start method not called, ignore msg: " + msg);
return;
}
/**
* Process the message abiding by the hierarchical semantics
* and perform any requested transitions.
*/
processMsg(msg);
performTransitions();
if (mDbg) Log.d(TAG, "handleMessage: X");
}
11.public final void handleMessage(Message msg) {//msg.what = null if (mDbg) Log.d(TAG, "handleMessage: E msg.what=" + msg.what); /** Save the current message */ mMsg = msg; /** * Check that construction was completed */ if (!mIsConstructionCompleted) { Log.e(TAG, "The start method not called, ignore msg: " + msg); return; } /** * Process the message abiding by the hierarchical semantics * and perform any requested transitions. */ processMsg(msg); performTransitions(); if (mDbg) Log.d(TAG, "handleMessage: X"); }
首先设置mMsg为传入msg,调用processMsg();
类 HsmHandler:
view plainprint?
12.private final void processMsg(Message msg) {
StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
if (mDbg) {
Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
}
while (!curStateInfo.state.processMessage(msg)) {//it is true, skip this scope
/**
* Not processed
*/
curStateInfo = curStateInfo.parentStateInfo;
if (curStateInfo == null) {
/**
* No parents left so it's not handled
*/
mHsm.unhandledMessage(msg);
if (isQuit(msg)) {
transitionTo(mQuittingState);
}
break;
}
if (mDbg) {
Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
}
}
/**
* Record that we processed the message
*/
if (curStateInfo != null) {
HierarchicalState orgState = mStateStack[mStateStackTopIndex].state;
mProcessedMessages.add(msg, curStateInfo.state, orgState);
} else {
mProcessedMessages.add(msg, null, null);
}
}
12.private final void processMsg(Message msg) { StateInfo curStateInfo = mStateStack[mStateStackTopIndex]; if (mDbg) { Log.d(TAG, "processMsg: " + curStateInfo.state.getName()); } while (!curStateInfo.state.processMessage(msg)) {//it is true, skip this scope /** * Not processed */ curStateInfo = curStateInfo.parentStateInfo; if (curStateInfo == null) { /** * No parents left so it's not handled */ mHsm.unhandledMessage(msg); if (isQuit(msg)) { transitionTo(mQuittingState); } break; } if (mDbg) { Log.d(TAG, "processMsg: " + curStateInfo.state.getName()); } } /** * Record that we processed the message */ if (curStateInfo != null) { HierarchicalState orgState = mStateStack[mStateStackTopIndex].state; mProcessedMessages.add(msg, curStateInfo.state, orgState); } else { mProcessedMessages.add(msg, null, null); } }
看这句话:curStateInfo.state.processMessage(msg);curStateInfo是mStateStack中的栈顶元素,从刚才初始化中我们知道,此时mStateStack中装的是mStableState。
因此调用BluetoothProfileState.StableState.processMessage(msg);
类BluetoothProfileState.StableState:
view plainprint?
13.protected boolean processMessage(Message msg) {
if (msg.what != TRANSITION_TO_STABLE) {
transitionTo(mPendingCommandState);//it is the mDestState in HierarchicalStateMachine,the initState is mStableState
}
return true;
}
13.protected boolean processMessage(Message msg) { if (msg.what != TRANSITION_TO_STABLE) { transitionTo(mPendingCommandState);//it is the mDestState in HierarchicalStateMachine,the initState is mStableState } return true; }
从代码1中知道,msg.what显然不是TRANSITION_TO_STABLE,所以调用了
transitionTo(mPendingCommandState),transitionTo方法在
HierarchicalStateMachine.HsmHandler类中;
把mDestState这个成员变量设为mPendingCommandState。完了。没有了,可能是忘了。
回到代码11,发现还有一个方法没有执行呢。刚才我们处理的是processMsg方法。那么接下来,方法:HierarchicalStateMachine.HsmHandler.performTransitions():
view plainprint?
14.private void performTransitions() { /** * If transitionTo has been called, exit and then enter * the appropriate states. We loop on this to allow * enter and exit methods to use transitionTo. */ HierarchicalState destState = null; while (mDestState != null) { if (mDbg) Log.d(TAG, "handleMessage: new destination call exit"); /** * Save mDestState locally and set to null * to know if enter/exit use transitionTo. */ destState = mDestState; mDestState = null; /** * Determine the states to exit and enter and return the * common ancestor state of the enter/exit states. Then * invoke the exit methods then the enter methods. */ StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState); invokeExitMethods(commonStateInfo); int stateStackEnteringIndex = moveTempStateStackToStateStack(); invokeEnterMethods(stateStackEnteringIndex); /** * Since we have transitioned to a new state we need to have * any deferred messages moved to the front of the message queue * so they will be processed before any other messages in the * message queue. */ moveDeferredMessageAtFrontOfQueue(); }
14.private void performTransitions() { /** * If transitionTo has been called, exit and then enter * the appropriate states. We loop on this to allow * enter and exit methods to use transitionTo. */ HierarchicalState destState = null; while (mDestState != null) { if (mDbg) Log.d(TAG, "handleMessage: new destination call exit"); /** * Save mDestState locally and set to null * to know if enter/exit use transitionTo. */ destState = mDestState; mDestState = null; /** * Determine the states to exit and enter and return the * common ancestor state of the enter/exit states. Then * invoke the exit methods then the enter methods. */ StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState); invokeExitMethods(commonStateInfo); int stateStackEnteringIndex = moveTempStateStackToStateStack(); invokeEnterMethods(stateStackEnteringIndex); /** * Since we have transitioned to a new state we need to have * any deferred messages moved to the front of the message queue * so they will be processed before any other messages in the * message queue. */ moveDeferredMessageAtFrontOfQueue(); }记得刚才在状态机初始化的时候见过这个方法,不过好像因为有些原因没有任何处理,是什么原因呢,mDestState为空?
[b]那么这一次这条原因则不成立,因为刚才我们通过transitionTo方法把mDestState已经变成了mPendingCommandState。[/b]
[b]这个方法做了什么呢?
>把mDestState赋给临时状态,然后置空;
>调用setupTempStateStackWithStatesToEnter(destState);把destState的状态分支都放到临时状态栈:mTempStateStack中,[/b]
[b]刚才忘记说了,这个临时栈跟mStateStack结构相同,每次有不同时序的处理的时候起到辅助作用,[/b]
[b]由于在本例中作用不明显未做深究;
>然后mStateStack中的所有状态调用exit方法,active置为false;
>调用mStateStack中所有状态的enter方法。本例中即调用:BluetoothProfileState.PendingCommandState.enter():[/b]
view plainprint?
15.protected void enter() { log("Entering PendingCommandState State"); dispatchMessage(getCurrentMessage());// log(getCurrentMessage()); }
15.protected void enter() { log("Entering PendingCommandState State"); dispatchMessage(getCurrentMessage());// log(getCurrentMessage()); }
getCurrentMessage得到的就是mMsg即 代码11 中传入的消息,也就是本次调用要处理的消息。然后调用BluetoothProfileState.PendingCommandState.dispatchMessage():
view plainprint?
16.private void dispatchMessage(Message msg) { BluetoothDeviceProfileState deviceProfileMgr = (BluetoothDeviceProfileState)msg.obj; int cmd = msg.arg1; if (mPendingDevice == null || mPendingDevice.equals(deviceProfileMgr.getDevice())) { mPendingDevice = deviceProfileMgr.getDevice(); deviceProfileMgr.sendMessage(cmd); } else { Message deferMsg = new Message(); deferMsg.arg1 = cmd; deferMsg.obj = deviceProfileMgr; deferMessage(deferMsg); } }
16.private void dispatchMessage(Message msg) { BluetoothDeviceProfileState deviceProfileMgr = (BluetoothDeviceProfileState)msg.obj; int cmd = msg.arg1; if (mPendingDevice == null || mPendingDevice.equals(deviceProfileMgr.getDevice())) { mPendingDevice = deviceProfileMgr.getDevice(); deviceProfileMgr.sendMessage(cmd); } else { Message deferMsg = new Message(); deferMsg.arg1 = cmd; deferMsg.obj = deviceProfileMgr; deferMessage(deferMsg); } }
首先,BluetoothDeviceProfileState deviceProfileMgr;回到代码1 查看msg.obj发现这个变量的值为
mDeviceProfileState.get(address);
address则为要连接音频设备的mac,mDeviceProfileState是一个hashMap储存了不同设备mac地址及设备协议状态。
它的初始化及赋值什么的都在BluetoothService中,这个hashMap里的值来自两个方面:
一是在蓝牙打开时把已经配对的设备,加到里面;
二是配对成功后,把相应设备加到这个hashMap中。
因此,每个设备对应了一个deviceProfileMgr,即BluetoothDeviceProfileState,这也是个状态机,先放在这里,我们等会再看。
接下来判断:if (mPendingDevice == null || mPendingDevice.equals(deviceProfileMgr.getDevice()))
哦,记得之前把mPengingDevice置为空过,在 代码 9中:
[b]判断条件符合mPendingDevice置为当前device,然后deviceProfileMgr.sendMessage(cmd);[/b]
然后,没了。
只剩下了 deviceProfileMgr.sendMessage(cmd);
不过这个形式挺眼熟,之前好想见到过,见 代码1.
mA2dpProfileState.sendMessage(msg);
只不过mA2dpProfileState换成了deviceProfileMgr,状态机由BluetoothProfileState换成了BluetoothDeviceProfileState。
其他的真的一点变化都没有,于是也就不用分析了。跟上面一样。
追到最后发现,其实connectSink方法最后调用:
BluetoothA2dpService.connectSinkInternal(BluetoothDevice device)
-------------------------------------------------
总结:状态机发送一个msg,通过父类HierarchicalStateMachine的成员handler中的handleMessage处理,
然后调用processMsg,实际调用的是mStateStack中存储的state的processMessage方法,然后调用performTransitions方法,
检测mDestState是否为空,不为空则将当前mStateStack的状态全部调用exit方法且avtive置为false,
然后把mDestState的状态分支都放进mStateStack中,调用这些状态的enter方法,且把active置为true。
更简单一点就是,状态机发送msg--->mStateStack--当前状态分支的exit方法--->调用mDestState状态分支的enter方法
-->其中msg里面的参数,会存在mMsg中可以通过getCurrentMsg来取得之。
相关文章推荐
- Java Secret: Using an enum to build a State machine(Java秘术:用枚举构建一个状态机)
- Java Secret: Using an enum to build a State machine(Java秘术:用枚举构建一个状态机)
- HierarchicalStateMachine(HandlerStateMachine)分析
- SharePoint 2010 自定义状态机工作流(StateMachine Workflow) + InfoPath 实例part2 (InfoPath设计部分及演示效果)
- Android StateListDrawable与透明度Alpha相关的一个bug
- Android之层次statelist属性
- quick StateMachine 状态机的使用
- HierarchicalStateMachine(HandlerStateMachine)分析
- Android在代码中打开切换wif失败:WifiStateMachine: Not authorized to update network
- Unity-Animator深入系列---StateMachineBehaviour状态机脚本学习
- Android wifi-framework StateMachine和AsyncChannel 学习
- Android StateMachine和AsyncChannel
- SharePoint 2010 自定义状态机工作流 (StateMachine Workflow) + InfoPath 实例part1 (工作流实现部分)
- Android StateMachine 学习笔记
- /drivers/net/phy/phy.c的状态机phy_state_machine分析
- Android学习 StateMachine与State模式(状态机)
- 《WF编程》系列之34 - 基本活动:状态活动 到目前为止,我们所讨论的工作流都是顺序工作流,而WF还支持另外一种工作流机制-状态机(State-Machine)工作流,本节就来介绍这些在状态机工作流中工作的活动.
- Spring-statemachine fork一个region后不能进入join状态的问题
- Android学习札记36:一个关于onSaveInstanceState ()方法的例子
- 关于PVFS状态机的声明和定义---src/common/misc/state-machine.h