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