OSDN Git Service

am d21e24bc: Merge "Cleanup StateMachine LogRec handling and get tests working."
authorWink Saville <wink@google.com>
Wed, 30 Jan 2013 20:10:03 +0000 (12:10 -0800)
committerAndroid Git Automerger <android-git-automerger@android.com>
Wed, 30 Jan 2013 20:10:03 +0000 (12:10 -0800)
# Via Android (Google) Code Review (1) and Wink Saville (1)
* commit 'd21e24bccec8309839a264da95c5dc1573fc65c3':
  Cleanup StateMachine LogRec handling and get tests working.

core/java/com/android/internal/util/StateMachine.java
core/tests/coretests/src/com/android/internal/util/StateMachineTest.java

index 1e5a97a..6641f2c 100644 (file)
@@ -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;
 
@@ -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>
@@ -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
@@ -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;
         }
 
         /**
@@ -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();
@@ -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");
@@ -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);
             }
         }
     }
@@ -788,55 +797,79 @@ 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
-                 * 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);
+                    /**
+                     * 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();
+                    /**
+                     * 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;
             }
 
             /**
@@ -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);
-                }
-            }
         }
 
         /**
@@ -1255,20 +1273,6 @@ public class StateMachine {
     }
 
     /**
-     * @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
      */
@@ -1287,6 +1291,26 @@ public class StateMachine {
     }
 
     /**
+     * @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
      * be executed and upon the next message arriving
@@ -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);
     }
 
     /**
@@ -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.
      *
-     * @return message or null if SM has quit
+     * 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  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);
     }
 
     /**
@@ -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);
     }
 
     /**
@@ -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();
     }
 
     /**
@@ -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();
     }
 
     /**
@@ -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();
     }
 
     /**
@@ -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);
     }
 
     /**
@@ -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();
     }
 
     /**
@@ -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());
index 418bbd6..2a2c24e 100644 (file)
@@ -16,6 +16,9 @@
 
 package com.android.internal.util;
 
+import java.util.Collection;
+import java.util.Iterator;
+
 import android.os.Debug;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -58,11 +61,28 @@ public class StateMachineTest extends TestCase {
         }
     }
 
+    private void dumpLogRecs(StateMachine sm) {
+        int size = sm.getLogRecSize();
+        tlog("size=" + size + " count=" + sm.getLogRecCount());
+        for (int i = 0; i < size; i++) {
+            LogRec lr = sm.getLogRec(i);
+            tlog(lr.toString());
+        }
+    }
+
+    private void dumpLogRecs(Collection<LogRec> clr) {
+        int size = clr.size();
+        tlog("size=" + size);
+        for (LogRec lr : clr) {
+            tlog(lr.toString());
+        }
+    }
+
     /**
      * Tests {@link StateMachine#quit()}.
      */
     class StateMachineQuitTest extends StateMachine {
-        Object mWaitUntilTestDone = new Object();
+        Collection<LogRec> mLogRecs;
 
         StateMachineQuitTest(String name) {
             super(name);
@@ -78,39 +98,32 @@ public class StateMachineTest extends TestCase {
 
         @Override
         public void onQuitting() {
-            Log.d(TAG, "onQuitting");
+            log("onQuitting");
             addLogRec(ON_QUITTING);
+            mLogRecs = mThisSm.copyLogRecs();
             synchronized (mThisSm) {
                 mThisSm.notifyAll();
             }
-
-            // Don't leave onQuitting before the test is done as everything is cleared
-            // including the log records.
-            synchronized (mWaitUntilTestDone) {
-                try {
-                    mWaitUntilTestDone.wait();
-                } catch(InterruptedException e) {
-                }
-            }
         }
 
         class S1 extends State {
+            @Override
             public void exit() {
-                Log.d(TAG, "S1.exit");
-                addLogRec(EXIT, mS1);
+                log("S1.exit");
+                addLogRec(EXIT);
             }
             @Override
             public boolean processMessage(Message message) {
                 switch(message.what) {
                     // Sleep and assume the other messages will be queued up.
                     case TEST_CMD_1: {
-                        Log.d(TAG, "TEST_CMD_1");
+                        log("TEST_CMD_1");
                         sleep(500);
                         quit();
                         break;
                     }
                     default: {
-                        Log.d(TAG, "default what=" + message.what);
+                        log("default what=" + message.what);
                         break;
                     }
                 }
@@ -128,7 +141,7 @@ public class StateMachineTest extends TestCase {
 
         StateMachineQuitTest smQuitTest = new StateMachineQuitTest("smQuitTest");
         smQuitTest.start();
-        if (smQuitTest.isDbg()) Log.d(TAG, "testStateMachineQuit E");
+        if (smQuitTest.isDbg()) tlog("testStateMachineQuit E");
 
         synchronized (smQuitTest) {
 
@@ -141,38 +154,36 @@ public class StateMachineTest extends TestCase {
                 // wait for the messages to be handled
                 smQuitTest.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testStateMachineQuit: exception while waiting " + e.getMessage());
+                tloge("testStateMachineQuit: exception while waiting " + e.getMessage());
             }
         }
 
-        assertEquals(8, smQuitTest.getLogRecCount());
+        dumpLogRecs(smQuitTest.mLogRecs);
+        assertEquals(8, smQuitTest.mLogRecs.size());
 
         LogRec lr;
-
-        for (int i = 0; i < 6; i++) {
-            lr = smQuitTest.getLogRec(i);
-            assertEquals(i+1, lr.getWhat());
+        Iterator<LogRec> itr = smQuitTest.mLogRecs.iterator();
+        for (int i = 1; i <= 6; i++) {
+            lr = itr.next();
+            assertEquals(i, lr.getWhat());
             assertEquals(smQuitTest.mS1, lr.getState());
             assertEquals(smQuitTest.mS1, lr.getOriginalState());
         }
-        lr = smQuitTest.getLogRec(6);
+        lr = itr.next();
         assertEquals(EXIT, lr.getInfo());
         assertEquals(smQuitTest.mS1, lr.getState());
 
-        lr = smQuitTest.getLogRec(7);
+        lr = itr.next();
         assertEquals(ON_QUITTING, lr.getInfo());
 
-        synchronized (smQuitTest.mWaitUntilTestDone) {
-            smQuitTest.mWaitUntilTestDone.notifyAll();
-        }
-        if (smQuitTest.isDbg()) Log.d(TAG, "testStateMachineQuit X");
+        if (smQuitTest.isDbg()) tlog("testStateMachineQuit X");
     }
 
     /**
      * Tests {@link StateMachine#quitNow()}
      */
     class StateMachineQuitNowTest extends StateMachine {
-        Object mWaitUntilTestDone = new Object();
+        public Collection<LogRec> mLogRecs = null;
 
         StateMachineQuitNowTest(String name) {
             super(name);
@@ -188,39 +199,34 @@ public class StateMachineTest extends TestCase {
 
         @Override
         public void onQuitting() {
-            Log.d(TAG, "onQuitting");
+            log("onQuitting");
             addLogRec(ON_QUITTING);
+            // Get a copy of the log records since we're quitting and they will disappear
+            mLogRecs = mThisSm.copyLogRecs();
+
             synchronized (mThisSm) {
                 mThisSm.notifyAll();
             }
-
-            // Don't leave onQuitting before the test is done as everything is cleared
-            // including the log records.
-            synchronized (mWaitUntilTestDone) {
-                try {
-                    mWaitUntilTestDone.wait();
-                } catch(InterruptedException e) {
-                }
-            }
         }
 
         class S1 extends State {
+            @Override
             public void exit() {
-                Log.d(TAG, "S1.exit");
-                addLogRec(EXIT, mS1);
+                log("S1.exit");
+                addLogRec(EXIT);
             }
             @Override
             public boolean processMessage(Message message) {
                 switch(message.what) {
                     // Sleep and assume the other messages will be queued up.
                     case TEST_CMD_1: {
-                        Log.d(TAG, "TEST_CMD_1");
+                        log("TEST_CMD_1");
                         sleep(500);
                         quitNow();
                         break;
                     }
                     default: {
-                        Log.d(TAG, "default what=" + message.what);
+                        log("default what=" + message.what);
                         break;
                     }
                 }
@@ -238,11 +244,11 @@ public class StateMachineTest extends TestCase {
 
         StateMachineQuitNowTest smQuitNowTest = new StateMachineQuitNowTest("smQuitNowTest");
         smQuitNowTest.start();
-        if (smQuitNowTest.isDbg()) Log.d(TAG, "testStateMachineQuitNow E");
+        if (smQuitNowTest.isDbg()) tlog("testStateMachineQuitNow E");
 
         synchronized (smQuitNowTest) {
 
-            // Send 6 messages but we'll QuitNow on the first so even though
+            // Send 6 message we'll QuitNow on the first even though
             // we send 6 only one will be processed.
             for (int i = 1; i <= 6; i++) {
                 smQuitNowTest.sendMessage(smQuitNowTest.obtainMessage(i));
@@ -252,31 +258,27 @@ public class StateMachineTest extends TestCase {
                 // wait for the messages to be handled
                 smQuitNowTest.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testStateMachineQuitNow: exception while waiting " + e.getMessage());
+                tloge("testStateMachineQuitNow: exception while waiting " + e.getMessage());
             }
         }
 
-        // Only three records because we executed quitNow.
-        assertEquals(3, smQuitNowTest.getLogRecCount());
+        tlog("testStateMachineQuiteNow: logRecs=" + smQuitNowTest.mLogRecs);
+        assertEquals(3, smQuitNowTest.mLogRecs.size());
 
-        LogRec lr;
-
-        lr = smQuitNowTest.getLogRec(0);
+        Iterator<LogRec> itr = smQuitNowTest.mLogRecs.iterator();
+        LogRec lr = itr.next();
         assertEquals(1, lr.getWhat());
         assertEquals(smQuitNowTest.mS1, lr.getState());
         assertEquals(smQuitNowTest.mS1, lr.getOriginalState());
 
-        lr = smQuitNowTest.getLogRec(1);
+        lr = itr.next();
         assertEquals(EXIT, lr.getInfo());
         assertEquals(smQuitNowTest.mS1, lr.getState());
 
-        lr = smQuitNowTest.getLogRec(2);
+        lr = itr.next();
         assertEquals(ON_QUITTING, lr.getInfo());
 
-        synchronized (smQuitNowTest.mWaitUntilTestDone) {
-            smQuitNowTest.mWaitUntilTestDone.notifyAll();
-        }
-        if (smQuitNowTest.isDbg()) Log.d(TAG, "testStateMachineQuitNow X");
+        if (smQuitNowTest.isDbg()) tlog("testStateMachineQuitNow X");
     }
 
     /**
@@ -303,39 +305,39 @@ public class StateMachineTest extends TestCase {
             @Override
             public void enter() {
                 // Test transitions in enter on the initial state work
-                addLogRec(ENTER, mS1);
+                addLogRec(ENTER);
                 transitionTo(mS2);
-                Log.d(TAG, "S1.enter");
+                log("S1.enter");
             }
             @Override
             public void exit() {
-                // Test that message is HSM_INIT_CMD
-                addLogRec(EXIT, mS1);
-                Log.d(TAG, "S1.exit");
+                addLogRec(EXIT);
+                log("S1.exit");
             }
         }
 
         class S2 extends State {
             @Override
             public void enter() {
-                addLogRec(ENTER, mS2);
-                Log.d(TAG, "S2.enter");
+                addLogRec(ENTER);
+                log("S2.enter");
             }
             @Override
             public void exit() {
-                addLogRec(EXIT, mS2);
-                assertEquals(TEST_CMD_1, getCurrentMessage().what);
-
                 // Test transition in exit work
                 transitionTo(mS4);
-                Log.d(TAG, "S2.exit");
+
+                assertEquals(TEST_CMD_1, getCurrentMessage().what);
+                addLogRec(EXIT);
+
+                log("S2.exit");
             }
             @Override
             public boolean processMessage(Message message) {
                 // Start a transition to S3 but it will be
                 // changed to a transition to S4 in exit
                 transitionTo(mS3);
-                Log.d(TAG, "S2.processMessage");
+                log("S2.processMessage");
                 return HANDLED;
             }
         }
@@ -343,28 +345,28 @@ public class StateMachineTest extends TestCase {
         class S3 extends State {
             @Override
             public void enter() {
-                addLogRec(ENTER, mS3);
-                Log.d(TAG, "S3.enter");
+                addLogRec(ENTER);
+                log("S3.enter");
             }
             @Override
             public void exit() {
-                addLogRec(EXIT, mS3);
-                Log.d(TAG, "S3.exit");
+                addLogRec(EXIT);
+                log("S3.exit");
             }
         }
 
         class S4 extends State {
             @Override
             public void enter() {
-                addLogRec(ENTER, mS4);
+                addLogRec(ENTER);
                 // Test that we can do halting in an enter/exit
                 transitionToHaltingState();
-                Log.d(TAG, "S4.enter");
+                log("S4.enter");
             }
             @Override
             public void exit() {
-                addLogRec(EXIT, mS4);
-                Log.d(TAG, "S4.exit");
+                addLogRec(EXIT);
+                log("S4.exit");
             }
         }
 
@@ -390,7 +392,7 @@ public class StateMachineTest extends TestCase {
             new StateMachineEnterExitTransitionToTest("smEnterExitTranstionToTest");
         smEnterExitTranstionToTest.start();
         if (smEnterExitTranstionToTest.isDbg()) {
-            Log.d(TAG, "testStateMachineEnterExitTransitionToTest E");
+            tlog("testStateMachineEnterExitTransitionToTest E");
         }
 
         synchronized (smEnterExitTranstionToTest) {
@@ -400,13 +402,14 @@ public class StateMachineTest extends TestCase {
                 // wait for the messages to be handled
                 smEnterExitTranstionToTest.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testStateMachineEnterExitTransitionToTest: exception while waiting "
+                tloge("testStateMachineEnterExitTransitionToTest: exception while waiting "
                     + e.getMessage());
             }
         }
 
-        assertEquals(smEnterExitTranstionToTest.getLogRecCount(), 9);
+        dumpLogRecs(smEnterExitTranstionToTest);
 
+        assertEquals(9, smEnterExitTranstionToTest.getLogRecCount());
         LogRec lr;
 
         lr = smEnterExitTranstionToTest.getLogRec(0);
@@ -425,29 +428,44 @@ public class StateMachineTest extends TestCase {
         assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(smEnterExitTranstionToTest.mS2, lr.getState());
         assertEquals(smEnterExitTranstionToTest.mS2, lr.getOriginalState());
+        assertEquals(smEnterExitTranstionToTest.mS3, lr.getDestState());
 
         lr = smEnterExitTranstionToTest.getLogRec(4);
-        assertEquals(EXIT, lr.getInfo());
+        assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(smEnterExitTranstionToTest.mS2, lr.getState());
+        assertEquals(smEnterExitTranstionToTest.mS2, lr.getOriginalState());
+        assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
+        assertEquals(EXIT, lr.getInfo());
 
         lr = smEnterExitTranstionToTest.getLogRec(5);
+        assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(ENTER, lr.getInfo());
         assertEquals(smEnterExitTranstionToTest.mS3, lr.getState());
+        assertEquals(smEnterExitTranstionToTest.mS3, lr.getOriginalState());
+        assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
 
         lr = smEnterExitTranstionToTest.getLogRec(6);
+        assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(EXIT, lr.getInfo());
         assertEquals(smEnterExitTranstionToTest.mS3, lr.getState());
+        assertEquals(smEnterExitTranstionToTest.mS3, lr.getOriginalState());
+        assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
 
         lr = smEnterExitTranstionToTest.getLogRec(7);
+        assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(ENTER, lr.getInfo());
         assertEquals(smEnterExitTranstionToTest.mS4, lr.getState());
+        assertEquals(smEnterExitTranstionToTest.mS4, lr.getOriginalState());
+        assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
 
         lr = smEnterExitTranstionToTest.getLogRec(8);
+        assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(EXIT, lr.getInfo());
         assertEquals(smEnterExitTranstionToTest.mS4, lr.getState());
+        assertEquals(smEnterExitTranstionToTest.mS4, lr.getOriginalState());
 
         if (smEnterExitTranstionToTest.isDbg()) {
-            Log.d(TAG, "testStateMachineEnterExitTransitionToTest X");
+            tlog("testStateMachineEnterExitTransitionToTest X");
         }
     }
 
@@ -495,7 +513,7 @@ public class StateMachineTest extends TestCase {
 
         StateMachine0 sm0 = new StateMachine0("sm0");
         sm0.start();
-        if (sm0.isDbg()) Log.d(TAG, "testStateMachine0 E");
+        if (sm0.isDbg()) tlog("testStateMachine0 E");
 
         synchronized (sm0) {
             // Send 6 messages
@@ -507,13 +525,15 @@ public class StateMachineTest extends TestCase {
                 // wait for the messages to be handled
                 sm0.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testStateMachine0: exception while waiting " + e.getMessage());
+                tloge("testStateMachine0: exception while waiting " + e.getMessage());
             }
         }
 
         assertEquals(6, sm0.getLogRecCount());
         assertEquals(3, sm0.getLogRecSize());
 
+        dumpLogRecs(sm0);
+
         LogRec lr;
         lr = sm0.getLogRec(0);
         assertEquals(TEST_CMD_4, lr.getWhat());
@@ -530,7 +550,7 @@ public class StateMachineTest extends TestCase {
         assertEquals(sm0.mS1, lr.getState());
         assertEquals(sm0.mS1, lr.getOriginalState());
 
-        if (sm0.isDbg()) Log.d(TAG, "testStateMachine0 X");
+        if (sm0.isDbg()) tlog("testStateMachine0 X");
     }
 
     /**
@@ -550,7 +570,7 @@ public class StateMachineTest extends TestCase {
 
             // Set the initial state
             setInitialState(mS1);
-            if (DBG) Log.d(TAG, "StateMachine1: ctor X");
+            if (DBG) log("StateMachine1: ctor X");
         }
 
         class S1 extends State {
@@ -595,7 +615,7 @@ public class StateMachineTest extends TestCase {
     public void testStateMachine1() throws Exception {
         StateMachine1 sm1 = new StateMachine1("sm1");
         sm1.start();
-        if (sm1.isDbg()) Log.d(TAG, "testStateMachine1 E");
+        if (sm1.isDbg()) tlog("testStateMachine1 E");
 
         synchronized (sm1) {
             // Send two messages
@@ -606,7 +626,7 @@ public class StateMachineTest extends TestCase {
                 // wait for the messages to be handled
                 sm1.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testStateMachine1: exception while waiting " + e.getMessage());
+                tloge("testStateMachine1: exception while waiting " + e.getMessage());
             }
         }
 
@@ -629,7 +649,7 @@ public class StateMachineTest extends TestCase {
         assertEquals(2, sm1.mEnterCount);
         assertEquals(2, sm1.mExitCount);
 
-        if (sm1.isDbg()) Log.d(TAG, "testStateMachine1 X");
+        if (sm1.isDbg()) tlog("testStateMachine1 X");
     }
 
     /**
@@ -651,7 +671,7 @@ public class StateMachineTest extends TestCase {
 
             // Set the initial state
             setInitialState(mS1);
-            if (DBG) Log.d(TAG, "StateMachine2: ctor X");
+            if (DBG) log("StateMachine2: ctor X");
         }
 
         class S1 extends State {
@@ -702,7 +722,7 @@ public class StateMachineTest extends TestCase {
     public void testStateMachine2() throws Exception {
         StateMachine2 sm2 = new StateMachine2("sm2");
         sm2.start();
-        if (sm2.isDbg()) Log.d(TAG, "testStateMachine2 E");
+        if (sm2.isDbg()) tlog("testStateMachine2 E");
 
         synchronized (sm2) {
             // Send two messages
@@ -713,7 +733,7 @@ public class StateMachineTest extends TestCase {
                 // wait for the messages to be handled
                 sm2.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testStateMachine2: exception while waiting " + e.getMessage());
+                tloge("testStateMachine2: exception while waiting " + e.getMessage());
             }
         }
 
@@ -739,7 +759,7 @@ public class StateMachineTest extends TestCase {
         assertTrue(sm2.mDidEnter);
         assertTrue(sm2.mDidExit);
 
-        if (sm2.isDbg()) Log.d(TAG, "testStateMachine2 X");
+        if (sm2.isDbg()) tlog("testStateMachine2 X");
     }
 
     /**
@@ -760,7 +780,7 @@ public class StateMachineTest extends TestCase {
 
             // Set the initial state will be the child
             setInitialState(mChildState);
-            if (DBG) Log.d(TAG, "StateMachine3: ctor X");
+            if (DBG) log("StateMachine3: ctor X");
         }
 
         class ParentState extends State {
@@ -796,7 +816,7 @@ public class StateMachineTest extends TestCase {
     public void testStateMachine3() throws Exception {
         StateMachine3 sm3 = new StateMachine3("sm3");
         sm3.start();
-        if (sm3.isDbg()) Log.d(TAG, "testStateMachine3 E");
+        if (sm3.isDbg()) tlog("testStateMachine3 E");
 
         synchronized (sm3) {
             // Send two messages
@@ -807,7 +827,7 @@ public class StateMachineTest extends TestCase {
                 // wait for the messages to be handled
                 sm3.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testStateMachine3: exception while waiting " + e.getMessage());
+                tloge("testStateMachine3: exception while waiting " + e.getMessage());
             }
         }
 
@@ -824,7 +844,7 @@ public class StateMachineTest extends TestCase {
         assertEquals(sm3.mParentState, lr.getState());
         assertEquals(sm3.mChildState, lr.getOriginalState());
 
-        if (sm3.isDbg()) Log.d(TAG, "testStateMachine3 X");
+        if (sm3.isDbg()) tlog("testStateMachine3 X");
     }
 
     /**
@@ -847,7 +867,7 @@ public class StateMachineTest extends TestCase {
 
             // Set the initial state will be child 1
             setInitialState(mChildState1);
-            if (DBG) Log.d(TAG, "StateMachine4: ctor X");
+            if (DBG) log("StateMachine4: ctor X");
         }
 
         class ParentState extends State {
@@ -892,7 +912,7 @@ public class StateMachineTest extends TestCase {
     public void testStateMachine4() throws Exception {
         StateMachine4 sm4 = new StateMachine4("sm4");
         sm4.start();
-        if (sm4.isDbg()) Log.d(TAG, "testStateMachine4 E");
+        if (sm4.isDbg()) tlog("testStateMachine4 E");
 
         synchronized (sm4) {
             // Send two messages
@@ -903,7 +923,7 @@ public class StateMachineTest extends TestCase {
                 // wait for the messages to be handled
                 sm4.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testStateMachine4: exception while waiting " + e.getMessage());
+                tloge("testStateMachine4: exception while waiting " + e.getMessage());
             }
         }
 
@@ -921,7 +941,7 @@ public class StateMachineTest extends TestCase {
         assertEquals(sm4.mParentState, lr.getState());
         assertEquals(sm4.mChildState2, lr.getOriginalState());
 
-        if (sm4.isDbg()) Log.d(TAG, "testStateMachine4 X");
+        if (sm4.isDbg()) tlog("testStateMachine4 X");
     }
 
     /**
@@ -947,7 +967,7 @@ public class StateMachineTest extends TestCase {
 
             // Set the initial state will be the child
             setInitialState(mChildState1);
-            if (DBG) Log.d(TAG, "StateMachine5: ctor X");
+            if (DBG) log("StateMachine5: ctor X");
         }
 
         class ParentState1 extends State {
@@ -1187,7 +1207,7 @@ public class StateMachineTest extends TestCase {
     public void testStateMachine5() throws Exception {
         StateMachine5 sm5 = new StateMachine5("sm5");
         sm5.start();
-        if (sm5.isDbg()) Log.d(TAG, "testStateMachine5 E");
+        if (sm5.isDbg()) tlog("testStateMachine5 E");
 
         synchronized (sm5) {
             // Send 6 messages
@@ -1202,7 +1222,7 @@ public class StateMachineTest extends TestCase {
                 // wait for the messages to be handled
                 sm5.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testStateMachine5: exception while waiting " + e.getMessage());
+                tloge("testStateMachine5: exception while waiting " + e.getMessage());
             }
         }
 
@@ -1255,7 +1275,7 @@ public class StateMachineTest extends TestCase {
         assertEquals(sm5.mParentState2, lr.getState());
         assertEquals(sm5.mParentState2, lr.getOriginalState());
 
-        if (sm5.isDbg()) Log.d(TAG, "testStateMachine5 X");
+        if (sm5.isDbg()) tlog("testStateMachine5 X");
     }
 
     /**
@@ -1274,7 +1294,7 @@ public class StateMachineTest extends TestCase {
 
             // Set the initial state
             setInitialState(mS1);
-            if (DBG) Log.d(TAG, "StateMachine6: ctor X");
+            if (DBG) log("StateMachine6: ctor X");
         }
 
         class S1 extends State {
@@ -1315,7 +1335,7 @@ public class StateMachineTest extends TestCase {
 
         StateMachine6 sm6 = new StateMachine6("sm6");
         sm6.start();
-        if (sm6.isDbg()) Log.d(TAG, "testStateMachine6 E");
+        if (sm6.isDbg()) tlog("testStateMachine6 E");
 
         synchronized (sm6) {
             // Send a message
@@ -1325,7 +1345,7 @@ public class StateMachineTest extends TestCase {
                 // wait for the messages to be handled
                 sm6.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testStateMachine6: exception while waiting " + e.getMessage());
+                tloge("testStateMachine6: exception while waiting " + e.getMessage());
             }
         }
 
@@ -1336,11 +1356,11 @@ public class StateMachineTest extends TestCase {
          */
         long arrivalTimeDiff = sm6.mArrivalTimeMsg2 - sm6.mArrivalTimeMsg1;
         long expectedDelay = DELAY_TIME - DELAY_FUDGE;
-        if (sm6.isDbg()) Log.d(TAG, "testStateMachine6: expect " + arrivalTimeDiff
+        if (sm6.isDbg()) tlog("testStateMachine6: expect " + arrivalTimeDiff
                                     + " >= " + expectedDelay);
         assertTrue(arrivalTimeDiff >= expectedDelay);
 
-        if (sm6.isDbg()) Log.d(TAG, "testStateMachine6 X");
+        if (sm6.isDbg()) tlog("testStateMachine6 X");
     }
 
     /**
@@ -1361,7 +1381,7 @@ public class StateMachineTest extends TestCase {
 
             // Set the initial state
             setInitialState(mS1);
-            if (DBG) Log.d(TAG, "StateMachine7: ctor X");
+            if (DBG) log("StateMachine7: ctor X");
         }
 
         class S1 extends State {
@@ -1421,7 +1441,7 @@ public class StateMachineTest extends TestCase {
 
         StateMachine7 sm7 = new StateMachine7("sm7");
         sm7.start();
-        if (sm7.isDbg()) Log.d(TAG, "testStateMachine7 E");
+        if (sm7.isDbg()) tlog("testStateMachine7 E");
 
         synchronized (sm7) {
             // Send a message
@@ -1431,7 +1451,7 @@ public class StateMachineTest extends TestCase {
                 // wait for the messages to be handled
                 sm7.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testStateMachine7: exception while waiting " + e.getMessage());
+                tloge("testStateMachine7: exception while waiting " + e.getMessage());
             }
         }
 
@@ -1442,11 +1462,11 @@ public class StateMachineTest extends TestCase {
          */
         long arrivalTimeDiff = sm7.mArrivalTimeMsg3 - sm7.mArrivalTimeMsg2;
         long expectedDelay = sm7.SM7_DELAY_TIME - SM7_DELAY_FUDGE;
-        if (sm7.isDbg()) Log.d(TAG, "testStateMachine7: expect " + arrivalTimeDiff
+        if (sm7.isDbg()) tlog("testStateMachine7: expect " + arrivalTimeDiff
                                     + " >= " + expectedDelay);
         assertTrue(arrivalTimeDiff >= expectedDelay);
 
-        if (sm7.isDbg()) Log.d(TAG, "testStateMachine7 X");
+        if (sm7.isDbg()) tlog("testStateMachine7 X");
     }
 
     /**
@@ -1494,9 +1514,9 @@ public class StateMachineTest extends TestCase {
     @SmallTest
     public void testStateMachineUnhandledMessage() throws Exception {
 
-        StateMachineUnhandledMessage sm = new StateMachineUnhandledMessage("sm");
+        StateMachineUnhandledMessage sm = new StateMachineUnhandledMessage("smUnhandledMessage");
         sm.start();
-        if (sm.isDbg()) Log.d(TAG, "testStateMachineUnhandledMessage E");
+        if (sm.isDbg()) tlog("testStateMachineUnhandledMessage E");
 
         synchronized (sm) {
             // Send 2 messages
@@ -1508,15 +1528,15 @@ public class StateMachineTest extends TestCase {
                 // wait for the messages to be handled
                 sm.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testStateMachineUnhandledMessage: exception while waiting "
+                tloge("testStateMachineUnhandledMessage: exception while waiting "
                         + e.getMessage());
             }
         }
 
-        assertEquals(sm.getLogRecCount(), 2);
+        assertEquals(2, sm.getLogRecSize());
         assertEquals(2, sm.mUnhandledMessageCount);
 
-        if (sm.isDbg()) Log.d(TAG, "testStateMachineUnhandledMessage X");
+        if (sm.isDbg()) tlog("testStateMachineUnhandledMessage X");
     }
 
     /**
@@ -1569,7 +1589,7 @@ public class StateMachineTest extends TestCase {
 
     @MediumTest
     public void testStateMachineSharedThread() throws Exception {
-        if (DBG) Log.d(TAG, "testStateMachineSharedThread E");
+        if (DBG) tlog("testStateMachineSharedThread E");
 
         // Create and start the handler thread
         HandlerThread smThread = new HandlerThread("testStateMachineSharedThread");
@@ -1578,7 +1598,8 @@ public class StateMachineTest extends TestCase {
         // Create the state machines
         StateMachineSharedThread sms[] = new StateMachineSharedThread[10];
         for (int i = 0; i < sms.length; i++) {
-            sms[i] = new StateMachineSharedThread("sm", smThread.getLooper(), sms.length);
+            sms[i] = new StateMachineSharedThread("smSharedThread",
+                        smThread.getLooper(), sms.length);
             sms[i].start();
         }
 
@@ -1594,14 +1615,14 @@ public class StateMachineTest extends TestCase {
             try {
                 waitObject.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testStateMachineSharedThread: exception while waiting "
+                tloge("testStateMachineSharedThread: exception while waiting "
                         + e.getMessage());
             }
         }
 
         for (StateMachineSharedThread sm : sms) {
-            assertEquals(sm.getLogRecCount(), 4);
-            for (int i = 0; i < sm.getLogRecCount(); i++) {
+            assertEquals(4, sm.getLogRecCount());
+            for (int i = 0; i < sm.getLogRecSize(); i++) {
                 LogRec lr = sm.getLogRec(i);
                 assertEquals(i+1, lr.getWhat());
                 assertEquals(sm.mS1, lr.getState());
@@ -1609,12 +1630,168 @@ public class StateMachineTest extends TestCase {
             }
         }
 
-        if (DBG) Log.d(TAG, "testStateMachineSharedThread X");
+        if (DBG) tlog("testStateMachineSharedThread X");
+    }
+
+    static class Hsm1 extends StateMachine {
+        private static final String HSM1_TAG = "hsm1";
+
+        public static final int CMD_1 = 1;
+        public static final int CMD_2 = 2;
+        public static final int CMD_3 = 3;
+        public static final int CMD_4 = 4;
+        public static final int CMD_5 = 5;
+
+        public static Hsm1 makeHsm1() {
+            Log.d(HSM1_TAG, "makeHsm1 E");
+            Hsm1 sm = new Hsm1(HSM1_TAG);
+            sm.start();
+            Log.d(HSM1_TAG, "makeHsm1 X");
+            return sm;
+        }
+
+        Hsm1(String name) {
+            super(name);
+            log("ctor E");
+
+            // Add states, use indentation to show hierarchy
+            addState(mP1);
+                addState(mS1, mP1);
+                addState(mS2, mP1);
+            addState(mP2);
+
+            // Set the initial state
+            setInitialState(mS1);
+            log("ctor X");
+        }
+
+        class P1 extends State {
+            @Override
+            public void enter() {
+                log("P1.enter");
+            }
+            @Override
+            public void exit() {
+                log("P1.exit");
+            }
+            @Override
+            public boolean processMessage(Message message) {
+                boolean retVal;
+                log("P1.processMessage what=" + message.what);
+                switch(message.what) {
+                case CMD_2:
+                    // CMD_2 will arrive in mS2 before CMD_3
+                    sendMessage(CMD_3);
+                    deferMessage(message);
+                    transitionTo(mS2);
+                    retVal = true;
+                    break;
+                default:
+                    // Any message we don't understand in this state invokes unhandledMessage
+                    retVal = false;
+                    break;
+                }
+                return retVal;
+            }
+        }
+
+        class S1 extends State {
+            @Override
+            public void enter() {
+                log("S1.enter");
+            }
+            @Override
+            public void exit() {
+                log("S1.exit");
+            }
+            @Override
+            public boolean processMessage(Message message) {
+                log("S1.processMessage what=" + message.what);
+                if (message.what == CMD_1) {
+                    // Transition to ourself to show that enter/exit is called
+                    transitionTo(mS1);
+                    return HANDLED;
+                } else {
+                    // Let parent process all other messages
+                    return NOT_HANDLED;
+                }
+            }
+        }
+
+        class S2 extends State {
+            @Override
+            public void enter() {
+                log("S2.enter");
+            }
+            @Override
+            public void exit() {
+                log("S2.exit");
+            }
+            @Override
+            public boolean processMessage(Message message) {
+                boolean retVal;
+                log("S2.processMessage what=" + message.what);
+                switch(message.what) {
+                case(CMD_2):
+                    sendMessage(CMD_4);
+                    retVal = true;
+                    break;
+                case(CMD_3):
+                    deferMessage(message);
+                    transitionTo(mP2);
+                    retVal = true;
+                    break;
+                default:
+                    retVal = false;
+                    break;
+                }
+                return retVal;
+            }
+        }
+
+        class P2 extends State {
+            @Override
+            public void enter() {
+                log("P2.enter");
+                sendMessage(CMD_5);
+            }
+            @Override
+            public void exit() {
+                log("P2.exit");
+            }
+            @Override
+            public boolean processMessage(Message message) {
+                log("P2.processMessage what=" + message.what);
+                switch(message.what) {
+                case(CMD_3):
+                    break;
+                case(CMD_4):
+                    break;
+                case(CMD_5):
+                    transitionToHaltingState();
+                    break;
+                }
+                return HANDLED;
+            }
+        }
+
+        @Override
+        protected void onHalting() {
+            log("halting");
+            synchronized (this) {
+                this.notifyAll();
+            }
+        }
+
+        P1 mP1 = new P1();
+        S1 mS1 = new S1();
+        S2 mS2 = new S2();
+        P2 mP2 = new P2();
     }
 
     @MediumTest
     public void testHsm1() throws Exception {
-        if (DBG) Log.d(TAG, "testHsm1 E");
+        if (DBG) tlog("testHsm1 E");
 
         Hsm1 sm = Hsm1.makeHsm1();
 
@@ -1627,11 +1804,14 @@ public class StateMachineTest extends TestCase {
             try {
                 sm.wait();
             } catch (InterruptedException e) {
-                Log.e(TAG, "testHsm1: exception while waiting " + e.getMessage());
+                tloge("testHsm1: exception while waiting " + e.getMessage());
             }
         }
 
+        dumpLogRecs(sm);
+
         assertEquals(7, sm.getLogRecCount());
+
         LogRec lr = sm.getLogRec(0);
         assertEquals(Hsm1.CMD_1, lr.getWhat());
         assertEquals(sm.mS1, lr.getState());
@@ -1667,162 +1847,14 @@ public class StateMachineTest extends TestCase {
         assertEquals(sm.mP2, lr.getState());
         assertEquals(sm.mP2, lr.getOriginalState());
 
-        if (DBG) Log.d(TAG, "testStateMachineSharedThread X");
-    }
-}
-
-class Hsm1 extends StateMachine {
-    private static final String TAG = "hsm1";
-
-    public static final int CMD_1 = 1;
-    public static final int CMD_2 = 2;
-    public static final int CMD_3 = 3;
-    public static final int CMD_4 = 4;
-    public static final int CMD_5 = 5;
-
-    public static Hsm1 makeHsm1() {
-        Log.d(TAG, "makeHsm1 E");
-        Hsm1 sm = new Hsm1("hsm1");
-        sm.start();
-        Log.d(TAG, "makeHsm1 X");
-        return sm;
-    }
-
-    Hsm1(String name) {
-        super(name);
-        Log.d(TAG, "ctor E");
-
-        // Add states, use indentation to show hierarchy
-        addState(mP1);
-            addState(mS1, mP1);
-            addState(mS2, mP1);
-        addState(mP2);
-
-        // Set the initial state
-        setInitialState(mS1);
-        Log.d(TAG, "ctor X");
-    }
-
-    class P1 extends State {
-        @Override
-        public void enter() {
-            Log.d(TAG, "P1.enter");
-        }
-        @Override
-        public void exit() {
-            Log.d(TAG, "P1.exit");
-        }
-        @Override
-        public boolean processMessage(Message message) {
-            boolean retVal;
-            Log.d(TAG, "P1.processMessage what=" + message.what);
-            switch(message.what) {
-            case CMD_2:
-                // CMD_2 will arrive in mS2 before CMD_3
-                sendMessage(CMD_3);
-                deferMessage(message);
-                transitionTo(mS2);
-                retVal = true;
-                break;
-            default:
-                // Any message we don't understand in this state invokes unhandledMessage
-                retVal = false;
-                break;
-            }
-            return retVal;
-        }
+        if (DBG) tlog("testStateMachineSharedThread X");
     }
 
-    class S1 extends State {
-        @Override
-        public void enter() {
-            Log.d(TAG, "S1.enter");
-        }
-        @Override
-        public void exit() {
-            Log.d(TAG, "S1.exit");
-        }
-        @Override
-        public boolean processMessage(Message message) {
-            Log.d(TAG, "S1.processMessage what=" + message.what);
-            if (message.what == CMD_1) {
-                // Transition to ourself to show that enter/exit is called
-                transitionTo(mS1);
-                return HANDLED;
-            } else {
-                // Let parent process all other messages
-                return NOT_HANDLED;
-            }
-        }
+    private void tlog(String s) {
+        Log.d(TAG, s);
     }
 
-    class S2 extends State {
-        @Override
-        public void enter() {
-            Log.d(TAG, "S2.enter");
-        }
-        @Override
-        public void exit() {
-            Log.d(TAG, "S2.exit");
-        }
-        @Override
-        public boolean processMessage(Message message) {
-            boolean retVal;
-            Log.d(TAG, "S2.processMessage what=" + message.what);
-            switch(message.what) {
-            case(CMD_2):
-                sendMessage(CMD_4);
-                retVal = true;
-                break;
-            case(CMD_3):
-                deferMessage(message);
-                transitionTo(mP2);
-                retVal = true;
-                break;
-            default:
-                retVal = false;
-                break;
-            }
-            return retVal;
-        }
-    }
-
-    class P2 extends State {
-        @Override
-        public void enter() {
-            Log.d(TAG, "P2.enter");
-            sendMessage(CMD_5);
-        }
-        @Override
-        public void exit() {
-            Log.d(TAG, "P2.exit");
-        }
-        @Override
-        public boolean processMessage(Message message) {
-            Log.d(TAG, "P2.processMessage what=" + message.what);
-            switch(message.what) {
-            case(CMD_3):
-                break;
-            case(CMD_4):
-                break;
-            case(CMD_5):
-                transitionToHaltingState();
-                break;
-            }
-            return HANDLED;
-        }
+    private void tloge(String s) {
+        Log.e(TAG, s);
     }
-
-    @Override
-    protected void onHalting() {
-        Log.d(TAG, "halting");
-        synchronized (this) {
-            this.notifyAll();
-        }
-    }
-
-    P1 mP1 = new P1();
-    S1 mS1 = new S1();
-    S2 mS2 = new S2();
-    P2 mP2 = new P2();
 }