Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1070027
  • 博文数量: 169
  • 博客积分: 12306
  • 博客等级: 上将
  • 技术积分: 1299
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-29 14:55
文章分类

全部博文(169)

文章存档

2012年(18)

2011年(78)

2010年(15)

2009年(1)

2008年(11)

2007年(39)

2006年(7)

我的朋友

分类: LINUX

2012-03-09 17:05:28

  1. /** 
  2.  * Copyright (C) 2009 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package com.android.internal.util;  
  18.   
  19. import android.os.Handler;  
  20. import android.os.HandlerThread;  
  21. import android.os.Looper;  
  22. import android.os.Message;  
  23. import android.util.Log;  
  24.   
  25. import java.util.ArrayList;  
  26. import java.util.HashMap;  
  27.   
  28. /** 
  29.  * {@hide} 
  30.  * 
  31.  * A hierarchical state machine is a state machine which processes messages 
  32.  * and can have states arranged hierarchically. A state is a HierarchicalState 
  33.  * object and must implement processMessage and optionally enter/exit/getName. 
  34.  * The enter/exit methods are equivalent to the construction and destruction 
  35.  * in Object Oriented programming and are used to perform initialization and 
  36.  * cleanup of the state respectively. The getName method returns the 
  37.  * name of the state the default implementation returns the class name it may be 
  38.  * desirable to have this return the name of the state instance name instead. 
  39.  * In particular if a particular state class has multiple instances. 
  40.  * 
  41.  * When a state machine is created addState is used to build the 
  42.  * hierarchy and setInitialState is used to identify which of these 
  43.  * is the initial state. After construction the programmer calls start 
  44.  * which initializes the state machine and calls enter for all of the initial 
  45.  * state's hierarchy, starting at its eldest parent. For example given the simple 
  46.  * state machine below after start is called mP1.enter will have been called and 
  47.  * then mS1.enter. 
  48.  
  49.         mP1 
  50.        /   \ 
  51.       mS2   mS1 ----> initial state 
  52.  
  53.  * After the state machine is created and started, messages are sent to a state 
  54.  * machine using sendMessage and the messages are created using 
  55.  * obtainMessage. When the state machine receives a message the 
  56.  * current state's processMessage is invoked. In the above example 
  57.  * mS1.processMessage will be invoked first. The state may use transitionTo 
  58.  * to change the current state to a new state 
  59.  * 
  60.  * Each state in the state machine may have a zero or one parent states and if 
  61.  * a child state is unable to handle a message it may have the message processed 
  62.  * by its parent by returning false or NOT_HANDLED. If a message is never processed 
  63.  * unhandledMessage will be invoked to give one last chance for the state machine 
  64.  * to process the message. 
  65.  * 
  66.  * When all processing is completed a state machine may choose to call 
  67.  * transitionToHaltingState. When the current processingMessage 
  68.  * returns the state machine will transfer to an internal HaltingState 
  69.  * and invoke halting. Any message subsequently received by the state 
  70.  * machine will cause haltedProcessMessage to be invoked. 
  71.  * 
  72.  * If it is desirable to completely stop the state machine call quit. This 
  73.  * will exit the current state and its parent and then exit from the controlling thread 
  74.  * and no further messages will be processed. 
  75.  * 
  76.  * In addition to processMessage each HierarchicalState has 
  77.  * an enter method and exit method which may be overridden. 
  78.  * 
  79.  * Since the states are arranged in a hierarchy transitioning to a new state 
  80.  * causes current states to be exited and new states to be entered. To determine 
  81.  * the list of states to be entered/exited the common parent closest to 
  82.  * the current state is found. We then exit from the current state and its 
  83.  * parent's up to but not including the common parent state and then enter all 
  84.  * of the new states below the common parent down to the destination state. 
  85.  * If there is no common parent all states are exited and then the new states 
  86.  * are entered. 
  87.  * 
  88.  * Two other methods that states can use are deferMessage and 
  89.  * sendMessageAtFrontOfQueue. The sendMessageAtFrontOfQueue sends 
  90.  * a message but places it on the front of the queue rather than the back. The 
  91.  * deferMessage causes the message to be saved on a list until a 
  92.  * transition is made to a new state. At which time all of the deferred messages 
  93.  * will be put on the front of the state machine queue with the oldest message 
  94.  * at the front. These will then be processed by the new current state before 
  95.  * any other messages that are on the queue or might be added later. Both of 
  96.  * these are protected and may only be invoked from within a state machine. 
  97.  * 
  98.  * To illustrate some of these properties we'll use state machine with an 8 
  99.  * state hierarchy: 
  100.  
  101.           mP0 
  102.          /   \ 
  103.         mP1   mS0 
  104.        /   \ 
  105.       mS2   mS1 
  106.      /  \    \ 
  107.     mS3  mS4  mS5  ---> initial state 
  108.  
  109.  * 
  110.  * After starting mS5 the list of active states is mP0, mP1, mS1 and mS5. 
  111.  * So the order of calling processMessage when a message is received is mS5, 
  112.  * mS1, mP1, mP0 assuming each processMessage indicates it can't handle this 
  113.  * message by returning false or NOT_HANDLED. 
  114.  * 
  115.  * Now assume mS5.processMessage receives a message it can handle, and during 
  116.  * the handling determines the machine should change states. It could call 
  117.  * transitionTo(mS4) and return true or HANDLED. Immediately after returning from 
  118.  * processMessage the state machine runtime will find the common parent, 
  119.  * which is mP1. It will then call mS5.exit, mS1.exit, mS2.enter and then 
  120.  * mS4.enter. The new list of active states is mP0, mP1, mS2 and mS4. So 
  121.  * when the next message is received mS4.processMessage will be invoked. 
  122.  * 
  123.  * Now for some concrete examples, here is the canonical HelloWorld as an HSM. 
  124.  * It responds with "Hello World" being printed to the log for every message. 
  125.  
  126. class HelloWorld extends HierarchicalStateMachine { 
  127.     Hsm1(String name) { 
  128.         super(name); 
  129.         addState(mState1); 
  130.         setInitialState(mState1); 
  131.     } 
  132.  
  133.     public static HelloWorld makeHelloWorld() { 
  134.         HelloWorld hw = new HelloWorld("hw"); 
  135.         hw.start(); 
  136.         return hw; 
  137.     } 
  138.  
  139.     class State1 extends HierarchicalState { 
  140.         @Override public boolean processMessage(Message message) { 
  141.             Log.d(TAG, "Hello World"); 
  142.             return HANDLED; 
  143.         } 
  144.     } 
  145.     State1 mState1 = new State1(); 
  146. } 
  147.  
  148. void testHelloWorld() { 
  149.     HelloWorld hw = makeHelloWorld(); 
  150.     hw.sendMessage(hw.obtainMessage()); 
  151. } 
  152.  
  153.  * 
  154.  * A more interesting state machine is one with four states 
  155.  * with two independent parent states. 
  156.  
  157.         mP1      mP2 
  158.        /   \ 
  159.       mS2   mS1 
  160.  
  161.  * 
  162.  * Here is a description of this state machine using pseudo code. 
  163.  * 
  164.  * 
  165.  * state mP1 { 
  166.  *      enter { log("mP1.enter"); } 
  167.  *      exit { log("mP1.exit");  } 
  168.  *      on msg { 
  169.  *          CMD_2 { 
  170.  *              send(CMD_3); 
  171.  *              defer(msg); 
  172.  *              transitonTo(mS2); 
  173.  *              return HANDLED; 
  174.  *          } 
  175.  *          return NOT_HANDLED; 
  176.  *      } 
  177.  * } 
  178.  * 
  179.  * INITIAL 
  180.  * state mS1 parent mP1 { 
  181.  *      enter { log("mS1.enter"); } 
  182.  *      exit  { log("mS1.exit");  } 
  183.  *      on msg { 
  184.  *          CMD_1 { 
  185.  *              transitionTo(mS1); 
  186.  *              return HANDLED; 
  187.  *          } 
  188.  *          return NOT_HANDLED; 
  189.  *      } 
  190.  * } 
  191.  * 
  192.  * state mS2 parent mP1 { 
  193.  *      enter { log("mS2.enter"); } 
  194.  *      exit  { log("mS2.exit");  } 
  195.  *      on msg { 
  196.  *          CMD_2 { 
  197.  *              send(CMD_4); 
  198.  *              return HANDLED; 
  199.  *          } 
  200.  *          CMD_3 { 
  201.  *              defer(msg); 
  202.  *              transitionTo(mP2); 
  203.  *              return HANDLED; 
  204.  *          } 
  205.  *          return NOT_HANDLED; 
  206.  *      } 
  207.  * } 
  208.  * 
  209.  * state mP2 { 
  210.  *      enter { 
  211.  *          log("mP2.enter"); 
  212.  *          send(CMD_5); 
  213.  *      } 
  214.  *      exit { log("mP2.exit"); } 
  215.  *      on msg { 
  216.  *          CMD_3, CMD_4 { return HANDLED; } 
  217.  *          CMD_5 { 
  218.  *              transitionTo(HaltingState); 
  219.  *              return HANDLED; 
  220.  *          } 
  221.  *          return NOT_HANDLED; 
  222.  *      } 
  223.  * } 
  224.  * 
  225.  * The implementation is below and also in HierarchicalStateMachineTest: 
  226.  
  227. class Hsm1 extends HierarchicalStateMachine { 
  228.     private static final String TAG = "hsm1"; 
  229.  
  230.     public static final int CMD_1 = 1; 
  231.     public static final int CMD_2 = 2; 
  232.     public static final int CMD_3 = 3; 
  233.     public static final int CMD_4 = 4; 
  234.     public static final int CMD_5 = 5; 
  235.  
  236.     public static Hsm1 makeHsm1() { 
  237.         Log.d(TAG, "makeHsm1 E"); 
  238.         Hsm1 sm = new Hsm1("hsm1"); 
  239.         sm.start(); 
  240.         Log.d(TAG, "makeHsm1 X"); 
  241.         return sm; 
  242.     } 
  243.  
  244.     Hsm1(String name) { 
  245.         super(name); 
  246.         Log.d(TAG, "ctor E"); 
  247.  
  248.         // Add states, use indentation to show hierarchy 
  249.         addState(mP1); 
  250.             addState(mS1, mP1); 
  251.             addState(mS2, mP1); 
  252.         addState(mP2); 
  253.  
  254.         // Set the initial state 
  255.         setInitialState(mS1); 
  256.         Log.d(TAG, "ctor X"); 
  257.     } 
  258.  
  259.     class P1 extends HierarchicalState { 
  260.         @Override public void enter() { 
  261.             Log.d(TAG, "mP1.enter"); 
  262.         } 
  263.         @Override public boolean processMessage(Message message) { 
  264.             boolean retVal; 
  265.             Log.d(TAG, "mP1.processMessage what=" + message.what); 
  266.             switch(message.what) { 
  267.             case CMD_2: 
  268.                 // CMD_2 will arrive in mS2 before CMD_3 
  269.                 sendMessage(obtainMessage(CMD_3)); 
  270.                 deferMessage(message); 
  271.                 transitionTo(mS2); 
  272.                 retVal = HANDLED; 
  273.                 break; 
  274.             default: 
  275.                 // Any message we don't understand in this state invokes unhandledMessage 
  276.                 retVal = NOT_HANDLED; 
  277.                 break; 
  278.             } 
  279.             return retVal; 
  280.         } 
  281.         @Override public void exit() { 
  282.             Log.d(TAG, "mP1.exit"); 
  283.         } 
  284.     } 
  285.  
  286.     class S1 extends HierarchicalState { 
  287.         @Override public void enter() { 
  288.             Log.d(TAG, "mS1.enter"); 
  289.         } 
  290.         @Override public boolean processMessage(Message message) { 
  291.             Log.d(TAG, "S1.processMessage what=" + message.what); 
  292.             if (message.what == CMD_1) { 
  293.                 // Transition to ourself to show that enter/exit is called 
  294.                 transitionTo(mS1); 
  295.                 return HANDLED; 
  296.             } else { 
  297.                 // Let parent process all other messages 
  298.                 return NOT_HANDLED; 
  299.             } 
  300.         } 
  301.         @Override public void exit() { 
  302.             Log.d(TAG, "mS1.exit"); 
  303.         } 
  304.     } 
  305.  
  306.     class S2 extends HierarchicalState { 
  307.         @Override public void enter() { 
  308.             Log.d(TAG, "mS2.enter"); 
  309.         } 
  310.         @Override public boolean processMessage(Message message) { 
  311.             boolean retVal; 
  312.             Log.d(TAG, "mS2.processMessage what=" + message.what); 
  313.             switch(message.what) { 
  314.             case(CMD_2): 
  315.                 sendMessage(obtainMessage(CMD_4)); 
  316.                 retVal = HANDLED; 
  317.                 break; 
  318.             case(CMD_3): 
  319.                 deferMessage(message); 
  320.                 transitionTo(mP2); 
  321.                 retVal = HANDLED; 
  322.                 break; 
  323.             default: 
  324.                 retVal = NOT_HANDLED; 
  325.                 break; 
  326.             } 
  327.             return retVal; 
  328.         } 
  329.         @Override public void exit() { 
  330.             Log.d(TAG, "mS2.exit"); 
  331.         } 
  332.     } 
  333.  
  334.     class P2 extends HierarchicalState { 
  335.         @Override public void enter() { 
  336.             Log.d(TAG, "mP2.enter"); 
  337.             sendMessage(obtainMessage(CMD_5)); 
  338.         } 
  339.         @Override public boolean processMessage(Message message) { 
  340.             Log.d(TAG, "P2.processMessage what=" + message.what); 
  341.             switch(message.what) { 
  342.             case(CMD_3): 
  343.                 break; 
  344.             case(CMD_4): 
  345.                 break; 
  346.             case(CMD_5): 
  347.                 transitionToHaltingState(); 
  348.                 break; 
  349.             } 
  350.             return HANDLED; 
  351.         } 
  352.         @Override public void exit() { 
  353.             Log.d(TAG, "mP2.exit"); 
  354.         } 
  355.     } 
  356.  
  357.     @Override 
  358.     void halting() { 
  359.         Log.d(TAG, "halting"); 
  360.         synchronized (this) { 
  361.             this.notifyAll(); 
  362.         } 
  363.     } 
  364.  
  365.     P1 mP1 = new P1(); 
  366.     S1 mS1 = new S1(); 
  367.     S2 mS2 = new S2(); 
  368.     P2 mP2 = new P2(); 
  369. } 
  370.  
  371.  * 
  372.  * If this is executed by sending two messages CMD_1 and CMD_2 
  373.  * (Note the synchronize is only needed because we use hsm.wait()) 
  374.  * 
  375.  * Hsm1 hsm = makeHsm1(); 
  376.  * synchronize(hsm) { 
  377.  *      hsm.sendMessage(obtainMessage(hsm.CMD_1)); 
  378.  *      hsm.sendMessage(obtainMessage(hsm.CMD_2)); 
  379.  *      try { 
  380.  *           // wait for the messages to be handled 
  381.  *           hsm.wait(); 
  382.  *      } catch (InterruptedException e) { 
  383.  *           Log.e(TAG, "exception while waiting " + e.getMessage()); 
  384.  *      } 
  385.  * } 
  386.  * 
  387.  * 
  388.  * The output is: 
  389.  * 
  390.  * D/hsm1    ( 1999): makeHsm1 E 
  391.  * D/hsm1    ( 1999): ctor E 
  392.  * D/hsm1    ( 1999): ctor X 
  393.  * D/hsm1    ( 1999): mP1.enter 
  394.  * D/hsm1    ( 1999): mS1.enter 
  395.  * D/hsm1    ( 1999): makeHsm1 X 
  396.  * D/hsm1    ( 1999): mS1.processMessage what=1 
  397.  * D/hsm1    ( 1999): mS1.exit 
  398.  * D/hsm1    ( 1999): mS1.enter 
  399.  * D/hsm1    ( 1999): mS1.processMessage what=2 
  400.  * D/hsm1    ( 1999): mP1.processMessage what=2 
  401.  * D/hsm1    ( 1999): mS1.exit 
  402.  * D/hsm1    ( 1999): mS2.enter 
  403.  * D/hsm1    ( 1999): mS2.processMessage what=2 
  404.  * D/hsm1    ( 1999): mS2.processMessage what=3 
  405.  * D/hsm1    ( 1999): mS2.exit 
  406.  * D/hsm1    ( 1999): mP1.exit 
  407.  * D/hsm1    ( 1999): mP2.enter 
  408.  * D/hsm1    ( 1999): mP2.processMessage what=3 
  409.  * D/hsm1    ( 1999): mP2.processMessage what=4 
  410.  * D/hsm1    ( 1999): mP2.processMessage what=5 
  411.  * D/hsm1    ( 1999): mP2.exit 
  412.  * D/hsm1    ( 1999): halting 
  413.  * 
  414.  */  
  415. public class HierarchicalStateMachine {  
  416.   
  417.     private static final String TAG = "HierarchicalStateMachine";  
  418.     private String mName;  
  419.   
  420.     /** Message.what value when quitting */  
  421.     public static final int HSM_QUIT_CMD = -1;  
  422.   
  423.     /** Message.what value when initializing */  
  424.     public static final int HSM_INIT_CMD = -1;  
  425.   
  426.     /** 
  427.      * Convenience constant that maybe returned by processMessage 
  428.      * to indicate the the message was processed and is not to be 
  429.      * processed by parent states 
  430.      */  
  431.     public static final boolean HANDLED = true;  
  432.   
  433.     /** 
  434.      * Convenience constant that maybe returned by processMessage 
  435.      * to indicate the the message was NOT processed and is to be 
  436.      * processed by parent states 
  437.      */  
  438.     public static final boolean NOT_HANDLED = false;  
  439.   
  440.     private static class HsmHandler extends Handler {  
  441.   
  442.         /** The debug flag */  
  443.         private boolean mDbg = false;  
  444.   
  445.         /** The quit object */  
  446.         private static final Object mQuitObj = new Object();  
  447.   
  448.         /** The initialization message */  
  449.         private static final Message mInitMsg = null;  
  450.   
  451.         /** The current message */  
  452.         private Message mMsg;  
  453.   
  454.         /** A list of messages that this state machine has processed */  
  455.         private ProcessedMessages mProcessedMessages = new ProcessedMessages();  
  456.   
  457.         /** true if construction of the state machine has not been completed */  
  458.         private boolean mIsConstructionCompleted;  
  459.   
  460.         /** Stack used to manage the current hierarchy of states */  
  461.         private StateInfo mStateStack[];  
  462.   
  463.         /** Top of mStateStack */  
  464.         private int mStateStackTopIndex = -1;  
  465.   
  466.         /** A temporary stack used to manage the state stack */  
  467.         private StateInfo mTempStateStack[];  
  468.   
  469.         /** The top of the mTempStateStack */  
  470.         private int mTempStateStackCount;  
  471.   
  472.         /** State used when state machine is halted */  
  473.         private HaltingState mHaltingState = new HaltingState();  
  474.   
  475.         /** State used when state machine is quitting */  
  476.         private QuittingState mQuittingState = new QuittingState();  
  477.   
  478.         /** Reference to the HierarchicalStateMachine */  
  479.         private HierarchicalStateMachine mHsm;  
  480.   
  481.         /** 
  482.          * Information about a state. 
  483.          * Used to maintain the hierarchy. 
  484.          */  
  485.         private class StateInfo {  
  486.             /** The state */  
  487.             HierarchicalState state;  
  488.   
  489.             /** The parent of this state, null if there is no parent */  
  490.             StateInfo parentStateInfo;  
  491.   
  492.             /** True when the state has been entered and on the stack */  
  493.             boolean active;  
  494.   
  495.             /** 
  496.              * Convert StateInfo to string 
  497.              */  
  498.             @Override  
  499.             public String toString() {  
  500.                 return "state=" + state.getName() + ",active=" + active  
  501.                         + ",parent=" + ((parentStateInfo == null) ?  
  502.                                         "null" : parentStateInfo.state.getName());  
  503.             }  
  504.         }  
  505.   
  506.         /** The map of all of the states in the state machine */  
  507.         private HashMap mStateInfo =  
  508.             new HashMap();  
  509.   
  510.         /** The initial state that will process the first message */  
  511.         private HierarchicalState mInitialState;  
  512.   
  513.         /** The destination state when transitionTo has been invoked */  
  514.         private HierarchicalState mDestState;  
  515.   
  516.         /** The list of deferred messages */  
  517.         private ArrayList mDeferredMessages = new ArrayList();  
  518.   
  519.         /** 
  520.          * State entered when transitionToHaltingState is called. 
  521.          */  
  522.         private class HaltingState extends HierarchicalState {  
  523.             @Override  
  524.             public boolean processMessage(Message msg) {  
  525.                 mHsm.haltedProcessMessage(msg);  
  526.                 return true;  
  527.             }  
  528.         }  
  529.   
  530.         /** 
  531.          * State entered when a valid quit message is handled. 
  532.          */  
  533.         private class QuittingState extends HierarchicalState {  
  534.             @Override  
  535.             public boolean processMessage(Message msg) {  
  536.                 return NOT_HANDLED;  
  537.             }  
  538.         }  
  539.   
  540.         /** 
  541.          * Handle messages sent to the state machine by calling 
  542.          * the current state's processMessage. It also handles 
  543.          * the enter/exit calls and placing any deferred messages 
  544.          * back onto the queue when transitioning to a new state. 
  545.          */  
  546.         @Override  
  547.         public final void handleMessage(Message msg) {  
  548.             if (mDbg) Log.d(TAG, "handleMessage: E msg.what=" + msg.what);  
  549.   
  550.             /** Save the current message */  
  551.             mMsg = msg;  
  552.   
  553.             /** 
  554.              * Check that construction was completed 
  555.              */  
  556.             if (!mIsConstructionCompleted) {  
  557.                 Log.e(TAG, "The start method not called, ignore msg: " + msg);  
  558.                 return;  
  559.             }  
  560.   
  561.             /** 
  562.              * Process the message abiding by the hierarchical semantics 
  563.              * and perform any requested transitions. 
  564.              */  
  565.             processMsg(msg);  
  566.             performTransitions();  
  567.   
  568.             if (mDbg) Log.d(TAG, "handleMessage: X");  
  569.         }  
  570.   
  571.         /** 
  572.          * Do any transitions 
  573.          */  
  574.         private void performTransitions() {  
  575.             /** 
  576.              * If transitionTo has been called, exit and then enter 
  577.              * the appropriate states. We loop on this to allow 
  578.              * enter and exit methods to use transitionTo. 
  579.              */  
  580.             HierarchicalState destState = null;  
  581.             while (mDestState != null) {  
  582.                 if (mDbg) Log.d(TAG, "handleMessage: new destination call exit");  
  583.   
  584.                 /** 
  585.                  * Save mDestState locally and set to null 
  586.                  * to know if enter/exit use transitionTo. 
  587.                  */  
  588.                 destState = mDestState;  
  589.                 mDestState = null;  
  590.   
  591.                 /** 
  592.                  * Determine the states to exit and enter and return the 
  593.                  * common ancestor state of the enter/exit states. Then 
  594.                  * invoke the exit methods then the enter methods. 
  595.                  */  
  596.                 StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);  
  597.                 invokeExitMethods(commonStateInfo);  
  598.                 int stateStackEnteringIndex = moveTempStateStackToStateStack();  
  599.                 invokeEnterMethods(stateStackEnteringIndex);  
  600.   
  601.   
  602.                 /** 
  603.                  * Since we have transitioned to a new state we need to have 
  604.                  * any deferred messages moved to the front of the message queue 
  605.                  * so they will be processed before any other messages in the 
  606.                  * message queue. 
  607.                  */  
  608.                 moveDeferredMessageAtFrontOfQueue();  
  609.             }  
  610.   
  611.             /** 
  612.              * After processing all transitions check and 
  613.              * see if the last transition was to quit or halt. 
  614.              */  
  615.             if (destState != null) {  
  616.                 if (destState == mQuittingState) {  
  617.                     /** 
  618.                      * We are quitting so ignore all messages. 
  619.                      */  
  620.                     mHsm.quitting();  
  621.                     if (mHsm.mHsmThread != null) {  
  622.                         // If we made the thread then quit looper  
  623.                         getLooper().quit();  
  624.                     }  
  625.                 } else if (destState == mHaltingState) {  
  626.                     /** 
  627.                      * Call halting() if we've transitioned to the halting 
  628.                      * state. All subsequent messages will be processed in 
  629.                      * in the halting state which invokes haltedProcessMessage(msg); 
  630.                      */  
  631.                     mHsm.halting();  
  632.                 }  
  633.             }  
  634.         }  
  635.   
  636.         /** 
  637.          * Complete the construction of the state machine. 
  638.          */  
  639.         private final void completeConstruction() {  
  640.             if (mDbg) Log.d(TAG, "completeConstruction: E");  
  641.   
  642.             /** 
  643.              * Determine the maximum depth of the state hierarchy 
  644.              * so we can allocate the state stacks. 
  645.              */  
  646.             int maxDepth = 0;  
  647.             for (StateInfo si : mStateInfo.values()) {  
  648.                 int depth = 0;  
  649.                 for (StateInfo i = si; i != null; depth++) {  
  650.                     i = i.parentStateInfo;  
  651.                 }  
  652.                 if (maxDepth < depth) {  
  653.                     maxDepth = depth;  
  654.                 }  
  655.             }  
  656.             if (mDbg) Log.d(TAG, "completeConstruction: maxDepth=" + maxDepth);  
  657.   
  658.             mStateStack = new StateInfo[maxDepth];  
  659.             mTempStateStack = new StateInfo[maxDepth];  
  660.             setupInitialStateStack();  
  661.   
  662.             /** 
  663.              * Construction is complete call all enter methods 
  664.              * starting at the first entry. 
  665.              */  
  666.             mIsConstructionCompleted = true;  
  667.             mMsg = obtainMessage(HSM_INIT_CMD);  
  668.             invokeEnterMethods(0);  
  669.   
  670.             /** 
  671.              * Perform any transitions requested by the enter methods 
  672.              */  
  673.             performTransitions();  
  674.   
  675.             if (mDbg) Log.d(TAG, "completeConstruction: X");  
  676.         }  
  677.   
  678.         /** 
  679.          * Process the message. If the current state doesn't handle 
  680.          * it, call the states parent and so on. If it is never handled then 
  681.          * call the state machines unhandledMessage method. 
  682.          */  
  683.         private final void processMsg(Message msg) {  
  684.             StateInfo curStateInfo = mStateStack[mStateStackTopIndex];  
  685.             if (mDbg) {  
  686.                 Log.d(TAG, "processMsg: " + curStateInfo.state.getName());  
  687.             }  
  688.             while (!curStateInfo.state.processMessage(msg)) {  
  689.                 /** 
  690.                  * Not processed 
  691.                  */  
  692.                 curStateInfo = curStateInfo.parentStateInfo;  
  693.                 if (curStateInfo == null) {  
  694.                     /** 
  695.                      * No parents left so it's not handled 
  696.                      */  
  697.                     mHsm.unhandledMessage(msg);  
  698.                     if (isQuit(msg)) {  
  699.                         transitionTo(mQuittingState);  
  700.                     }  
  701.                     break;  
  702.                 }  
  703.                 if (mDbg) {  
  704.                     Log.d(TAG, "processMsg: " + curStateInfo.state.getName());  
  705.                 }  
  706.             }  
  707.   
  708.             /** 
  709.              * Record that we processed the message 
  710.              */  
  711.             if (curStateInfo != null) {  
  712.                 HierarchicalState orgState = mStateStack[mStateStackTopIndex].state;  
  713.                 mProcessedMessages.add(msg, curStateInfo.state, orgState);  
  714.             } else {  
  715.                 mProcessedMessages.add(msg, nullnull);  
  716.             }  
  717.         }  
  718.   
  719.         /** 
  720.          * Call the exit method for each state from the top of stack 
  721.          * up to the common ancestor state. 
  722.          */  
  723.         private final void invokeExitMethods(StateInfo commonStateInfo) {  
  724.             while ((mStateStackTopIndex >= 0) &&  
  725.                     (mStateStack[mStateStackTopIndex] != commonStateInfo)) {  
  726.                 HierarchicalState curState = mStateStack[mStateStackTopIndex].state;  
  727.                 if (mDbg) Log.d(TAG, "invokeExitMethods: " + curState.getName());  
  728.                 curState.exit();  
  729.                 mStateStack[mStateStackTopIndex].active = false;  
  730.                 mStateStackTopIndex -= 1;  
  731.             }  
  732.         }  
  733.   
  734.         /** 
  735.          * Invoke the enter method starting at the entering index to top of state stack 
  736.          */  
  737.         private final void invokeEnterMethods(int stateStackEnteringIndex) {  
  738.             for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {  
  739.                 if (mDbg) Log.d(TAG, "invokeEnterMethods: " + mStateStack[i].state.getName());  
  740.                 mStateStack[i].state.enter();  
  741.                 mStateStack[i].active = true;  
  742.             }  
  743.         }  
  744.   
  745.         /** 
  746.          * Move the deferred message to the front of the message queue. 
  747.          */  
  748.         private final void moveDeferredMessageAtFrontOfQueue() {  
  749.             /** 
  750.              * The oldest messages on the deferred list must be at 
  751.              * the front of the queue so start at the back, which 
  752.              * as the most resent message and end with the oldest 
  753.              * messages at the front of the queue. 
  754.              */  
  755.             for (int i = mDeferredMessages.size() - 1; i >= 0; i-- ) {  
  756.                 Message curMsg = mDeferredMessages.get(i);  
  757.                 if (mDbg) Log.d(TAG, "moveDeferredMessageAtFrontOfQueue; what=" + curMsg.what);  
  758.                 sendMessageAtFrontOfQueue(curMsg);  
  759.             }  
  760.             mDeferredMessages.clear();  
  761.         }  
  762.   
  763.         /** 
  764.          * Move the contents of the temporary stack to the state stack 
  765.          * reversing the order of the items on the temporary stack as 
  766.          * they are moved. 
  767.          * 
  768.          * @return index into mStateState where entering needs to start 
  769.          */  
  770.         private final int moveTempStateStackToStateStack() {  
  771.             int startingIndex = mStateStackTopIndex + 1;  
  772.             int i = mTempStateStackCount - 1;  
  773.             int j = startingIndex;  
  774.             while (i >= 0) {  
  775.                 if (mDbg) Log.d(TAG, "moveTempStackToStateStack: i=" + i + ",j=" + j);  
  776.                 mStateStack[j] = mTempStateStack[i];  
  777.                 j += 1;  
  778.                 i -= 1;  
  779.             }  
  780.   
  781.             mStateStackTopIndex = j - 1;  
  782.             if (mDbg) {  
  783.                 Log.d(TAG, "moveTempStackToStateStack: X mStateStackTop="  
  784.                       + mStateStackTopIndex + ",startingIndex=" + startingIndex  
  785.                       + ",Top=" + mStateStack[mStateStackTopIndex].state.getName());  
  786.             }  
  787.             return startingIndex;  
  788.         }  
  789.   
  790.         /** 
  791.          * Setup the mTempStateStack with the states we are going to enter. 
  792.          * 
  793.          * This is found by searching up the destState's ancestors for a 
  794.          * state that is already active i.e. StateInfo.active == true. 
  795.          * The destStae and all of its inactive parents will be on the 
  796.          * TempStateStack as the list of states to enter. 
  797.          * 
  798.          * @return StateInfo of the common ancestor for the destState and 
  799.          * current state or null if there is no common parent. 
  800.          */  
  801.         private final StateInfo setupTempStateStackWithStatesToEnter(HierarchicalState destState) {  
  802.             /** 
  803.              * Search up the parent list of the destination state for an active 
  804.              * state. Use a do while() loop as the destState must always be entered 
  805.              * even if it is active. This can happen if we are exiting/entering 
  806.              * the current state. 
  807.              */  
  808.             mTempStateStackCount = 0;  
  809.             StateInfo curStateInfo = mStateInfo.get(destState);  
  810.             do {  
  811.                 mTempStateStack[mTempStateStackCount++] = curStateInfo;  
  812.                 curStateInfo = curStateInfo.parentStateInfo;  
  813.             } while ((curStateInfo != null) && !curStateInfo.active);  
  814.   
  815.             if (mDbg) {  
  816.                 Log.d(TAG, "setupTempStateStackWithStatesToEnter: X mTempStateStackCount="  
  817.                       + mTempStateStackCount + ",curStateInfo: " + curStateInfo);  
  818.             }  
  819.             return curStateInfo;  
  820.         }  
  821.   
  822.         /** 
  823.          * Initialize StateStack to mInitialState. 
  824.          */  
  825.         private final void setupInitialStateStack() {  
  826.             if (mDbg) {  
  827.                 Log.d(TAG, "setupInitialStateStack: E mInitialState="  
  828.                     + mInitialState.getName());  
  829.             }  
  830.   
  831.             StateInfo curStateInfo = mStateInfo.get(mInitialState);  
  832.             for (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {  
  833.                 mTempStateStack[mTempStateStackCount] = curStateInfo;  
  834.                 curStateInfo = curStateInfo.parentStateInfo;  
  835.             }  
  836.   
  837.             // Empty the StateStack  
  838.             mStateStackTopIndex = -1;  
  839.   
  840.             moveTempStateStackToStateStack();  
  841.         }  
  842.   
  843.         /** 
  844.          * @return current message 
  845.          */  
  846.         private final Message getCurrentMessage() {  
  847.             return mMsg;  
  848.         }  
  849.   
  850.         /** 
  851.          * @return current state 
  852.          */  
  853.         private final HierarchicalState getCurrentState() {  
  854.             return mStateStack[mStateStackTopIndex].state;  
  855.         }  
  856.   
  857.         /** 
  858.          * Add a new state to the state machine. Bottom up addition 
  859.          * of states is allowed but the same state may only exist 
  860.          * in one hierarchy. 
  861.          * 
  862.          * @param state the state to add 
  863.          * @param parent the parent of state 
  864.          * @return stateInfo for this state 
  865.          */  
  866.         private final StateInfo addState(HierarchicalState state, HierarchicalState parent) {  
  867.             if (mDbg) {  
  868.                 Log.d(TAG, "addStateInternal: E state=" + state.getName()  
  869.                         + ",parent=" + ((parent == null) ? "" : parent.getName()));  
  870.             }  
  871.             StateInfo parentStateInfo = null;  
  872.             if (parent != null) {  
  873.                 parentStateInfo = mStateInfo.get(parent);  
  874.                 if (parentStateInfo == null) {  
  875.                     // Recursively add our parent as it's not been added yet.  
  876.                     parentStateInfo = addState(parent, null);  
  877.                 }  
  878.             }  
  879.             StateInfo stateInfo = mStateInfo.get(state);  
  880.             if (stateInfo == null) {  
  881.                 stateInfo = new StateInfo();  
  882.                 mStateInfo.put(state, stateInfo);  
  883.             }  
  884.   
  885.             // Validate that we aren't adding the same state in two different hierarchies.  
  886.             if ((stateInfo.parentStateInfo != null) &&  
  887.                     (stateInfo.parentStateInfo != parentStateInfo)) {  
  888.                     throw new RuntimeException("state already added");  
  889.             }  
  890.             stateInfo.state = state;  
  891.             stateInfo.parentStateInfo = parentStateInfo;  
  892.             stateInfo.active = false;  
  893.             if (mDbg) Log.d(TAG, "addStateInternal: X stateInfo: " + stateInfo);  
  894.             return stateInfo;  
  895.         }  
  896.   
  897.         /** 
  898.          * Constructor 
  899.          * 
  900.          * @param looper for dispatching messages 
  901.          * @param hsm the hierarchical state machine 
  902.          */  
  903.         private HsmHandler(Looper looper, HierarchicalStateMachine hsm) {  
  904.             super(looper);  
  905.             mHsm = hsm;  
  906.   
  907.             addState(mHaltingState, null);  
  908.             addState(mQuittingState, null);  
  909.         }  
  910.   
  911.         /** @see HierarchicalStateMachine#setInitialState(HierarchicalState) */  
  912.         private final void setInitialState(HierarchicalState initialState) {  
  913.             if (mDbg) Log.d(TAG, "setInitialState: initialState" + initialState.getName());  
  914.             mInitialState = initialState;  
  915.         }  
  916.   
  917.         /** @see HierarchicalStateMachine#transitionTo(HierarchicalState) */  
  918.         private final void transitionTo(HierarchicalState destState) {  
  919.             if (mDbg) Log.d(TAG, "StateMachine.transitionTo EX destState" + destState.getName());  
  920.             mDestState = destState;  
  921.         }  
  922.   
  923.         /** @see HierarchicalStateMachine#deferMessage(Message) */  
  924.         private final void deferMessage(Message msg) {  
  925.             if (mDbg) Log.d(TAG, "deferMessage: msg=" + msg.what);  
  926.   
  927.             /* Copy the "msg" to "newMsg" as "msg" will be recycled */  
  928.             Message newMsg = obtainMessage();  
  929.             newMsg.copyFrom(msg);  
  930.   
  931.             mDeferredMessages.add(newMsg);  
  932.         }  
  933.   
  934.         /** @see HierarchicalStateMachine#deferMessage(Message) */  
  935.         private final void quit() {  
  936.             if (mDbg) Log.d(TAG, "quit:");  
  937.             sendMessage(obtainMessage(HSM_QUIT_CMD, mQuitObj));  
  938.         }  
  939.   
  940.         /** @see HierarchicalStateMachine#isQuit(Message) */  
  941.         private final boolean isQuit(Message msg) {  
  942.             return (msg.what == HSM_QUIT_CMD) && (msg.obj == mQuitObj);  
  943.         }  
  944.   
  945.         /** @see HierarchicalStateMachine#isDbg() */  
  946.         private final boolean isDbg() {  
  947.             return mDbg;  
  948.         }  
  949.   
  950.         /** @see HierarchicalStateMachine#setDbg(boolean) */  
  951.         private final void setDbg(boolean dbg) {  
  952.             mDbg = dbg;  
  953.         }  
  954.   
  955.         /** @see HierarchicalStateMachine#setProcessedMessagesSize(int) */  
  956.         private final void setProcessedMessagesSize(int maxSize) {  
  957.             mProcessedMessages.setSize(maxSize);  
  958.         }  
  959.   
  960.         /** @see HierarchicalStateMachine#getProcessedMessagesSize() */  
  961.         private final int getProcessedMessagesSize() {  
  962.             return mProcessedMessages.size();  
  963.         }  
  964.   
  965.         /** @see HierarchicalStateMachine#getProcessedMessagesCount() */  
  966.         private final int getProcessedMessagesCount() {  
  967.             return mProcessedMessages.count();  
  968.         }  
  969.   
  970.         /** @see HierarchicalStateMachine#getProcessedMessage(int) */  
  971.         private final ProcessedMessages.Info getProcessedMessage(int index) {  
  972.             return mProcessedMessages.get(index);  
  973.         }  
  974.   
  975.     }  
  976.   
  977.     private HsmHandler mHsmHandler;  
  978.     private HandlerThread mHsmThread;  
  979.   
  980.     /** 
  981.      * Initialize. 
  982.      * 
  983.      * @param looper for this state machine 
  984.      * @param name of the state machine 
  985.      */  
  986.     private void initStateMachine(String name, Looper looper) {  
  987.         mName = name;  
  988.         mHsmHandler = new HsmHandler(looper, this);  
  989.     }  
  990.   
  991.     /** 
  992.      * Constructor creates an HSM with its own thread. 
  993.      * 
  994.      * @param name of the state machine 
  995.      */  
  996.     protected HierarchicalStateMachine(String name) {  
  997.         mHsmThread = new HandlerThread(name);  
  998.         mHsmThread.start();  
  999.         Looper looper = mHsmThread.getLooper();  
  1000.   
  1001.         initStateMachine(name, looper);  
  1002.     }  
  1003.   
  1004.     /** 
  1005.      * Constructor creates an HSMStateMachine using the looper. 
  1006.      * 
  1007.      * @param name of the state machine 
  1008.      */  
  1009.     protected HierarchicalStateMachine(String name, Looper looper) {  
  1010.         initStateMachine(name, looper);  
  1011.     }  
  1012.   
  1013.     /** 
  1014.      * Add a new state to the state machine 
  1015.      * @param state the state to add 
  1016.      * @param parent the parent of state 
  1017.      */  
  1018.     protected final void addState(HierarchicalState state, HierarchicalState parent) {  
  1019.         mHsmHandler.addState(state, parent);  
  1020.     }  
  1021.   
  1022.     /** 
  1023.      * @return current message 
  1024.      */  
  1025.     protected final Message getCurrentMessage() {  
  1026.         return mHsmHandler.getCurrentMessage();  
  1027.     }  
  1028.   
  1029.     /** 
  1030.      * @return current state 
  1031.      */  
  1032.     protected final HierarchicalState getCurrentState() {  
  1033.         return mHsmHandler.getCurrentState();  
  1034.     }  
  1035.   
  1036.     /** 
  1037.      * Add a new state to the state machine, parent will be null 
  1038.      * @param state to add 
  1039.      */  
  1040.     protected final void addState(HierarchicalState state) {  
  1041.         mHsmHandler.addState(state, null);  
  1042.     }  
  1043.   
  1044.     /** 
  1045.      * Set the initial state. This must be invoked before 
  1046.      * and messages are sent to the state machine. 
  1047.      * 
  1048.      * @param initialState is the state which will receive the first message. 
  1049.      */  
  1050.     protected final void setInitialState(HierarchicalState initialState) {  
  1051.         mHsmHandler.setInitialState(initialState);  
  1052.     }  
  1053.   
  1054.     /** 
  1055.      * transition to destination state. Upon returning 
  1056.      * from processMessage the current state's exit will 
  1057.      * be executed and upon the next message arriving 
  1058.      * destState.enter will be invoked. 
  1059.      * 
  1060.      * @param destState will be the state that receives the next message. 
  1061.      */  
  1062.     protected final void transitionTo(HierarchicalState destState) {  
  1063.         mHsmHandler.transitionTo(destState);  
  1064.     }  
  1065.   
  1066.     /** 
  1067.      * transition to halt state. Upon returning 
  1068.      * from processMessage we will exit all current 
  1069.      * states, execute the halting() method and then 
  1070.      * all subsequent messages haltedProcessMesage 
  1071.      * will be called. 
  1072.      */  
  1073.     protected final void transitionToHaltingState() {  
  1074.         mHsmHandler.transitionTo(mHsmHandler.mHaltingState);  
  1075.     }  
  1076.   
  1077.     /** 
  1078.      * Defer this message until next state transition. 
  1079.      * Upon transitioning all deferred messages will be 
  1080.      * placed on the queue and reprocessed in the original 
  1081.      * order. (i.e. The next state the oldest messages will 
  1082.      * be processed first) 
  1083.      * 
  1084.      * @param msg is deferred until the next transition. 
  1085.      */  
  1086.     protected final void deferMessage(Message msg) {  
  1087.         mHsmHandler.deferMessage(msg);  
  1088.     }  
  1089.   
  1090.   
  1091.     /** 
  1092.      * Called when message wasn't handled 
  1093.      * 
  1094.      * @param msg that couldn't be handled. 
  1095.      */  
  1096.     protected void unhandledMessage(Message msg) {  
  1097.         if (false) {  
  1098.             Log.e(TAG, mName + " - unhandledMessage: msg.what=" + msg.what);  
  1099.         }  
  1100.     }  
  1101.   
  1102.     /** 
  1103.      * Called for any message that is received after 
  1104.      * transitionToHalting is called. 
  1105.      */  
  1106.     protected void haltedProcessMessage(Message msg) {  
  1107.     }  
  1108.   
  1109.     /** 
  1110.      * Called after the message that called transitionToHalting 
  1111.      * is called and should be overridden by StateMachine's that 
  1112.      * call transitionToHalting. 
  1113.      */  
  1114.     protected void halting() {  
  1115.     }  
  1116.   
  1117.     /** 
  1118.      * Called after the quitting message was NOT handled and 
  1119.      * just before the quit actually occurs. 
  1120.      */  
  1121.     protected void quitting() {  
  1122.     }  
  1123.   
  1124.     /** 
  1125.      * @return the name 
  1126.      */  
  1127.     public final String getName() {  
  1128.         return mName;  
  1129.     }  
  1130.   
  1131.     /** 
  1132.      * Set size of messages to maintain and clears all current messages. 
  1133.      * 
  1134.      * @param maxSize number of messages to maintain at anyone time. 
  1135.      */  
  1136.     public final void setProcessedMessagesSize(int maxSize) {  
  1137.         mHsmHandler.setProcessedMessagesSize(maxSize);  
  1138.     }  
  1139.   
  1140.     /** 
  1141.      * @return number of messages processed 
  1142.      */  
  1143.     public final int getProcessedMessagesSize() {  
  1144.         return mHsmHandler.getProcessedMessagesSize();  
  1145.     }  
  1146.   
  1147.     /** 
  1148.      * @return the total number of messages processed 
  1149.      */  
  1150.     public final int getProcessedMessagesCount() {  
  1151.         return mHsmHandler.getProcessedMessagesCount();  
  1152.     }  
  1153.   
  1154.     /** 
  1155.      * @return a processed message 
  1156.      */  
  1157.     public final ProcessedMessages.Info getProcessedMessage(int index) {  
  1158.         return mHsmHandler.getProcessedMessage(index);  
  1159.     }  
  1160.   
  1161.     /** 
  1162.      * @return Handler 
  1163.      */  
  1164.     public final Handler getHandler() {  
  1165.         return mHsmHandler;  
  1166.     }  
  1167.   
  1168.     /** 
  1169.      * Get a message and set Message.target = this. 
  1170.      * 
  1171.      * @return message 
  1172.      */  
  1173.     public final Message obtainMessage()  
  1174.     {  
  1175.         return Message.obtain(mHsmHandler);  
  1176.     }  
  1177.   
  1178.     /** 
  1179.      * Get a message and set Message.target = this and what 
  1180.      * 
  1181.      * @param what is the assigned to Message.what. 
  1182.      * @return message 
  1183.      */  
  1184.     public final Message obtainMessage(int what) {  
  1185.         return Message.obtain(mHsmHandler, what);  
  1186.     }  
  1187.   
  1188.     /** 
  1189.      * Get a message and set Message.target = this, 
  1190.      * what and obj. 
  1191.      * 
  1192.      * @param what is the assigned to Message.what. 
  1193.      * @param obj is assigned to Message.obj. 
  1194.      * @return message 
  1195.      */  
  1196.     public final Message obtainMessage(int what, Object obj)  
  1197.     {  
  1198.         return Message.obtain(mHsmHandler, what, obj);  
  1199.     }  
  1200.   
  1201.     /** 
  1202.      * Enqueue a message to this state machine. 
  1203.      */  
  1204.     public final void sendMessage(int what) {  
  1205.         mHsmHandler.sendMessage(obtainMessage(what));  
  1206.     }  
  1207.   
  1208.     /** 
  1209.      * Enqueue a message to this state machine. 
  1210.      */  
  1211.     public final void sendMessage(int what, Object obj) {  
  1212.         mHsmHandler.sendMessage(obtainMessage(what,obj));  
  1213.     }  
  1214.   
  1215.     /** 
  1216.      * Enqueue a message to this state machine. 
  1217.      */  
  1218.     public final void sendMessage(Message msg) {  
  1219.         mHsmHandler.sendMessage(msg);  
  1220.     }  
  1221.   
  1222.     /** 
  1223.      * Enqueue a message to this state machine after a delay. 
  1224.      */  
  1225.     public final void sendMessageDelayed(int what, long delayMillis) {  
  1226.         mHsmHandler.sendMessageDelayed(obtainMessage(what), delayMillis);  
  1227.     }  
  1228.   
  1229.     /** 
  1230.      * Enqueue a message to this state machine after a delay. 
  1231.      */  
  1232.     public final void sendMessageDelayed(int what, Object obj, long delayMillis) {  
  1233.         mHsmHandler.sendMessageDelayed(obtainMessage(what, obj), delayMillis);  
  1234.     }  
  1235.   
  1236.     /** 
  1237.      * Enqueue a message to this state machine after a delay. 
  1238.      */  
  1239.     public final void sendMessageDelayed(Message msg, long delayMillis) {  
  1240.         mHsmHandler.sendMessageDelayed(msg, delayMillis);  
  1241.     }  
  1242.   
  1243.     /** 
  1244.      * Enqueue a message to the front of the queue for this state machine. 
  1245.      * Protected, may only be called by instances of HierarchicalStateMachine. 
  1246.      */  
  1247.     protected final void sendMessageAtFrontOfQueue(int what, Object obj) {  
  1248.         mHsmHandler.sendMessageAtFrontOfQueue(obtainMessage(what, obj));  
  1249.     }  
  1250.   
  1251.     /** 
  1252.      * Enqueue a message to the front of the queue for this state machine. 
  1253.      * Protected, may only be called by instances of HierarchicalStateMachine. 
  1254.      */  
  1255.     protected final void sendMessageAtFrontOfQueue(int what) {  
  1256.         mHsmHandler.sendMessageAtFrontOfQueue(obtainMessage(what));  
  1257.     }  
  1258.   
  1259.     /** 
  1260.      * Enqueue a message to the front of the queue for this state machine. 
  1261.      * Protected, may only be called by instances of HierarchicalStateMachine. 
  1262.      */  
  1263.     protected final void sendMessageAtFrontOfQueue(Message msg) {  
  1264.         mHsmHandler.sendMessageAtFrontOfQueue(msg);  
  1265.     }  
  1266.   
  1267.     /** 
  1268.      * Conditionally quit the looper and stop execution. 
  1269.      * 
  1270.      * This sends the HSM_QUIT_MSG to the state machine and 
  1271.      * if not handled by any state's processMessage then the 
  1272.      * state machine will be stopped and no further messages 
  1273.      * will be processed. 
  1274.      */  
  1275.     public final void quit() {  
  1276.         mHsmHandler.quit();  
  1277.     }  
  1278.   
  1279.     /** 
  1280.      * @return ture if msg is quit 
  1281.      */  
  1282.     protected final boolean isQuit(Message msg) {  
  1283.         return mHsmHandler.isQuit(msg);  
  1284.     }  
  1285.   
  1286.     /** 
  1287.      * @return if debugging is enabled 
  1288.      */  
  1289.     public boolean isDbg() {  
  1290.         return mHsmHandler.isDbg();  
  1291.     }  
  1292.   
  1293.     /** 
  1294.      * Set debug enable/disabled. 
  1295.      * 
  1296.      * @param dbg is true to enable debugging. 
  1297.      */  
  1298.     public void setDbg(boolean dbg) {  
  1299.         mHsmHandler.setDbg(dbg);  
  1300.     }  
  1301.   
  1302.     /** 
  1303.      * Start the state machine. 
  1304.      */  
  1305.     public void start() {  
  1306.         /** Send the complete construction message */  
  1307.         mHsmHandler.completeConstruction();  
  1308.     }  


原文地址:http://blog.csdn.net/jdsjlzx/article/details/6897447

阅读(2683) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~