/** * Process the message. If the current state doesn't handle it, call the states parent and so * on. If it is never handled then call the state machines unhandledMessage method. */ private final void processMsg(Message msg) { StateInfo curStateInfo = mStateStack[mStateStackTopIndex]; if (mDbg) { Log.d(TAG, "processMsg: " + curStateInfo.state.getName()); } while (!curStateInfo.state.processMessage(msg)) { /** Not processed */ curStateInfo = curStateInfo.parentStateInfo; if (curStateInfo == null) { /** No parents left so it's not handled */ mSm.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) { State orgState = mStateStack[mStateStackTopIndex].state; mProcessedMessages.add(msg, curStateInfo.state, orgState); } else { mProcessedMessages.add(msg, null, null); } }
/** Cleanup all the static variables and the looper after the SM has been quit. */ private final void cleanupAfterQuitting() { mSm.quitting(); if (mSm.mSmThread != null) { // If we made the thread then quit looper which stops the thread. getLooper().quit(); mSm.mSmThread = null; } mSm.mSmHandler = null; mSm = null; mMsg = null; mProcessedMessages.cleanup(); mStateStack = null; mTempStateStack = null; mStateInfo.clear(); mInitialState = null; mDestState = null; mDeferredMessages.clear(); }
/** Do any transitions */ private synchronized 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. */ State 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(); } /** * After processing all transitions check and see if the last transition was to quit or halt. */ if (destState != null) { if (destState == mQuittingState) { cleanupAfterQuitting(); } else if (destState == mHaltingState) { /** * Call halting() if we've transitioned to the halting state. All subsequent messages will * be processed in in the halting state which invokes haltedProcessMessage(msg); */ mSm.halting(); } } }