Loading core/java/com/android/internal/util/StateMachine.java +257 −146 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.HashMap; import java.util.Vector; Loading Loading @@ -81,8 +82,8 @@ import java.util.Vector; * machine will cause <code>haltedProcessMessage</code> to be invoked.</p> * * <p>If it is desirable to completely stop the state machine call <code>quit</code> or * <code>abort</code>. These will call <code>exit</code> of the current state and its parents, call * <code>onQuiting</code> and then exit Thread/Loopers.</p> * <code>quitNow</code>. These will call <code>exit</code> of the current state and its parents, * call <code>onQuiting</code> and then exit Thread/Loopers.</p> * * <p>In addition to <code>processMessage</code> each <code>State</code> has * an <code>enter</code> method and <code>exit</exit> method which may be overridden.</p> Loading Loading @@ -444,12 +445,13 @@ public class StateMachine { * {@hide} */ public static class LogRec { private StateMachine mSm; private long mTime; private int mWhat; private String mInfo; private State mState; private State mOrgState; private State mTransitionToState; private IState mState; private IState mOrgState; private IState mDstState; /** * Constructor Loading @@ -461,26 +463,26 @@ public class StateMachine { * @param transToState is the state that was transitioned to after the message was * processed. */ LogRec(Message msg, String info, State state, State orgState, State transToState) { update(msg, info, state, orgState, transToState); LogRec(StateMachine sm, Message msg, String info, IState state, IState orgState, IState transToState) { update(sm, msg, info, state, orgState, transToState); } /** * Update the information in the record. * @param state that handled the message * @param orgState is the first state the received the message but * did not processes the message. * @param transToState is the state that was transitioned to after the message was * processed. * @param orgState is the first state the received the message * @param dstState is the state that was the transition target when logging */ public void update(Message msg, String info, State state, State orgState, State transToState) { public void update(StateMachine sm, Message msg, String info, IState state, IState orgState, IState dstState) { mSm = sm; mTime = System.currentTimeMillis(); mWhat = (msg != null) ? msg.what : 0; mInfo = info; mState = state; mOrgState = orgState; mTransitionToState = transToState; mDstState = dstState; } /** Loading @@ -507,21 +509,27 @@ public class StateMachine { /** * @return the state that handled this message */ public State getState() { public IState getState() { return mState; } /** * @return the original state that received the message. * @return the state destination state if a transition is occurring or null if none. */ public State getOriginalState() { return mOrgState; public IState getDestState() { return mDstState; } /** * @return as string * @return the original state that received the message. */ public String toString(StateMachine sm) { public IState getOriginalState() { return mOrgState; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("time="); Calendar c = Calendar.getInstance(); Loading @@ -532,9 +540,9 @@ public class StateMachine { sb.append(" org="); sb.append(mOrgState == null ? "<null>" : mOrgState.getName()); sb.append(" dest="); sb.append(mTransitionToState == null ? "<null>" : mTransitionToState.getName()); sb.append(mDstState == null ? "<null>" : mDstState.getName()); sb.append(" what="); String what = sm.getWhatToString(mWhat); String what = mSm != null ? mSm.getWhatToString(mWhat) : ""; if (TextUtils.isEmpty(what)) { sb.append(mWhat); sb.append("(0x"); Loading Loading @@ -647,18 +655,19 @@ public class StateMachine { * processed. * */ synchronized void add(Message msg, String messageInfo, State state, State orgState, State transToState) { synchronized void add(StateMachine sm, Message msg, String messageInfo, IState state, IState orgState, IState transToState) { mCount += 1; if (mLogRecVector.size() < mMaxSize) { mLogRecVector.add(new LogRec(msg, messageInfo, state, orgState, transToState)); mLogRecVector.add(new LogRec(sm, msg, messageInfo, state, orgState, transToState)); } else { LogRec pmi = mLogRecVector.get(mOldestIndex); mOldestIndex += 1; if (mOldestIndex >= mMaxSize) { mOldestIndex = 0; } pmi.update(msg, messageInfo, state, orgState, transToState); pmi.update(sm, msg, messageInfo, state, orgState, transToState); } } } Loading Loading @@ -788,36 +797,50 @@ public class StateMachine { throw new RuntimeException("StateMachine.handleMessage: " + "The start method not called, received msg: " + msg); } performTransitions(msgProcessedState); performTransitions(msgProcessedState, msg); if (mDbg) mSm.log("handleMessage: X"); // We need to check if mSm == null here as we could be quitting. if (mDbg && mSm != null) mSm.log("handleMessage: X"); } /** * Do any transitions * @param msgProcessedState is the state that processed the message */ private void performTransitions(State msgProcessedState) { 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 destState = null; State orgState = mStateStack[mStateStackTopIndex].state; /** Record whether message needs to be logged before transitions */ boolean recordLogMsg = mSm.recordLogRec(mMsg); /** * 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); while (mDestState != null) { if (mDbg) mSm.log("handleMessage: new destination call exit"); 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) { /** * Save mDestState locally and set to null * to know if enter/exit use transitionTo. * Process the transitions including transitions in the enter/exit methods */ destState = mDestState; mDestState = null; while (true) { if (mDbg) mSm.log("handleMessage: new destination call exit/enter"); /** * Determine the states to exit and enter and return the Loading @@ -837,6 +860,16 @@ public class StateMachine { * 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; } /** Loading @@ -859,21 +892,6 @@ public class StateMachine { mSm.onHalting(); } } // Log only if state machine has not quit if (mSm != null) { if (mLogRecords.logOnlyTransitions()) { /** Record only if there is a transition */ if (destState != null) { mLogRecords.add(mMsg, mSm.getLogRecString(mMsg), msgProcessedState, orgState, destState); } } else if (recordLogMsg) { /** Record message */ mLogRecords.add(mMsg, mSm.getLogRecString(mMsg), msgProcessedState, orgState, destState); } } } /** Loading Loading @@ -1254,20 +1272,6 @@ public class StateMachine { mSmHandler.addState(state, parent); } /** * @return current message */ protected final Message getCurrentMessage() { return mSmHandler.getCurrentMessage(); } /** * @return current state */ protected final IState getCurrentState() { return mSmHandler.getCurrentState(); } /** * Add a new state to the state machine, parent will be null * @param state to add Loading @@ -1286,6 +1290,26 @@ public class StateMachine { mSmHandler.setInitialState(initialState); } /** * @return current message */ protected final Message getCurrentMessage() { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return null; return smh.getCurrentMessage(); } /** * @return current state */ protected final IState getCurrentState() { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return null; return smh.getCurrentState(); } /** * transition to destination state. Upon returning * from processMessage the current state's exit will Loading Loading @@ -1390,40 +1414,57 @@ public class StateMachine { * @return number of log records */ public final int getLogRecSize() { return mSmHandler.mLogRecords.size(); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return 0; return smh.mLogRecords.size(); } /** * @return the total number of records processed */ public final int getLogRecCount() { return mSmHandler.mLogRecords.count(); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return 0; return smh.mLogRecords.count(); } /** * @return a log record * @return a log record, or null if index is out of range */ public final LogRec getLogRec(int index) { return mSmHandler.mLogRecords.get(index); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return null; return smh.mLogRecords.get(index); } /** * Add the string to LogRecords. * * @param string * @return a copy of LogRecs as a collection */ protected void addLogRec(String string) { mSmHandler.mLogRecords.add(null, string, null, null, null); public final Collection<LogRec> copyLogRecs() { Vector<LogRec> vlr = new Vector<LogRec>(); SmHandler smh = mSmHandler; if (smh != null) { for (LogRec lr : smh.mLogRecords.mLogRecVector) { vlr.add(lr); } } return vlr; } /** * Add the string and state to LogRecords * Add the string to LogRecords. * * @param string * @param state current state */ protected void addLogRec(String string, State state) { mSmHandler.mLogRecords.add(null, string, state, null, null); protected void addLogRec(String string) { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return; smh.mLogRecords.add(this, smh.getCurrentMessage(), string, smh.getCurrentState(), smh.mStateStack[smh.mStateStackTopIndex].state, smh.mDestState); } /** Loading Loading @@ -1452,168 +1493,217 @@ public class StateMachine { } /** * @return Handler * @return Handler, maybe null if state machine has quit. */ public final Handler getHandler() { return mSmHandler; } /** * Get a message and set Message.target = this. * Get a message and set Message.target state machine handler. * * Note: The handler can be null if the state machine has quit, * which means target will be null and may cause a AndroidRuntimeException * in MessageQueue#enqueMessage if sent directly or if sent using * StateMachine#sendMessage the message will just be ignored. * * @return message or null if SM has quit * @return A Message object from the global pool */ public final Message obtainMessage() { if (mSmHandler == null) return null; return Message.obtain(mSmHandler); } /** * Get a message and set Message.target = this and what * Get a message and set Message.target state machine handler, what. * * Note: The handler can be null if the state machine has quit, * which means target will be null and may cause a AndroidRuntimeException * in MessageQueue#enqueMessage if sent directly or if sent using * StateMachine#sendMessage the message will just be ignored. * * @param what is the assigned to Message.what. * @return message or null if SM has quit * @return A Message object from the global pool */ public final Message obtainMessage(int what) { if (mSmHandler == null) return null; return Message.obtain(mSmHandler, what); } /** * Get a message and set Message.target = this, * Get a message and set Message.target state machine handler, * what and obj. * * Note: The handler can be null if the state machine has quit, * which means target will be null and may cause a AndroidRuntimeException * in MessageQueue#enqueMessage if sent directly or if sent using * StateMachine#sendMessage the message will just be ignored. * * @param what is the assigned to Message.what. * @param obj is assigned to Message.obj. * @return message or null if SM has quit * @return A Message object from the global pool */ public final Message obtainMessage(int what, Object obj) { if (mSmHandler == null) return null; return Message.obtain(mSmHandler, what, obj); } /** * Get a message and set Message.target = this, * Get a message and set Message.target state machine handler, * what, arg1 and arg2 * * Note: The handler can be null if the state machine has quit, * which means target will be null and may cause a AndroidRuntimeException * in MessageQueue#enqueMessage if sent directly or if sent using * StateMachine#sendMessage the message will just be ignored. * * @param what is assigned to Message.what * @param arg1 is assigned to Message.arg1 * @param arg2 is assigned to Message.arg2 * @return A Message object from the global pool or null if * SM has quit * @return A Message object from the global pool */ public final Message obtainMessage(int what, int arg1, int arg2) { if (mSmHandler == null) return null; return Message.obtain(mSmHandler, what, arg1, arg2); } /** * Get a message and set Message.target = this, * Get a message and set Message.target state machine handler, * what, arg1, arg2 and obj * * Note: The handler can be null if the state machine has quit, * which means target will be null and may cause a AndroidRuntimeException * in MessageQueue#enqueMessage if sent directly or if sent using * StateMachine#sendMessage the message will just be ignored. * * @param what is assigned to Message.what * @param arg1 is assigned to Message.arg1 * @param arg2 is assigned to Message.arg2 * @param obj is assigned to Message.obj * @return A Message object from the global pool or null if * SM has quit * @return A Message object from the global pool */ public final Message obtainMessage(int what, int arg1, int arg2, Object obj) { if (mSmHandler == null) return null; return Message.obtain(mSmHandler, what, arg1, arg2, obj); } /** * Enqueue a message to this state machine. * * Message is ignored if state machine has quit. */ public final void sendMessage(int what) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.sendMessage(obtainMessage(what)); smh.sendMessage(obtainMessage(what)); } /** * Enqueue a message to this state machine. * * Message is ignored if state machine has quit. */ public final void sendMessage(int what, Object obj) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.sendMessage(obtainMessage(what,obj)); smh.sendMessage(obtainMessage(what,obj)); } /** * Enqueue a message to this state machine. * * Message is ignored if state machine has quit. */ public final void sendMessage(Message msg) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.sendMessage(msg); smh.sendMessage(msg); } /** * Enqueue a message to this state machine after a delay. * * Message is ignored if state machine has quit. */ public final void sendMessageDelayed(int what, long delayMillis) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.sendMessageDelayed(obtainMessage(what), delayMillis); smh.sendMessageDelayed(obtainMessage(what), delayMillis); } /** * Enqueue a message to this state machine after a delay. * * Message is ignored if state machine has quit. */ public final void sendMessageDelayed(int what, Object obj, long delayMillis) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.sendMessageDelayed(obtainMessage(what, obj), delayMillis); smh.sendMessageDelayed(obtainMessage(what, obj), delayMillis); } /** * Enqueue a message to this state machine after a delay. * * Message is ignored if state machine has quit. */ public final void sendMessageDelayed(Message msg, long delayMillis) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.sendMessageDelayed(msg, delayMillis); smh.sendMessageDelayed(msg, delayMillis); } /** * Enqueue a message to the front of the queue for this state machine. * Protected, may only be called by instances of StateMachine. * * Message is ignored if state machine has quit. */ protected final void sendMessageAtFrontOfQueue(int what, Object obj) { mSmHandler.sendMessageAtFrontOfQueue(obtainMessage(what, obj)); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return; smh.sendMessageAtFrontOfQueue(obtainMessage(what, obj)); } /** * Enqueue a message to the front of the queue for this state machine. * Protected, may only be called by instances of StateMachine. * * Message is ignored if state machine has quit. */ protected final void sendMessageAtFrontOfQueue(int what) { mSmHandler.sendMessageAtFrontOfQueue(obtainMessage(what)); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return; smh.sendMessageAtFrontOfQueue(obtainMessage(what)); } /** * Enqueue a message to the front of the queue for this state machine. * Protected, may only be called by instances of StateMachine. * * Message is ignored if state machine has quit. */ protected final void sendMessageAtFrontOfQueue(Message msg) { mSmHandler.sendMessageAtFrontOfQueue(msg); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return; smh.sendMessageAtFrontOfQueue(msg); } /** Loading @@ -1621,7 +1711,23 @@ public class StateMachine { * Protected, may only be called by instances of StateMachine. */ protected final void removeMessages(int what) { mSmHandler.removeMessages(what); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return; smh.removeMessages(what); } /** * Validate that the message was sent by * {@link StateMachine#quit} or {@link StateMachine#quitNow}. * */ protected final boolean isQuit(Message msg) { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return msg.what == SM_QUIT_CMD; return smh.isQuit(msg); } /** Loading @@ -1629,9 +1735,10 @@ public class StateMachine { */ protected final void quit() { // mSmHandler can be null if the state machine is already stopped. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.quit(); smh.quit(); } /** Loading @@ -1639,9 +1746,10 @@ public class StateMachine { */ protected final void quitNow() { // mSmHandler can be null if the state machine is already stopped. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.quitNow(); smh.quitNow(); } /** Loading @@ -1649,9 +1757,10 @@ public class StateMachine { */ public boolean isDbg() { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return false; SmHandler smh = mSmHandler; if (smh == null) return false; return mSmHandler.isDbg(); return smh.isDbg(); } /** Loading @@ -1661,9 +1770,10 @@ public class StateMachine { */ public void setDbg(boolean dbg) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.setDbg(dbg); smh.setDbg(dbg); } /** Loading @@ -1671,10 +1781,11 @@ public class StateMachine { */ public void start() { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; /** Send the complete construction message */ mSmHandler.completeConstruction(); smh.completeConstruction(); } /** Loading @@ -1688,7 +1799,7 @@ public class StateMachine { pw.println(getName() + ":"); pw.println(" total records=" + getLogRecCount()); for (int i=0; i < getLogRecSize(); i++) { pw.printf(" rec[%d]: %s\n", i, getLogRec(i).toString(this)); pw.printf(" rec[%d]: %s\n", i, getLogRec(i).toString()); pw.flush(); } pw.println("curState=" + getCurrentState().getName()); Loading core/tests/coretests/src/com/android/internal/util/StateMachineTest.java +313 −281 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/com/android/internal/util/StateMachine.java +257 −146 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.HashMap; import java.util.Vector; Loading Loading @@ -81,8 +82,8 @@ import java.util.Vector; * machine will cause <code>haltedProcessMessage</code> to be invoked.</p> * * <p>If it is desirable to completely stop the state machine call <code>quit</code> or * <code>abort</code>. These will call <code>exit</code> of the current state and its parents, call * <code>onQuiting</code> and then exit Thread/Loopers.</p> * <code>quitNow</code>. These will call <code>exit</code> of the current state and its parents, * call <code>onQuiting</code> and then exit Thread/Loopers.</p> * * <p>In addition to <code>processMessage</code> each <code>State</code> has * an <code>enter</code> method and <code>exit</exit> method which may be overridden.</p> Loading Loading @@ -444,12 +445,13 @@ public class StateMachine { * {@hide} */ public static class LogRec { private StateMachine mSm; private long mTime; private int mWhat; private String mInfo; private State mState; private State mOrgState; private State mTransitionToState; private IState mState; private IState mOrgState; private IState mDstState; /** * Constructor Loading @@ -461,26 +463,26 @@ public class StateMachine { * @param transToState is the state that was transitioned to after the message was * processed. */ LogRec(Message msg, String info, State state, State orgState, State transToState) { update(msg, info, state, orgState, transToState); LogRec(StateMachine sm, Message msg, String info, IState state, IState orgState, IState transToState) { update(sm, msg, info, state, orgState, transToState); } /** * Update the information in the record. * @param state that handled the message * @param orgState is the first state the received the message but * did not processes the message. * @param transToState is the state that was transitioned to after the message was * processed. * @param orgState is the first state the received the message * @param dstState is the state that was the transition target when logging */ public void update(Message msg, String info, State state, State orgState, State transToState) { public void update(StateMachine sm, Message msg, String info, IState state, IState orgState, IState dstState) { mSm = sm; mTime = System.currentTimeMillis(); mWhat = (msg != null) ? msg.what : 0; mInfo = info; mState = state; mOrgState = orgState; mTransitionToState = transToState; mDstState = dstState; } /** Loading @@ -507,21 +509,27 @@ public class StateMachine { /** * @return the state that handled this message */ public State getState() { public IState getState() { return mState; } /** * @return the original state that received the message. * @return the state destination state if a transition is occurring or null if none. */ public State getOriginalState() { return mOrgState; public IState getDestState() { return mDstState; } /** * @return as string * @return the original state that received the message. */ public String toString(StateMachine sm) { public IState getOriginalState() { return mOrgState; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("time="); Calendar c = Calendar.getInstance(); Loading @@ -532,9 +540,9 @@ public class StateMachine { sb.append(" org="); sb.append(mOrgState == null ? "<null>" : mOrgState.getName()); sb.append(" dest="); sb.append(mTransitionToState == null ? "<null>" : mTransitionToState.getName()); sb.append(mDstState == null ? "<null>" : mDstState.getName()); sb.append(" what="); String what = sm.getWhatToString(mWhat); String what = mSm != null ? mSm.getWhatToString(mWhat) : ""; if (TextUtils.isEmpty(what)) { sb.append(mWhat); sb.append("(0x"); Loading Loading @@ -647,18 +655,19 @@ public class StateMachine { * processed. * */ synchronized void add(Message msg, String messageInfo, State state, State orgState, State transToState) { synchronized void add(StateMachine sm, Message msg, String messageInfo, IState state, IState orgState, IState transToState) { mCount += 1; if (mLogRecVector.size() < mMaxSize) { mLogRecVector.add(new LogRec(msg, messageInfo, state, orgState, transToState)); mLogRecVector.add(new LogRec(sm, msg, messageInfo, state, orgState, transToState)); } else { LogRec pmi = mLogRecVector.get(mOldestIndex); mOldestIndex += 1; if (mOldestIndex >= mMaxSize) { mOldestIndex = 0; } pmi.update(msg, messageInfo, state, orgState, transToState); pmi.update(sm, msg, messageInfo, state, orgState, transToState); } } } Loading Loading @@ -788,36 +797,50 @@ public class StateMachine { throw new RuntimeException("StateMachine.handleMessage: " + "The start method not called, received msg: " + msg); } performTransitions(msgProcessedState); performTransitions(msgProcessedState, msg); if (mDbg) mSm.log("handleMessage: X"); // We need to check if mSm == null here as we could be quitting. if (mDbg && mSm != null) mSm.log("handleMessage: X"); } /** * Do any transitions * @param msgProcessedState is the state that processed the message */ private void performTransitions(State msgProcessedState) { 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 destState = null; State orgState = mStateStack[mStateStackTopIndex].state; /** Record whether message needs to be logged before transitions */ boolean recordLogMsg = mSm.recordLogRec(mMsg); /** * 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); while (mDestState != null) { if (mDbg) mSm.log("handleMessage: new destination call exit"); 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) { /** * Save mDestState locally and set to null * to know if enter/exit use transitionTo. * Process the transitions including transitions in the enter/exit methods */ destState = mDestState; mDestState = null; while (true) { if (mDbg) mSm.log("handleMessage: new destination call exit/enter"); /** * Determine the states to exit and enter and return the Loading @@ -837,6 +860,16 @@ public class StateMachine { * 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; } /** Loading @@ -859,21 +892,6 @@ public class StateMachine { mSm.onHalting(); } } // Log only if state machine has not quit if (mSm != null) { if (mLogRecords.logOnlyTransitions()) { /** Record only if there is a transition */ if (destState != null) { mLogRecords.add(mMsg, mSm.getLogRecString(mMsg), msgProcessedState, orgState, destState); } } else if (recordLogMsg) { /** Record message */ mLogRecords.add(mMsg, mSm.getLogRecString(mMsg), msgProcessedState, orgState, destState); } } } /** Loading Loading @@ -1254,20 +1272,6 @@ public class StateMachine { mSmHandler.addState(state, parent); } /** * @return current message */ protected final Message getCurrentMessage() { return mSmHandler.getCurrentMessage(); } /** * @return current state */ protected final IState getCurrentState() { return mSmHandler.getCurrentState(); } /** * Add a new state to the state machine, parent will be null * @param state to add Loading @@ -1286,6 +1290,26 @@ public class StateMachine { mSmHandler.setInitialState(initialState); } /** * @return current message */ protected final Message getCurrentMessage() { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return null; return smh.getCurrentMessage(); } /** * @return current state */ protected final IState getCurrentState() { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return null; return smh.getCurrentState(); } /** * transition to destination state. Upon returning * from processMessage the current state's exit will Loading Loading @@ -1390,40 +1414,57 @@ public class StateMachine { * @return number of log records */ public final int getLogRecSize() { return mSmHandler.mLogRecords.size(); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return 0; return smh.mLogRecords.size(); } /** * @return the total number of records processed */ public final int getLogRecCount() { return mSmHandler.mLogRecords.count(); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return 0; return smh.mLogRecords.count(); } /** * @return a log record * @return a log record, or null if index is out of range */ public final LogRec getLogRec(int index) { return mSmHandler.mLogRecords.get(index); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return null; return smh.mLogRecords.get(index); } /** * Add the string to LogRecords. * * @param string * @return a copy of LogRecs as a collection */ protected void addLogRec(String string) { mSmHandler.mLogRecords.add(null, string, null, null, null); public final Collection<LogRec> copyLogRecs() { Vector<LogRec> vlr = new Vector<LogRec>(); SmHandler smh = mSmHandler; if (smh != null) { for (LogRec lr : smh.mLogRecords.mLogRecVector) { vlr.add(lr); } } return vlr; } /** * Add the string and state to LogRecords * Add the string to LogRecords. * * @param string * @param state current state */ protected void addLogRec(String string, State state) { mSmHandler.mLogRecords.add(null, string, state, null, null); protected void addLogRec(String string) { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return; smh.mLogRecords.add(this, smh.getCurrentMessage(), string, smh.getCurrentState(), smh.mStateStack[smh.mStateStackTopIndex].state, smh.mDestState); } /** Loading Loading @@ -1452,168 +1493,217 @@ public class StateMachine { } /** * @return Handler * @return Handler, maybe null if state machine has quit. */ public final Handler getHandler() { return mSmHandler; } /** * Get a message and set Message.target = this. * Get a message and set Message.target state machine handler. * * Note: The handler can be null if the state machine has quit, * which means target will be null and may cause a AndroidRuntimeException * in MessageQueue#enqueMessage if sent directly or if sent using * StateMachine#sendMessage the message will just be ignored. * * @return message or null if SM has quit * @return A Message object from the global pool */ public final Message obtainMessage() { if (mSmHandler == null) return null; return Message.obtain(mSmHandler); } /** * Get a message and set Message.target = this and what * Get a message and set Message.target state machine handler, what. * * Note: The handler can be null if the state machine has quit, * which means target will be null and may cause a AndroidRuntimeException * in MessageQueue#enqueMessage if sent directly or if sent using * StateMachine#sendMessage the message will just be ignored. * * @param what is the assigned to Message.what. * @return message or null if SM has quit * @return A Message object from the global pool */ public final Message obtainMessage(int what) { if (mSmHandler == null) return null; return Message.obtain(mSmHandler, what); } /** * Get a message and set Message.target = this, * Get a message and set Message.target state machine handler, * what and obj. * * Note: The handler can be null if the state machine has quit, * which means target will be null and may cause a AndroidRuntimeException * in MessageQueue#enqueMessage if sent directly or if sent using * StateMachine#sendMessage the message will just be ignored. * * @param what is the assigned to Message.what. * @param obj is assigned to Message.obj. * @return message or null if SM has quit * @return A Message object from the global pool */ public final Message obtainMessage(int what, Object obj) { if (mSmHandler == null) return null; return Message.obtain(mSmHandler, what, obj); } /** * Get a message and set Message.target = this, * Get a message and set Message.target state machine handler, * what, arg1 and arg2 * * Note: The handler can be null if the state machine has quit, * which means target will be null and may cause a AndroidRuntimeException * in MessageQueue#enqueMessage if sent directly or if sent using * StateMachine#sendMessage the message will just be ignored. * * @param what is assigned to Message.what * @param arg1 is assigned to Message.arg1 * @param arg2 is assigned to Message.arg2 * @return A Message object from the global pool or null if * SM has quit * @return A Message object from the global pool */ public final Message obtainMessage(int what, int arg1, int arg2) { if (mSmHandler == null) return null; return Message.obtain(mSmHandler, what, arg1, arg2); } /** * Get a message and set Message.target = this, * Get a message and set Message.target state machine handler, * what, arg1, arg2 and obj * * Note: The handler can be null if the state machine has quit, * which means target will be null and may cause a AndroidRuntimeException * in MessageQueue#enqueMessage if sent directly or if sent using * StateMachine#sendMessage the message will just be ignored. * * @param what is assigned to Message.what * @param arg1 is assigned to Message.arg1 * @param arg2 is assigned to Message.arg2 * @param obj is assigned to Message.obj * @return A Message object from the global pool or null if * SM has quit * @return A Message object from the global pool */ public final Message obtainMessage(int what, int arg1, int arg2, Object obj) { if (mSmHandler == null) return null; return Message.obtain(mSmHandler, what, arg1, arg2, obj); } /** * Enqueue a message to this state machine. * * Message is ignored if state machine has quit. */ public final void sendMessage(int what) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.sendMessage(obtainMessage(what)); smh.sendMessage(obtainMessage(what)); } /** * Enqueue a message to this state machine. * * Message is ignored if state machine has quit. */ public final void sendMessage(int what, Object obj) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.sendMessage(obtainMessage(what,obj)); smh.sendMessage(obtainMessage(what,obj)); } /** * Enqueue a message to this state machine. * * Message is ignored if state machine has quit. */ public final void sendMessage(Message msg) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.sendMessage(msg); smh.sendMessage(msg); } /** * Enqueue a message to this state machine after a delay. * * Message is ignored if state machine has quit. */ public final void sendMessageDelayed(int what, long delayMillis) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.sendMessageDelayed(obtainMessage(what), delayMillis); smh.sendMessageDelayed(obtainMessage(what), delayMillis); } /** * Enqueue a message to this state machine after a delay. * * Message is ignored if state machine has quit. */ public final void sendMessageDelayed(int what, Object obj, long delayMillis) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.sendMessageDelayed(obtainMessage(what, obj), delayMillis); smh.sendMessageDelayed(obtainMessage(what, obj), delayMillis); } /** * Enqueue a message to this state machine after a delay. * * Message is ignored if state machine has quit. */ public final void sendMessageDelayed(Message msg, long delayMillis) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.sendMessageDelayed(msg, delayMillis); smh.sendMessageDelayed(msg, delayMillis); } /** * Enqueue a message to the front of the queue for this state machine. * Protected, may only be called by instances of StateMachine. * * Message is ignored if state machine has quit. */ protected final void sendMessageAtFrontOfQueue(int what, Object obj) { mSmHandler.sendMessageAtFrontOfQueue(obtainMessage(what, obj)); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return; smh.sendMessageAtFrontOfQueue(obtainMessage(what, obj)); } /** * Enqueue a message to the front of the queue for this state machine. * Protected, may only be called by instances of StateMachine. * * Message is ignored if state machine has quit. */ protected final void sendMessageAtFrontOfQueue(int what) { mSmHandler.sendMessageAtFrontOfQueue(obtainMessage(what)); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return; smh.sendMessageAtFrontOfQueue(obtainMessage(what)); } /** * Enqueue a message to the front of the queue for this state machine. * Protected, may only be called by instances of StateMachine. * * Message is ignored if state machine has quit. */ protected final void sendMessageAtFrontOfQueue(Message msg) { mSmHandler.sendMessageAtFrontOfQueue(msg); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return; smh.sendMessageAtFrontOfQueue(msg); } /** Loading @@ -1621,7 +1711,23 @@ public class StateMachine { * Protected, may only be called by instances of StateMachine. */ protected final void removeMessages(int what) { mSmHandler.removeMessages(what); // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return; smh.removeMessages(what); } /** * Validate that the message was sent by * {@link StateMachine#quit} or {@link StateMachine#quitNow}. * */ protected final boolean isQuit(Message msg) { // mSmHandler can be null if the state machine has quit. SmHandler smh = mSmHandler; if (smh == null) return msg.what == SM_QUIT_CMD; return smh.isQuit(msg); } /** Loading @@ -1629,9 +1735,10 @@ public class StateMachine { */ protected final void quit() { // mSmHandler can be null if the state machine is already stopped. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.quit(); smh.quit(); } /** Loading @@ -1639,9 +1746,10 @@ public class StateMachine { */ protected final void quitNow() { // mSmHandler can be null if the state machine is already stopped. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.quitNow(); smh.quitNow(); } /** Loading @@ -1649,9 +1757,10 @@ public class StateMachine { */ public boolean isDbg() { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return false; SmHandler smh = mSmHandler; if (smh == null) return false; return mSmHandler.isDbg(); return smh.isDbg(); } /** Loading @@ -1661,9 +1770,10 @@ public class StateMachine { */ public void setDbg(boolean dbg) { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; mSmHandler.setDbg(dbg); smh.setDbg(dbg); } /** Loading @@ -1671,10 +1781,11 @@ public class StateMachine { */ public void start() { // mSmHandler can be null if the state machine has quit. if (mSmHandler == null) return; SmHandler smh = mSmHandler; if (smh == null) return; /** Send the complete construction message */ mSmHandler.completeConstruction(); smh.completeConstruction(); } /** Loading @@ -1688,7 +1799,7 @@ public class StateMachine { pw.println(getName() + ":"); pw.println(" total records=" + getLogRecCount()); for (int i=0; i < getLogRecSize(); i++) { pw.printf(" rec[%d]: %s\n", i, getLogRec(i).toString(this)); pw.printf(" rec[%d]: %s\n", i, getLogRec(i).toString()); pw.flush(); } pw.println("curState=" + getCurrentState().getName()); Loading
core/tests/coretests/src/com/android/internal/util/StateMachineTest.java +313 −281 File changed.Preview size limit exceeded, changes collapsed. Show changes