StatMachine的start方法用于启动状态机,代码如下:
//frameworks/base/core/java/com/android/internal/util/StateMachine.java
public class StateMachine {
private SmHandler mSmHandler;
public void start() {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
/** Send the complete construction message */
smh.completeConstruction();
}
}
SmHandler completeConstruction
调用SmHandler的completeConstruction方法:
//frameworks/base/core/java/com/android/internal/util/StateMachine.java
public class StateMachine {
private static class SmHandler extends Handler {
/** Stack used to manage the current hierarchy of states */
private StateInfo mStateStack[];
/** A temporary stack used to manage the state stack */
private StateInfo mTempStateStack[];
/** The map of all of the states in the state machine */
private HashMap<State, StateInfo> mStateInfo = new HashMap<State, StateInfo>();
private final void completeConstruction() {
if (mDbg) mSm.log("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()) { //遍历取出状态机中通过addState方法加入的,所有的状态。
int depth = 0;
for (StateInfo i = si; i != null; depth++) {
i = i.parentStateInfo;
}
if (maxDepth < depth) {
maxDepth = depth; //求出树的深度
}
}
if (mDbg) mSm.log("completeConstruction: maxDepth=" + maxDepth);
mStateStack = new StateInfo[maxDepth]; //创建StateInfo类型的数组,作为状态堆栈
mTempStateStack = new StateInfo[maxDepth]; //创建StateInfo类型的数组,作为状态临时堆栈
setupInitialStateStack();
/** Sending SM_INIT_CMD message to invoke enter methods asynchronously */
sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));
if (mDbg) mSm.log("completeConstruction: X");
}
}
}
上面方法主要处理如下:
1、创建StateInfo类型的数组,作为状态堆栈
2、创建StateInfo类型的数组,作为状态临时堆栈
3、调用setupInitialStateStack方法,初始化堆栈
4、调用obtainMessage方法,获取消息并设置 Message.target 状态机处理程序、what 和 obj
5、调用sendMessageAtFrontOfQueue方法,发送SM_INIT_CMD消息
下面分别进行分析:
setupInitialStateStack
调用setupInitialStateStack方法,初始化堆栈:
//frameworks/base/core/java/com/android/internal/util/StateMachine.java
public class StateMachine {
private static class SmHandler extends Handler {
/** The top of the mTempStateStack */
private int mTempStateStackCount;
/** A temporary stack used to manage the state stack */
private StateInfo mTempStateStack[];
private final void setupInitialStateStack() {
if (mDbg) {
mSm.log("setupInitialStateStack: E mInitialState=" + mInitialState.getName());
}
StateInfo curStateInfo = mStateInfo.get(mInitialState); //获取初始状态对应的StateInfo
for (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {
mTempStateStack[mTempStateStackCount] = curStateInfo;
curStateInfo = curStateInfo.parentStateInfo;
}
// Empty the StateStack
mStateStackTopIndex = -1;
moveTempStateStackToStateStack(); //将mTempStateStack[]数组的值倒序付给了mStateStack[]数组并且设置了 mStateStackTopIndex(栈顶序列号)的值为数组的最大下标,方便在ProcessMsg()时取出的state为栈顶元素。
}
}
}
setupInitialStateStack(); 这个方法首先初始化了mTempStateStack[]数组()(树根保存在数组下标最大的那个元素上),然后又通过函数moveTempStateStackToStateStack()将mTempStateStack[]数组的值倒序付给了mStateStack[]数组并且设置了 mStateStackTopIndex(栈顶序列号)的值为数组的最大下标,方便在ProcessMsg()时取出的state为栈顶元素。
mTempStateStack[]数组保存的是当前正在处理的树叶状态的所有父亲,且树根总是保存在数组下标最大的单元里;它是中间进行值操作所用的。
mStateStack[]数组是mTempStateStack[]元素的反向保存,所以,树根永远保存在小标为0的单元里。且它是最终应用的state。
StateMachine obtainMessage
调用obtainMessage方法,获取消息并设置 Message.target 状态机处理程序、what 和 obj
//frameworks/base/core/java/com/android/internal/util/StateMachine.java
public class StateMachine {
public final Message obtainMessage(int what, int arg1, int arg2, @Nullable Object obj) {
return Message.obtain(this, what, arg1, arg2, obj);
}
}
Message obtain
调用Message的obtain方法,创建Message。
handleMessage
调用Handle的sendMessageAtFrontOfQueue方法,将SM_INIT_CMD消息排在消息队列的前面,以便在消息循环的下一次迭代中进行处理,发送的消息会在StateMachine的handleMessage方法中处理:
//frameworks/base/core/java/com/android/internal/util/StateMachine.java
public class StateMachine {
/** true if construction of the state machine has not been completed */
private boolean mIsConstructionCompleted;
//通过调用当前状态的 processMessage 来处理发送到状态机的消息。它还处理进入/退出调用,并在转换到新状态时将任何延迟的消息放回队列。
@Override
public final void handleMessage(Message msg) {
if (!mHasQuit) {
if (mSm != null && msg.what != SM_INIT_CMD && msg.what != SM_QUIT_CMD) {
mSm.onPreHandleMessage(msg);
}
if (mDbg) mSm.log("handleMessage: E msg.what=" + msg.what);
/** Save the current message */
mMsg = msg;
/** State that processed the message */
State msgProcessedState = null;
if (mIsConstructionCompleted || (mMsg.what == SM_QUIT_CMD)) {
/** Normal path */
msgProcessedState = processMsg(msg);
} else if (!mIsConstructionCompleted && (mMsg.what == SM_INIT_CMD)
&& (mMsg.obj == mSmHandlerObj)) {
/** Initial one time path. */
mIsConstructionCompleted = true; //将mIsConstructionCompleted 变量设置为true,目前是自调用invokeEnterMethods一次
invokeEnterMethods(0);
} else {
throw new RuntimeException("StateMachine.handleMessage: "
+ "The start method not called, received msg: " + msg);
}
performTransitions(msgProcessedState, msg);
// We need to check if mSm == null here as we could be quitting.
if (mDbg && mSm != null) mSm.log("handleMessage: X");
if (mSm != null && msg.what != SM_INIT_CMD && msg.what != SM_QUIT_CMD) {
mSm.onPostHandleMessage(msg);
}
}
}
}
}
上面方法主要处理如下:
1、调用invokeEnterMethods方法,只在start时执行一次。
2、调用processMsg处理消息,消息包括SM_QUIT_CMD(调用quit或quitNow发送的消息,也包括调用sendMessage发送的消息)。
3、调用performTransitions方法,消息处理完毕状态切换,更新mStateStack。
下面分别进行分析:
invokeEnterMethods
调用invokeEnterMethods方法,从stateStackEnteringIndex向栈顶依次执行enter方法并设Active为true:
//frameworks/base/core/java/com/android/internal/util/StateMachine.java
public class StateMachine {
private static class SmHandler extends Handler {
private final void invokeEnterMethods(int stateStackEnteringIndex) {
for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
if (stateStackEnteringIndex == mStateStackTopIndex) {
// Last enter state for transition
mTransitionInProgress = false;
}
if (mDbg) mSm.log("invokeEnterMethods: " + mStateStack[i].state.getName());
mStateStack[i].state.enter(); //从stateStackEnteringIndex向栈顶依次执行enter方法
mStateStack[i].active = true; //并设Active为true
}
mTransitionInProgress = false; // ensure flag set to false if no methods called
}
}
}
processMsg
调用processMsg处理消息,消息包括SM_QUIT_CMD(调用quit或quitNow发送的消息,也包括调用sendMessage发送的消息):
//frameworks/base/core/java/com/android/internal/util/StateMachine.java
public class StateMachine {
private static class SmHandler extends Handler {
private final State processMsg(Message msg) {
StateInfo curStateInfo = mStateStack[mStateStackTopIndex]; //从栈顶中取出当前StateInfo
if (mDbg) {
mSm.log("processMsg: " + curStateInfo.state.getName());
}
if (isQuit(msg)) {
transitionTo(mQuittingState);
} else {
while (!curStateInfo.state.processMessage(msg)) { //调用当前StateInfo的state的processMessage方法
/**
* Not processed
*/
curStateInfo = curStateInfo.parentStateInfo; //如果当前状态的processMessage的返回为false,将curStateInfo赋值为当前状态的父状态的curStateInfo,然后继续调用父状态的processMessage方法
if (curStateInfo == null) {
/**
* No parents left so it's not handled
*/
mSm.unhandledMessage(msg); //直到没有父状态,调用unhandledMessage方法
break;
}
if (mDbg) {
mSm.log("processMsg: " + curStateInfo.state.getName());
}
}
}
return (curStateInfo != null) ? curStateInfo.state : null;
}
}
}
performTransitions
调用performTransitions方法,消息处理完毕状态切换,更新mStateStack:
//frameworks/base/core/java/com/android/internal/util/StateMachine.java
public class StateMachine {
private static class SmHandler extends Handler {
private void performTransitions(State msgProcessedState, Message msg) {
/**
* 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.
*/
State orgState = mStateStack[mStateStackTopIndex].state;
/**
* Record whether message needs to be logged before we transition and
* and we won't log special messages SM_INIT_CMD or SM_QUIT_CMD which
* always set msg.obj to the handler.
*/
boolean recordLogMsg = mSm.recordLogRec(mMsg) && (msg.obj != mSmHandlerObj);
if (mLogRecords.logOnlyTransitions()) {
/** Record only if there is a transition */
if (mDestState != null) {
mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState,
orgState, mDestState);
}
} else if (recordLogMsg) {
/** Record message */
mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState, orgState,
mDestState);
}
State destState = mDestState;
if (destState != null) {
/**
* Process the transitions including transitions in the enter/exit methods
*/
while (true) {
if (mDbg) mSm.log("handleMessage: new destination call exit/enter");
/**
* 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); // 逐次向上查找destState的所有祖先直到该祖先的stateInfo.Active为true才停止,并将值放到mTempStateStake 里面,树根对应下标最大的,commonstateInfo为该祖先的 stateInfor属性,在这个函数里面也将mTempStateStake清空了,并重新赋值了
// flag is cleared in invokeEnterMethods before entering the target state
mTransitionInProgress = true;
invokeExitMethods(commonStateInfo); //从mStateStack的顶部依次向下移动直到找到commonStateInfo,把这些之间的state的exit方法都执行,并将Active赋值为false
int stateStackEnteringIndex = moveTempStateStackToStateStack(); //将mTempStateStack[]数组的值倒序付 给了mStateStack[]数组并且设置了 mStateStackTopIndex(栈顶序列号)的值为数组的最大下标。
invokeEnterMethods(stateStackEnteringIndex); //从stateStackEnteringIndex向栈顶依次执行enter方法并设Active为true
/**
* 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(); //将消息移动到消息队列的顶部以便马上执行
if (destState != mDestState) {
// A new mDestState so continue looping
destState = mDestState;
} else {
// No change in mDestState so we're done
break;
}
}
mDestState = null;
}
/**
* After processing all transitions check and
* see if the last transition was to quit or halt.
*/
// 处理完所有转换后,检查并查看最后一个转换是退出还是停止。
if (destState != null) {
if (destState == mQuittingState) { //退出状态
/**
* Call onQuitting to let subclasses cleanup.
*/
mSm.onQuitting();
cleanupAfterQuitting();
} else if (destState == mHaltingState) { //停止状态
/**
* Call onHalting() if we've transitioned to the halting
* state. All subsequent messages will be processed in
* in the halting state which invokes haltedProcessMessage(msg);
*/
mSm.onHalting();
}
}
}
}
}
上面方法主要处理如下:
1、调用setupTempStateStackWithStatesToEnter方法,逐次向上查找destState的所有祖先直到该祖先的stateInfo.Active为true才停止,并将值放到mTempStateStake 里面,树根对应下标最大的,commonstateInfo为该祖先的 stateInfor属性,在这个函数里面也将mTempStateStake清空了,并重新赋值了。
2、调用invokeExitMethods方法,从mStateStack的顶部依次向下移动直到找到commonStateInfo,把这些之间的state的exit方法都执行,并将Active赋值为false。
3、调用moveTempStateStackToStateStack方法,将mTempStateStack[]数组的值倒序付 给了mStateStack[]数组并且设置了 mStateStackTopIndex(栈顶序列号)的值为数组的最大下标。
4、调用invokeEnterMethods方法,从stateStackEnteringIndex向栈顶依次执行enter方法并设Active为true。
下面分别进行分析:
setupTempStateStackWithStatesToEnter
调用setupTempStateStackWithStatesToEnter方法,逐次向上查找destState的所有祖先直到该祖先的stateInfo.Active为true才停止,并将值放到mTempStateStake 里面,树根对应下标最大的,commonstateInfo为该祖先的 stateInfor属性,在这个函数里面也将mTempStateStake清空了,并重新赋值了。
//frameworks/base/core/java/com/android/internal/util/StateMachine.java
public class StateMachine {
private static class SmHandler extends Handler {
private final StateInfo setupTempStateStackWithStatesToEnter(State destState) {
/**
* Search up the parent list of the destination state for an active
* state. Use a do while() loop as the destState must always be entered
* even if it is active. This can happen if we are exiting/entering
* the current state.
*/
mTempStateStackCount = 0;
StateInfo curStateInfo = mStateInfo.get(destState);
do {
mTempStateStack[mTempStateStackCount++] = curStateInfo;
curStateInfo = curStateInfo.parentStateInfo;
} while ((curStateInfo != null) && !curStateInfo.active);
if (mDbg) {
mSm.log("setupTempStateStackWithStatesToEnter: X mTempStateStackCount="
+ mTempStateStackCount + ",curStateInfo: " + curStateInfo);
}
return curStateInfo;
}
}
}
invokeExitMethods
调用invokeExitMethods方法,从mStateStack的顶部依次向下移动直到找到commonStateInfo,把这些之间的state的exit方法都执行,并将Active赋值为false。
//frameworks/base/core/java/com/android/internal/util/StateMachine.java
public class StateMachine {
private static class SmHandler extends Handler {
/**
* Call the exit method for each state from the top of stack
* up to the common ancestor state.
*/
private final void invokeExitMethods(StateInfo commonStateInfo) {
while ((mStateStackTopIndex >= 0)
&& (mStateStack[mStateStackTopIndex] != commonStateInfo)) {
State curState = mStateStack[mStateStackTopIndex].state;
if (mDbg) mSm.log("invokeExitMethods: " + curState.getName());
curState.exit();
mStateStack[mStateStackTopIndex].active = false;
mStateStackTopIndex -= 1;
}
}
}
}
moveTempStateStackToStateStack
调用moveTempStateStackToStateStack方法,将mTempStateStack[]数组的值倒序付 给了mStateStack[]数组并且设置了 mStateStackTopIndex(栈顶序列号)的值为数组的最大下标。
//frameworks/base/core/java/com/android/internal/util/StateMachine.java
public class StateMachine {
private static class SmHandler extends Handler {
/**
* Move the contents of the temporary stack to the state stack
* reversing the order of the items on the temporary stack as
* they are moved.
*
* @return index into mStateStack where entering needs to start
*/
private final int moveTempStateStackToStateStack() {
int startingIndex = mStateStackTopIndex + 1;
int i = mTempStateStackCount - 1;
int j = startingIndex;
while (i >= 0) {
if (mDbg) mSm.log("moveTempStackToStateStack: i=" + i + ",j=" + j);
mStateStack[j] = mTempStateStack[i];
j += 1;
i -= 1;
}
mStateStackTopIndex = j - 1;
if (mDbg) {
mSm.log("moveTempStackToStateStack: X mStateStackTop=" + mStateStackTopIndex
+ ",startingIndex=" + startingIndex + ",Top="
+ mStateStack[mStateStackTopIndex].state.getName());
}
return startingIndex;
}
}
}
invokeEnterMethods
调用invokeEnterMethods方法,从stateStackEnteringIndex向栈顶依次执行enter方法并设Active为true。
//frameworks/base/core/java/com/android/internal/util/StateMachine.java
public class StateMachine {
private static class SmHandler extends Handler {
/**
* Invoke the enter method starting at the entering index to top of state stack
*/
private final void invokeEnterMethods(int stateStackEnteringIndex) {
for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
if (stateStackEnteringIndex == mStateStackTopIndex) {
// Last enter state for transition
mTransitionInProgress = false;
}
if (mDbg) mSm.log("invokeEnterMethods: " + mStateStack[i].state.getName());
mStateStack[i].state.enter();
mStateStack[i].active = true;
}
mTransitionInProgress = false; // ensure flag set to false if no methods called
}
}