StateMachine.java revision bbf30dfd767f823f5f40d14b498e2a593454c5c9
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;
23583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Savilleimport android.text.TextUtils;
24fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport android.util.Log;
25fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
26583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Savilleimport java.io.FileDescriptor;
27583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Savilleimport java.io.PrintWriter;
28fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport java.util.ArrayList;
29583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Savilleimport java.util.Calendar;
30fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport java.util.HashMap;
31d3059487abd526b91b912f70939c1c6994eecf52Wink Savilleimport java.util.Vector;
32fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
33fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville/**
34fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * {@hide}
35fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
3664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>The state machine defined here is a hierarchical state machine which processes messages
3733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * and can have states arranged hierarchically.</p>
3833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville *
3964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>A state is a <code>State</code> object and must implement
4033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <code>processMessage</code> and optionally <code>enter/exit/getName</code>.
41fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * The enter/exit methods are equivalent to the construction and destruction
42fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * in Object Oriented programming and are used to perform initialization and
43fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * cleanup of the state respectively. The <code>getName</code> method returns the
44fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * name of the state the default implementation returns the class name it may be
45fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * desirable to have this return the name of the state instance name instead.
4633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * In particular if a particular state class has multiple instances.</p>
47fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
4833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>When a state machine is created <code>addState</code> is used to build the
49fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * hierarchy and <code>setInitialState</code> is used to identify which of these
50fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * is the initial state. After construction the programmer calls <code>start</code>
51cea056f5894543819898a0e62f98dc7870b27758Wink Saville * which initializes and starts the state machine. The first action the StateMachine
52cea056f5894543819898a0e62f98dc7870b27758Wink Saville * is to the invoke <code>enter</code> for all of the initial state's hierarchy,
53cea056f5894543819898a0e62f98dc7870b27758Wink Saville * starting at its eldest parent. The calls to enter will be done in the context
54cea056f5894543819898a0e62f98dc7870b27758Wink Saville * of the StateMachines Handler not in the context of the call to start and they
55cea056f5894543819898a0e62f98dc7870b27758Wink Saville * will be invoked before any messages are processed. For example, given the simple
56cea056f5894543819898a0e62f98dc7870b27758Wink Saville * state machine below mP1.enter will be invoked and then mS1.enter. Finally,
57cea056f5894543819898a0e62f98dc7870b27758Wink Saville * messages sent to the state machine will be processed by the current state,
58cea056f5894543819898a0e62f98dc7870b27758Wink Saville * in our simple state machine below that would initially be mS1.processMessage.</p>
59fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville<code>
60fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        mP1
61fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville       /   \
62fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville      mS2   mS1 ----> initial state
63fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville</code>
6433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>After the state machine is created and started, messages are sent to a state
65a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * machine using <code>sendMessage</code> and the messages are created using
66fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * <code>obtainMessage</code>. When the state machine receives a message the
67fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * current state's <code>processMessage</code> is invoked. In the above example
68fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * mS1.processMessage will be invoked first. The state may use <code>transitionTo</code>
6933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * to change the current state to a new state</p>
70fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
7133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Each state in the state machine may have a zero or one parent states and if
72fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * a child state is unable to handle a message it may have the message processed
73a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * by its parent by returning false or NOT_HANDLED. If a message is never processed
74a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * <code>unhandledMessage</code> will be invoked to give one last chance for the state machine
7533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * to process the message.</p>
76fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
7733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>When all processing is completed a state machine may choose to call
78fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * <code>transitionToHaltingState</code>. When the current <code>processingMessage</code>
79fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * returns the state machine will transfer to an internal <code>HaltingState</code>
80fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * and invoke <code>halting</code>. Any message subsequently received by the state
8133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * machine will cause <code>haltedProcessMessage</code> to be invoked.</p>
82fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
83bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville * <p>If it is desirable to completely stop the state machine call <code>quit</code> or
84bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville * <code>abort</code>. These will call <code>exit</code> of the current state and its parents, call
85bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville * <code>onQuiting</code> and then exit Thread/Loopers.</p>
861b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville *
8764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>In addition to <code>processMessage</code> each <code>State</code> has
8833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * an <code>enter</code> method and <code>exit</exit> method which may be overridden.</p>
89fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
9033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Since the states are arranged in a hierarchy transitioning to a new state
91fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * causes current states to be exited and new states to be entered. To determine
92fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * the list of states to be entered/exited the common parent closest to
93fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * the current state is found. We then exit from the current state and its
94fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * parent's up to but not including the common parent state and then enter all
95fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * of the new states below the common parent down to the destination state.
96fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * If there is no common parent all states are exited and then the new states
9733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * are entered.</p>
98fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
9933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Two other methods that states can use are <code>deferMessage</code> and
100fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * <code>sendMessageAtFrontOfQueue</code>. The <code>sendMessageAtFrontOfQueue</code> sends
101fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * a message but places it on the front of the queue rather than the back. The
102fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * <code>deferMessage</code> causes the message to be saved on a list until a
103fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * transition is made to a new state. At which time all of the deferred messages
104fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * will be put on the front of the state machine queue with the oldest message
105fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * at the front. These will then be processed by the new current state before
106fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * any other messages that are on the queue or might be added later. Both of
10733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * these are protected and may only be invoked from within a state machine.</p>
108fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
10933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>To illustrate some of these properties we'll use state machine with an 8
11033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * state hierarchy:</p>
111fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville<code>
112fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville          mP0
113fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         /   \
114fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        mP1   mS0
115fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville       /   \
116fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville      mS2   mS1
117fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     /  \    \
118fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    mS3  mS4  mS5  ---> initial state
119fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville</code>
12033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>After starting mS5 the list of active states is mP0, mP1, mS1 and mS5.
121fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * So the order of calling processMessage when a message is received is mS5,
122a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * mS1, mP1, mP0 assuming each processMessage indicates it can't handle this
12333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * message by returning false or NOT_HANDLED.</p>
124fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
12533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Now assume mS5.processMessage receives a message it can handle, and during
126a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * the handling determines the machine should change states. It could call
127a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * transitionTo(mS4) and return true or HANDLED. Immediately after returning from
128fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * processMessage the state machine runtime will find the common parent,
129fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * which is mP1. It will then call mS5.exit, mS1.exit, mS2.enter and then
130fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * mS4.enter. The new list of active states is mP0, mP1, mS2 and mS4. So
13133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * when the next message is received mS4.processMessage will be invoked.</p>
132fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
13364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>Now for some concrete examples, here is the canonical HelloWorld as a state machine.
13433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * It responds with "Hello World" being printed to the log for every message.</p>
135fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville<code>
13664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Savilleclass HelloWorld extends StateMachine {
13764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    HelloWorld(String name) {
138fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        super(name);
139fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        addState(mState1);
140fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        setInitialState(mState1);
141fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
142fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
143fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static HelloWorld makeHelloWorld() {
144fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        HelloWorld hw = new HelloWorld("hw");
145fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        hw.start();
146fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        return hw;
147fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
148fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
14964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class State1 extends State {
1500b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
151fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "Hello World");
152a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            return HANDLED;
153fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
154fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
155fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    State1 mState1 = new State1();
156fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
157fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
158fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savillevoid testHelloWorld() {
159fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    HelloWorld hw = makeHelloWorld();
160fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    hw.sendMessage(hw.obtainMessage());
161fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
162fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville</code>
16333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>A more interesting state machine is one with four states
16433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * with two independent parent states.</p>
165fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville<code>
166fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        mP1      mP2
167fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville       /   \
168fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville      mS2   mS1
169fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville</code>
17033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Here is a description of this state machine using pseudo code.</p>
17133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville <code>
17233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillestate mP1 {
17333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     enter { log("mP1.enter"); }
17433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     exit { log("mP1.exit");  }
17533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     on msg {
17633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_2 {
17733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             send(CMD_3);
17833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             defer(msg);
17933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             transitonTo(mS2);
18033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
18133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
18233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         return NOT_HANDLED;
18333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
18433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
18533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville
18633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleINITIAL
18733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillestate mS1 parent mP1 {
18833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     enter { log("mS1.enter"); }
18933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     exit  { log("mS1.exit");  }
19033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     on msg {
19133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_1 {
19233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             transitionTo(mS1);
19333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
19433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
19533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         return NOT_HANDLED;
19633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
19733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
19833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville
19933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillestate mS2 parent mP1 {
20033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     enter { log("mS2.enter"); }
20133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     exit  { log("mS2.exit");  }
20233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     on msg {
20333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_2 {
20433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             send(CMD_4);
20533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
20633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
20733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_3 {
20833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             defer(msg);
20933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             transitionTo(mP2);
21033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
21133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
21233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         return NOT_HANDLED;
21333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
21433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
21533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville
21633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillestate mP2 {
21733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     enter {
21833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         log("mP2.enter");
21933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         send(CMD_5);
22033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
22133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     exit { log("mP2.exit"); }
22233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     on msg {
22333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_3, CMD_4 { return HANDLED; }
22433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_5 {
22533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             transitionTo(HaltingState);
22633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
22733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
22833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         return NOT_HANDLED;
22933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
23033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
23133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville</code>
23264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>The implementation is below and also in StateMachineTest:</p>
233fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville<code>
23464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Savilleclass Hsm1 extends StateMachine {
235fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private static final String TAG = "hsm1";
236fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
237fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_1 = 1;
238fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_2 = 2;
239fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_3 = 3;
240fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_4 = 4;
241fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_5 = 5;
242fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
243fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static Hsm1 makeHsm1() {
244fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Log.d(TAG, "makeHsm1 E");
245fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Hsm1 sm = new Hsm1("hsm1");
246fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        sm.start();
247fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Log.d(TAG, "makeHsm1 X");
248fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        return sm;
249fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
250fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
251fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    Hsm1(String name) {
252fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        super(name);
253fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Log.d(TAG, "ctor E");
254fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
255fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        // Add states, use indentation to show hierarchy
256fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        addState(mP1);
257fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS1, mP1);
258fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS2, mP1);
259fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        addState(mP2);
260fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
261fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        // Set the initial state
262fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        setInitialState(mS1);
263fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Log.d(TAG, "ctor X");
264fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
265fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
26664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class P1 extends State {
2670b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void enter() {
268fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "mP1.enter");
269fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
2700b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
271fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            boolean retVal;
272fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "mP1.processMessage what=" + message.what);
273fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            switch(message.what) {
274fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case CMD_2:
275fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // CMD_2 will arrive in mS2 before CMD_3
276fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sendMessage(obtainMessage(CMD_3));
277fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                deferMessage(message);
278fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mS2);
279a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = HANDLED;
280fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
281fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            default:
282fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // Any message we don't understand in this state invokes unhandledMessage
283a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = NOT_HANDLED;
284fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
285fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
286fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return retVal;
287fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
2880b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void exit() {
289fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "mP1.exit");
290fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
291fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
292fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
29364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class S1 extends State {
2940b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void enter() {
295fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "mS1.enter");
296fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
2970b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
298fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "S1.processMessage what=" + message.what);
299fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (message.what == CMD_1) {
300fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // Transition to ourself to show that enter/exit is called
301fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mS1);
302a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                return HANDLED;
303fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } else {
304fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // Let parent process all other messages
305a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                return NOT_HANDLED;
306fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
307fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3080b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void exit() {
309fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "mS1.exit");
310fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
311fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
312fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
31364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class S2 extends State {
3140b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void enter() {
315fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "mS2.enter");
316fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3170b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
318fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            boolean retVal;
319fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "mS2.processMessage what=" + message.what);
320fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            switch(message.what) {
321fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_2):
322fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sendMessage(obtainMessage(CMD_4));
323a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = HANDLED;
324fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
325fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_3):
326fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                deferMessage(message);
327fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mP2);
328a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = HANDLED;
329fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
330fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            default:
331a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = NOT_HANDLED;
332fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
333fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
334fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return retVal;
335fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3360b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void exit() {
337fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "mS2.exit");
338fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
339fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
340fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
34164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class P2 extends State {
3420b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void enter() {
343fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "mP2.enter");
344fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            sendMessage(obtainMessage(CMD_5));
345fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3460b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
347fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "P2.processMessage what=" + message.what);
348fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            switch(message.what) {
349fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_3):
350fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
351fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_4):
352fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
353fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_5):
354fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionToHaltingState();
355fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
356fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
357a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            return HANDLED;
358fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3590b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void exit() {
360fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "mP2.exit");
361fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
362fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
363fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
3640b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato    &#64;Override
365bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    void onHalting() {
366fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Log.d(TAG, "halting");
367fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (this) {
368fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            this.notifyAll();
369fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
370fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
371fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
372fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    P1 mP1 = new P1();
373fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    S1 mS1 = new S1();
374fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    S2 mS2 = new S2();
375fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    P2 mP2 = new P2();
376fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
377fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville</code>
37833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>If this is executed by sending two messages CMD_1 and CMD_2
37933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * (Note the synchronize is only needed because we use hsm.wait())</p>
38033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville<code>
38133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleHsm1 hsm = makeHsm1();
38233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillesynchronize(hsm) {
38333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     hsm.sendMessage(obtainMessage(hsm.CMD_1));
38433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     hsm.sendMessage(obtainMessage(hsm.CMD_2));
38533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     try {
38633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville          // wait for the messages to be handled
38733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville          hsm.wait();
38833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     } catch (InterruptedException e) {
38933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville          Log.e(TAG, "exception while waiting " + e.getMessage());
39033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
39133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
39233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville</code>
39333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>The output is:</p>
39433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville<code>
39533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): makeHsm1 E
39633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): ctor E
39733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): ctor X
39833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP1.enter
39933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.enter
40033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): makeHsm1 X
40133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.processMessage what=1
40233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.exit
40333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.enter
40433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.processMessage what=2
40533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP1.processMessage what=2
40633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.exit
40733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS2.enter
40833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS2.processMessage what=2
40933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS2.processMessage what=3
41033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS2.exit
41133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP1.exit
41233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.enter
41333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.processMessage what=3
41433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.processMessage what=4
41533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.processMessage what=5
41633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.exit
41733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): halting
41833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville</code>
419fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville */
42064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Savillepublic class StateMachine {
421fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
42264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private static final String TAG = "StateMachine";
423fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private String mName;
424fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
425a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /** Message.what value when quitting */
426bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    private static final int SM_QUIT_CMD = -1;
4271b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
428a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /** Message.what value when initializing */
429bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    private static final int SM_INIT_CMD = -2;
430a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
431a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /**
432a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * Convenience constant that maybe returned by processMessage
433a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * to indicate the the message was processed and is not to be
434a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * processed by parent states
435a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     */
436a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    public static final boolean HANDLED = true;
437a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
438a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /**
439a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * Convenience constant that maybe returned by processMessage
440a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * to indicate the the message was NOT processed and is to be
441a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * processed by parent states
442a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     */
443a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    public static final boolean NOT_HANDLED = false;
444a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
445d3059487abd526b91b912f70939c1c6994eecf52Wink Saville    /**
446bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * StateMachine logging record.
447d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * {@hide}
448d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     */
449bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public static class LogRec {
450583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        private long mTime;
451583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        private int mWhat;
452583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        private String mInfo;
453583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        private State mState;
454583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        private State mOrgState;
455d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
456d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
457d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * Constructor
458bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         *
459bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @param msg
460d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param state that handled the message
461d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param orgState is the first state the received the message but
462d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * did not processes the message.
463d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
464bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        LogRec(Message msg, String info, State state, State orgState) {
465583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            update(msg, info, state, orgState);
466d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
467d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
468d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
469d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * Update the information in the record.
470d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param state that handled the message
471d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param orgState is the first state the received the message but
472d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * did not processes the message.
473d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
474583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        public void update(Message msg, String info, State state, State orgState) {
475583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            mTime = System.currentTimeMillis();
476bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            mWhat = (msg != null) ? msg.what : 0;
477583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            mInfo = info;
478583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            mState = state;
479583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            mOrgState = orgState;
480583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        }
481583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
482583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        /**
483583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @return time stamp
484583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         */
485583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        public long getTime() {
486583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return mTime;
487583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        }
488583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
489583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        /**
490583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @return msg.what
491583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         */
492583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        public long getWhat() {
493583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return mWhat;
494d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
495d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
496d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
497d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @return the command that was executing
498d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
499583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        public String getInfo() {
500583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return mInfo;
501d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
502d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
503d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
504d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @return the state that handled this message
505d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
50664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        public State getState() {
507583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return mState;
508d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
509d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
510d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
511d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @return the original state that received the message.
512d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
51364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        public State getOriginalState() {
514583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return mOrgState;
515d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
516d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
517d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
518d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @return as string
519d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
520bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        public String toString(StateMachine sm) {
521d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            StringBuilder sb = new StringBuilder();
522583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append("time=");
523583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            Calendar c = Calendar.getInstance();
524583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            c.setTimeInMillis(mTime);
525583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
526d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            sb.append(" state=");
527583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append(mState == null ? "<null>" : mState.getName());
528d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            sb.append(" orgState=");
529583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append(mOrgState == null ? "<null>" : mOrgState.getName());
530583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append(" what=");
531bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            String what = sm.getWhatToString(mWhat);
532bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            if (TextUtils.isEmpty(what)) {
533bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append(mWhat);
534bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append("(0x");
535bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append(Integer.toHexString(mWhat));
536bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append(")");
537bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            } else {
538bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append(what);
539bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            }
540583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            if ( ! TextUtils.isEmpty(mInfo)) {
541583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville                sb.append(" ");
542583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville                sb.append(mInfo);
543d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
544583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return sb.toString();
545d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
546d3059487abd526b91b912f70939c1c6994eecf52Wink Saville    }
547d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
548d3059487abd526b91b912f70939c1c6994eecf52Wink Saville    /**
549bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * A list of log records including messages recently processed by the state machine.
550d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     *
551bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * The class maintains a list of log records including messages
552d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * recently processed. The list is finite and may be set in the
553d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * constructor or by calling setSize. The public interface also
554bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * includes size which returns the number of recent records,
555bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * count which is the number of records processed since the
556bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * the last setSize, get which returns a record and
557bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * add which adds a record.
558d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     */
559bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    private static class LogRecords {
560d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
561d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        private static final int DEFAULT_SIZE = 20;
562d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
563bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        private Vector<LogRec> mLogRecords = new Vector<LogRec>();
564d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        private int mMaxSize = DEFAULT_SIZE;
565d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        private int mOldestIndex = 0;
566d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        private int mCount = 0;
567d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
568d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
569583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * private constructor use add
570d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
571bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        private LogRecords() {
572d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
573d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
574d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
575bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * Set size of messages to maintain and clears all current records.
576d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         *
577bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @param maxSize number of records to maintain at anyone time.
578d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        */
579bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized void setSize(int maxSize) {
580d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            mMaxSize = maxSize;
581d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            mCount = 0;
582bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            mLogRecords.clear();
583d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
584d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
585d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
586bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @return the number of recent records.
587d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
588bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized int size() {
589bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            return mLogRecords.size();
590d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
591d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
592d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
593bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @return the total number of records processed since size was set.
594d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
595bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized int count() {
596d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            return mCount;
597d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
598d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
599d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
600bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * Clear the list of records.
6016f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh         */
602bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized void cleanup() {
603bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            mLogRecords.clear();
6046f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        }
6056f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh
6066f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        /**
607d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @return the information on a particular record. 0 is the oldest
608d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * record and size()-1 is the newest record. If the index is to
609d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * large null is returned.
610d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
611bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized LogRec get(int index) {
612d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            int nextIndex = mOldestIndex + index;
613d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            if (nextIndex >= mMaxSize) {
614d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                nextIndex -= mMaxSize;
615d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
616d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            if (nextIndex >= size()) {
617d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                return null;
618d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            } else {
619bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                return mLogRecords.get(nextIndex);
620d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
621d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
622d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
623d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
624d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * Add a processed message.
625d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         *
626583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @param msg
627583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @param messageInfo to be stored
628d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param state that handled the message
629d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param orgState is the first state the received the message but
630d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * did not processes the message.
631d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
632bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized void add(Message msg, String messageInfo, State state, State orgState) {
633d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            mCount += 1;
634bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            if (mLogRecords.size() < mMaxSize) {
635bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                mLogRecords.add(new LogRec(msg, messageInfo, state, orgState));
636d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            } else {
637bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                LogRec pmi = mLogRecords.get(mOldestIndex);
638d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                mOldestIndex += 1;
639d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                if (mOldestIndex >= mMaxSize) {
640d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                    mOldestIndex = 0;
641d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                }
642583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville                pmi.update(msg, messageInfo, state, orgState);
643d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
644d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
645d3059487abd526b91b912f70939c1c6994eecf52Wink Saville    }
646d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
6476f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh
64864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private static class SmHandler extends Handler {
649fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
650fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The debug flag */
651fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private boolean mDbg = false;
652fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
653cea056f5894543819898a0e62f98dc7870b27758Wink Saville        /** The SmHandler object, identifies that message is internal */
654cea056f5894543819898a0e62f98dc7870b27758Wink Saville        private static final Object mSmHandlerObj = new Object();
6551b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
656a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        /** The current message */
657a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        private Message mMsg;
658a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
659bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        /** A list of log records including messages this state machine has processed */
660bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        private LogRecords mLogRecords = new LogRecords();
661fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
662fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** true if construction of the state machine has not been completed */
663fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private boolean mIsConstructionCompleted;
664fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
665fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** Stack used to manage the current hierarchy of states */
666fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateInfo mStateStack[];
667fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
668fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** Top of mStateStack */
669fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mStateStackTopIndex = -1;
670fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
671fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** A temporary stack used to manage the state stack */
672fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateInfo mTempStateStack[];
673fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
674fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The top of the mTempStateStack */
675fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mTempStateStackCount;
676fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
677fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** State used when state machine is halted */
678fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private HaltingState mHaltingState = new HaltingState();
679fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
6801b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        /** State used when state machine is quitting */
6811b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private QuittingState mQuittingState = new QuittingState();
6821b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
68364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** Reference to the StateMachine */
68464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private StateMachine mSm;
685fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
686fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
687fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Information about a state.
688fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Used to maintain the hierarchy.
689fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
690fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private class StateInfo {
691fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /** The state */
69264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            State state;
693fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
694fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /** The parent of this state, null if there is no parent */
695fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo parentStateInfo;
696fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
697fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /** True when the state has been entered and on the stack */
698fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            boolean active;
699fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
700fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
701fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * Convert StateInfo to string
702fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
703fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override
704fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            public String toString() {
705fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return "state=" + state.getName() + ",active=" + active
706fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                        + ",parent=" + ((parentStateInfo == null) ?
707fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                                        "null" : parentStateInfo.state.getName());
708fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
709fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
710fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
711fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The map of all of the states in the state machine */
71264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private HashMap<State, StateInfo> mStateInfo =
71364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            new HashMap<State, StateInfo>();
714fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
715fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The initial state that will process the first message */
71664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private State mInitialState;
717fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
718fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The destination state when transitionTo has been invoked */
71964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private State mDestState;
720fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
721fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The list of deferred messages */
722fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ArrayList<Message> mDeferredMessages = new ArrayList<Message>();
723fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
724fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
725fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * State entered when transitionToHaltingState is called.
726fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
72764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private class HaltingState extends State {
728fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override
729fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            public boolean processMessage(Message msg) {
73064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville                mSm.haltedProcessMessage(msg);
731fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
732fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
733fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
734fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
735fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
7361b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville         * State entered when a valid quit message is handled.
7371b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville         */
73864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private class QuittingState extends State {
7391b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            @Override
7401b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            public boolean processMessage(Message msg) {
741a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                return NOT_HANDLED;
7421b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            }
7431b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
7441b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
7451b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        /**
746fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Handle messages sent to the state machine by calling
747fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * the current state's processMessage. It also handles
748fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * the enter/exit calls and placing any deferred messages
749fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * back onto the queue when transitioning to a new state.
750fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
751fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
752fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        public final void handleMessage(Message msg) {
753fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) Log.d(TAG, "handleMessage: E msg.what=" + msg.what);
754fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
755a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            /** Save the current message */
756a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            mMsg = msg;
757a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
758cea056f5894543819898a0e62f98dc7870b27758Wink Saville            if (mIsConstructionCompleted) {
759cea056f5894543819898a0e62f98dc7870b27758Wink Saville                /** Normal path */
760cea056f5894543819898a0e62f98dc7870b27758Wink Saville                processMsg(msg);
761cea056f5894543819898a0e62f98dc7870b27758Wink Saville            } else if (!mIsConstructionCompleted &&
762cea056f5894543819898a0e62f98dc7870b27758Wink Saville                    (mMsg.what == SM_INIT_CMD) && (mMsg.obj == mSmHandlerObj)) {
763cea056f5894543819898a0e62f98dc7870b27758Wink Saville                /** Initial one time path. */
764cea056f5894543819898a0e62f98dc7870b27758Wink Saville                mIsConstructionCompleted = true;
765cea056f5894543819898a0e62f98dc7870b27758Wink Saville                invokeEnterMethods(0);
766cea056f5894543819898a0e62f98dc7870b27758Wink Saville            } else {
767cea056f5894543819898a0e62f98dc7870b27758Wink Saville                throw new RuntimeException("StateMachine.handleMessage: " +
768cea056f5894543819898a0e62f98dc7870b27758Wink Saville                            "The start method not called, received msg: " + msg);
769fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
770e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            performTransitions();
771fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
772e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            if (mDbg) Log.d(TAG, "handleMessage: X");
773e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville        }
774e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville
775e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville        /**
776e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville         * Do any transitions
777e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville         */
778e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville        private void performTransitions() {
779fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
780fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * If transitionTo has been called, exit and then enter
781e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * the appropriate states. We loop on this to allow
782e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * enter and exit methods to use transitionTo.
783fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
78464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            State destState = null;
785e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            while (mDestState != null) {
786fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (mDbg) Log.d(TAG, "handleMessage: new destination call exit");
787fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
788fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                /**
789e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                 * Save mDestState locally and set to null
790e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                 * to know if enter/exit use transitionTo.
791e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                 */
792e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                destState = mDestState;
793e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                mDestState = null;
794e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville
795e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                /**
796fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                 * Determine the states to exit and enter and return the
797fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                 * common ancestor state of the enter/exit states. Then
798fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                 * invoke the exit methods then the enter methods.
799fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                 */
800e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
801fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                invokeExitMethods(commonStateInfo);
802fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                int stateStackEnteringIndex = moveTempStateStackToStateStack();
803fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                invokeEnterMethods(stateStackEnteringIndex);
804fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
805fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
806fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                /**
807fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                 * Since we have transitioned to a new state we need to have
808fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                 * any deferred messages moved to the front of the message queue
809fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                 * so they will be processed before any other messages in the
810fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                 * message queue.
811fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                 */
812fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                moveDeferredMessageAtFrontOfQueue();
813e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            }
814fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
815e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            /**
816e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * After processing all transitions check and
817e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * see if the last transition was to quit or halt.
818e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             */
819e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            if (destState != null) {
820e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                if (destState == mQuittingState) {
821bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    /**
822bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     * Call onQuitting to let subclasses cleanup.
823bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     */
824bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    mSm.onQuitting();
8256f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                    cleanupAfterQuitting();
826e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                } else if (destState == mHaltingState) {
827e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                    /**
828bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     * Call onHalting() if we've transitioned to the halting
829e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                     * state. All subsequent messages will be processed in
830e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                     * in the halting state which invokes haltedProcessMessage(msg);
831e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                     */
832bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    mSm.onHalting();
833fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
834fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
835fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
836fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
837fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
8386f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh         * Cleanup all the static variables and the looper after the SM has been quit.
8396f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh         */
8406f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        private final void cleanupAfterQuitting() {
8416f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            if (mSm.mSmThread != null) {
8426f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                // If we made the thread then quit looper which stops the thread.
8436f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                getLooper().quit();
8446f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                mSm.mSmThread = null;
8456f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            }
8466f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh
8476f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mSm.mSmHandler = null;
8486f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mSm = null;
8496f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mMsg = null;
850bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            mLogRecords.cleanup();
8516f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mStateStack = null;
8526f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mTempStateStack = null;
8536f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mStateInfo.clear();
8546f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mInitialState = null;
8556f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mDestState = null;
8566f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mDeferredMessages.clear();
8576f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        }
8586f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh
8596f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        /**
860fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Complete the construction of the state machine.
861fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
862fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void completeConstruction() {
863fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) Log.d(TAG, "completeConstruction: E");
864fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
865fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
866fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * Determine the maximum depth of the state hierarchy
867fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * so we can allocate the state stacks.
868fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
869fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int maxDepth = 0;
870fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (StateInfo si : mStateInfo.values()) {
871fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                int depth = 0;
872fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                for (StateInfo i = si; i != null; depth++) {
873fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    i = i.parentStateInfo;
874fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
875fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (maxDepth < depth) {
876fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    maxDepth = depth;
877fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
878fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
879fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) Log.d(TAG, "completeConstruction: maxDepth=" + maxDepth);
880fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
881fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mStateStack = new StateInfo[maxDepth];
882fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mTempStateStack = new StateInfo[maxDepth];
883fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setupInitialStateStack();
884fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
885cea056f5894543819898a0e62f98dc7870b27758Wink Saville            /** Sending SM_INIT_CMD message to invoke enter methods asynchronously */
886cea056f5894543819898a0e62f98dc7870b27758Wink Saville            sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));
887e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville
888fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) Log.d(TAG, "completeConstruction: X");
889fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
890fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
891fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
892fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Process the message. If the current state doesn't handle
893fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * it, call the states parent and so on. If it is never handled then
894fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * call the state machines unhandledMessage method.
895fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
896fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void processMsg(Message msg) {
897fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
898fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
899fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
900fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
901bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
902bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            if (isQuit(msg)) {
903bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                transitionTo(mQuittingState);
904bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            } else {
905bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                while (!curStateInfo.state.processMessage(msg)) {
906fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    /**
907bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     * Not processed
908fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                     */
909bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    curStateInfo = curStateInfo.parentStateInfo;
910bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    if (curStateInfo == null) {
911bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        /**
912bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                         * No parents left so it's not handled
913bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                         */
914bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        mSm.unhandledMessage(msg);
915bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        break;
916bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    }
917bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    if (mDbg) {
918bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
9191b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                    }
920fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
921fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
922bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                /**
923bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                 * Record that we processed the message
924bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                 */
925bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                if (mSm.recordLogRec(msg)) {
926bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    if (curStateInfo != null) {
927bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        State orgState = mStateStack[mStateStackTopIndex].state;
928bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        mLogRecords.add(msg, mSm.getLogRecString(msg), curStateInfo.state,
929bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                                orgState);
930bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    } else {
931bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        mLogRecords.add(msg, mSm.getLogRecString(msg), null, null);
932bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    }
933583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville                }
934fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
935fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
936fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
937fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
938fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Call the exit method for each state from the top of stack
939fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * up to the common ancestor state.
940fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
941fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void invokeExitMethods(StateInfo commonStateInfo) {
942fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            while ((mStateStackTopIndex >= 0) &&
943fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    (mStateStack[mStateStackTopIndex] != commonStateInfo)) {
94464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville                State curState = mStateStack[mStateStackTopIndex].state;
945fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (mDbg) Log.d(TAG, "invokeExitMethods: " + curState.getName());
946fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                curState.exit();
947fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[mStateStackTopIndex].active = false;
948fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStackTopIndex -= 1;
949fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
950fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
951fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
952fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
953fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Invoke the enter method starting at the entering index to top of state stack
954fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
955fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void invokeEnterMethods(int stateStackEnteringIndex) {
956fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
957fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (mDbg) Log.d(TAG, "invokeEnterMethods: " + mStateStack[i].state.getName());
958fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[i].state.enter();
959fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[i].active = true;
960fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
961fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
962fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
963fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
964fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Move the deferred message to the front of the message queue.
965fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
966fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void moveDeferredMessageAtFrontOfQueue() {
967fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
968fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * The oldest messages on the deferred list must be at
969fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * the front of the queue so start at the back, which
970fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * as the most resent message and end with the oldest
971fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * messages at the front of the queue.
972fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
973fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (int i = mDeferredMessages.size() - 1; i >= 0; i-- ) {
974fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Message curMsg = mDeferredMessages.get(i);
975fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (mDbg) Log.d(TAG, "moveDeferredMessageAtFrontOfQueue; what=" + curMsg.what);
976fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sendMessageAtFrontOfQueue(curMsg);
977fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
978fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mDeferredMessages.clear();
979fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
980fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
981fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
982fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Move the contents of the temporary stack to the state stack
983fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * reversing the order of the items on the temporary stack as
984fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * they are moved.
985fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
98664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville         * @return index into mStateStack where entering needs to start
987fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
988fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final int moveTempStateStackToStateStack() {
989fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int startingIndex = mStateStackTopIndex + 1;
990fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int i = mTempStateStackCount - 1;
991fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int j = startingIndex;
992fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            while (i >= 0) {
993fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (mDbg) Log.d(TAG, "moveTempStackToStateStack: i=" + i + ",j=" + j);
994fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[j] = mTempStateStack[i];
995fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                j += 1;
996fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                i -= 1;
997fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
998fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
999fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mStateStackTopIndex = j - 1;
1000fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
1001fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.d(TAG, "moveTempStackToStateStack: X mStateStackTop="
1002fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                      + mStateStackTopIndex + ",startingIndex=" + startingIndex
1003fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                      + ",Top=" + mStateStack[mStateStackTopIndex].state.getName());
1004fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1005fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return startingIndex;
1006fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1007fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1008fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1009fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Setup the mTempStateStack with the states we are going to enter.
1010fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1011fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * This is found by searching up the destState's ancestors for a
1012fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * state that is already active i.e. StateInfo.active == true.
1013fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * The destStae and all of its inactive parents will be on the
1014fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * TempStateStack as the list of states to enter.
1015fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1016fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @return StateInfo of the common ancestor for the destState and
1017fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * current state or null if there is no common parent.
1018fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
101964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final StateInfo setupTempStateStackWithStatesToEnter(State destState) {
1020fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
1021fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * Search up the parent list of the destination state for an active
1022fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * state. Use a do while() loop as the destState must always be entered
1023fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * even if it is active. This can happen if we are exiting/entering
1024fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * the current state.
1025fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
1026fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mTempStateStackCount = 0;
1027fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo curStateInfo = mStateInfo.get(destState);
1028fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            do {
1029fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mTempStateStack[mTempStateStackCount++] = curStateInfo;
1030fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                curStateInfo = curStateInfo.parentStateInfo;
1031fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } while ((curStateInfo != null) && !curStateInfo.active);
1032fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1033fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
1034fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.d(TAG, "setupTempStateStackWithStatesToEnter: X mTempStateStackCount="
1035fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                      + mTempStateStackCount + ",curStateInfo: " + curStateInfo);
1036fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1037fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return curStateInfo;
1038fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1039fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1040fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1041fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Initialize StateStack to mInitialState.
1042fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1043fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void setupInitialStateStack() {
1044fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
1045fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.d(TAG, "setupInitialStateStack: E mInitialState="
1046fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    + mInitialState.getName());
1047fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1048fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1049fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo curStateInfo = mStateInfo.get(mInitialState);
1050fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {
1051fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mTempStateStack[mTempStateStackCount] = curStateInfo;
1052fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                curStateInfo = curStateInfo.parentStateInfo;
1053fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1054fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1055fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Empty the StateStack
1056fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mStateStackTopIndex = -1;
1057fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1058fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            moveTempStateStackToStateStack();
1059fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1060fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1061fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1062a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville         * @return current message
1063a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville         */
1064a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        private final Message getCurrentMessage() {
1065a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            return mMsg;
1066a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        }
1067a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
1068a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        /**
1069fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @return current state
1070fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
107164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final IState getCurrentState() {
1072fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return mStateStack[mStateStackTopIndex].state;
1073fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1074fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1075fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1076fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Add a new state to the state machine. Bottom up addition
1077fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * of states is allowed but the same state may only exist
1078fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * in one hierarchy.
1079fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1080fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @param state the state to add
1081fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @param parent the parent of state
1082fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @return stateInfo for this state
1083fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
108464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final StateInfo addState(State state, State parent) {
1085fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
1086fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.d(TAG, "addStateInternal: E state=" + state.getName()
1087fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                        + ",parent=" + ((parent == null) ? "" : parent.getName()));
1088fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1089fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo parentStateInfo = null;
1090fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (parent != null) {
1091fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                parentStateInfo = mStateInfo.get(parent);
1092fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (parentStateInfo == null) {
1093fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    // Recursively add our parent as it's not been added yet.
1094fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    parentStateInfo = addState(parent, null);
1095fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
1096fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1097fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo stateInfo = mStateInfo.get(state);
1098fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (stateInfo == null) {
1099fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                stateInfo = new StateInfo();
1100fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateInfo.put(state, stateInfo);
1101fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1102fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1103fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Validate that we aren't adding the same state in two different hierarchies.
1104fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if ((stateInfo.parentStateInfo != null) &&
1105fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    (stateInfo.parentStateInfo != parentStateInfo)) {
1106fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    throw new RuntimeException("state already added");
1107fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1108fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            stateInfo.state = state;
1109fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            stateInfo.parentStateInfo = parentStateInfo;
1110fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            stateInfo.active = false;
1111fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) Log.d(TAG, "addStateInternal: X stateInfo: " + stateInfo);
1112fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return stateInfo;
1113fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1114fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1115fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1116fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Constructor
1117fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1118fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @param looper for dispatching messages
111964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville         * @param sm the hierarchical state machine
1120fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
112164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private SmHandler(Looper looper, StateMachine sm) {
1122fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            super(looper);
112364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            mSm = sm;
1124fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1125fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mHaltingState, null);
11261b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            addState(mQuittingState, null);
1127fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1128fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
112964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#setInitialState(State) */
113064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final void setInitialState(State initialState) {
1131cea056f5894543819898a0e62f98dc7870b27758Wink Saville            if (mDbg) Log.d(TAG, "setInitialState: initialState=" + initialState.getName());
1132fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mInitialState = initialState;
1133fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1134fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
113564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#transitionTo(IState) */
113664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final void transitionTo(IState destState) {
113764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            mDestState = (State) destState;
1138cea056f5894543819898a0e62f98dc7870b27758Wink Saville            if (mDbg) Log.d(TAG, "transitionTo: destState=" + mDestState.getName());
1139fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1140fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
114164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#deferMessage(Message) */
1142fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void deferMessage(Message msg) {
1143fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) Log.d(TAG, "deferMessage: msg=" + msg.what);
1144fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1145fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /* Copy the "msg" to "newMsg" as "msg" will be recycled */
1146fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Message newMsg = obtainMessage();
1147fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            newMsg.copyFrom(msg);
1148fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1149fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mDeferredMessages.add(newMsg);
1150fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1151fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1152bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        /** @see StateMachine#quit() */
11531b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private final void quit() {
11541b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            if (mDbg) Log.d(TAG, "quit:");
1155cea056f5894543819898a0e62f98dc7870b27758Wink Saville            sendMessage(obtainMessage(SM_QUIT_CMD, mSmHandlerObj));
11561b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
11571b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1158bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        /** @see StateMachine#quitNow() */
1159bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        private final void quitNow() {
1160bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            if (mDbg) Log.d(TAG, "abort:");
1161bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            sendMessageAtFrontOfQueue(obtainMessage(SM_QUIT_CMD, mSmHandlerObj));
1162bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        }
1163bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1164bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        /** Validate that the message was sent by quit or abort. */
11651b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private final boolean isQuit(Message msg) {
1166cea056f5894543819898a0e62f98dc7870b27758Wink Saville            return (msg.what == SM_QUIT_CMD) && (msg.obj == mSmHandlerObj);
11671b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
11681b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
116964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#isDbg() */
1170fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final boolean isDbg() {
1171fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return mDbg;
1172fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1173fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
117464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#setDbg(boolean) */
1175fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void setDbg(boolean dbg) {
1176fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mDbg = dbg;
1177fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1178fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1179fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1180fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
118164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private SmHandler mSmHandler;
118264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private HandlerThread mSmThread;
1183fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1184fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1185fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Initialize.
1186fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1187fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param looper for this state machine
1188fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param name of the state machine
1189fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1190f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville    private void initStateMachine(String name, Looper looper) {
1191fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        mName = name;
119264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler = new SmHandler(looper, this);
1193fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1194fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1195fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
119664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Constructor creates a StateMachine with its own thread.
1197fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1198fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param name of the state machine
1199fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
120064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected StateMachine(String name) {
120164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmThread = new HandlerThread(name);
120264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmThread.start();
120364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        Looper looper = mSmThread.getLooper();
1204fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1205f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville        initStateMachine(name, looper);
1206fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1207fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1208fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1209f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa     * Constructor creates a StateMachine using the looper.
1210fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1211fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param name of the state machine
1212fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
121364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected StateMachine(String name, Looper looper) {
1214f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville        initStateMachine(name, looper);
1215fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1216fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1217fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1218fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Add a new state to the state machine
1219fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param state the state to add
1220fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param parent the parent of state
1221fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
122264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void addState(State state, State parent) {
122364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.addState(state, parent);
1224fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1225a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
1226a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /**
1227a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * @return current message
1228a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     */
1229a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    protected final Message getCurrentMessage() {
123064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return mSmHandler.getCurrentMessage();
1231a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    }
1232a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
1233fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1234fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @return current state
1235fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
123664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final IState getCurrentState() {
123764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return mSmHandler.getCurrentState();
1238fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1239fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1240fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1241fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Add a new state to the state machine, parent will be null
1242fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param state to add
1243fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
124464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void addState(State state) {
124564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.addState(state, null);
1246fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1247fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1248fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1249fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Set the initial state. This must be invoked before
1250fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * and messages are sent to the state machine.
1251fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1252fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param initialState is the state which will receive the first message.
1253fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
125464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void setInitialState(State initialState) {
125564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.setInitialState(initialState);
1256fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1257fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1258fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1259fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * transition to destination state. Upon returning
1260fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * from processMessage the current state's exit will
1261fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * be executed and upon the next message arriving
1262fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * destState.enter will be invoked.
1263fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1264d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * this function can also be called inside the enter function of the
1265d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * previous transition target, but the behavior is undefined when it is
1266d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * called mid-way through a previous transition (for example, calling this
1267d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * in the enter() routine of a intermediate node when the current transition
1268d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * target is one of the nodes descendants).
1269d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     *
1270fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param destState will be the state that receives the next message.
1271fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
127264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void transitionTo(IState destState) {
127364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.transitionTo(destState);
1274fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1275fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1276fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1277fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * transition to halt state. Upon returning
1278fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * from processMessage we will exit all current
1279bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * states, execute the onHalting() method and then
1280bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * for all subsequent messages haltedProcessMessage
1281fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * will be called.
1282fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1283fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected final void transitionToHaltingState() {
128464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.transitionTo(mSmHandler.mHaltingState);
1285fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1286fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1287fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1288fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Defer this message until next state transition.
1289fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Upon transitioning all deferred messages will be
1290fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * placed on the queue and reprocessed in the original
1291fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * order. (i.e. The next state the oldest messages will
1292fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * be processed first)
1293fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1294fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param msg is deferred until the next transition.
1295fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1296fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected final void deferMessage(Message msg) {
129764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.deferMessage(msg);
1298fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1299fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1300fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1301fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Called when message wasn't handled
1302fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1303fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param msg that couldn't be handled.
1304fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1305fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected void unhandledMessage(Message msg) {
130664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        if (mSmHandler.mDbg) Log.e(TAG, mName + " - unhandledMessage: msg.what=" + msg.what);
1307fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1308fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1309fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1310fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Called for any message that is received after
1311fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * transitionToHalting is called.
1312fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1313fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected void haltedProcessMessage(Message msg) {
1314fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1315fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1316fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1317d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * This will be called once after handling a message that called
1318d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * transitionToHalting. All subsequent messages will invoke
131964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * {@link StateMachine#haltedProcessMessage(Message)}
1320fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1321bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected void onHalting() {
1322fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1323fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1324fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1325d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * This will be called once after a quit message that was NOT handled by
132664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * the derived StateMachine. The StateMachine will stop and any subsequent messages will be
132764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * ignored. In addition, if this StateMachine created the thread, the thread will
1328d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * be stopped after this method returns.
13291b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     */
1330bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected void onQuitting() {
13311b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    }
13321b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
13331b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    /**
1334fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @return the name
1335fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1336fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final String getName() {
1337fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        return mName;
1338fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1339fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1340fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1341bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Set number of log records to maintain and clears all current records.
1342fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1343fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param maxSize number of messages to maintain at anyone time.
1344fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1345bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final void setLogRecSize(int maxSize) {
1346bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        mSmHandler.mLogRecords.setSize(maxSize);
1347bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1348bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1349bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1350bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return number of log records
1351bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1352bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final int getLogRecSize() {
1353bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return mSmHandler.mLogRecords.size();
1354bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1355bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1356bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1357bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return the total number of records processed
1358bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1359bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final int getLogRecCount() {
1360bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return mSmHandler.mLogRecords.count();
1361bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1362bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1363bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1364bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return a log record
1365bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1366bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final LogRec getLogRec(int index) {
1367bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return mSmHandler.mLogRecords.get(index);
1368bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1369bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1370bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1371bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Add the string to LogRecords.
1372bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     *
1373bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @param string
1374bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1375bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected void addLogRec(String string) {
1376bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        mSmHandler.mLogRecords.add(null, string, null, null);
1377fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1378fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1379fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1380bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Add the string and state to LogRecords
1381bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     *
1382bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @param string
1383bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @param state current state
1384fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1385bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected void addLogRec(String string, State state) {
1386bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        mSmHandler.mLogRecords.add(null, string, state, null);
1387fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1388fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1389fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1390bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return true if msg should be saved in the log, default is true.
1391fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1392bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected boolean recordLogRec(Message msg) {
1393bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return true;
1394fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1395fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1396fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1397bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Return a string to be logged by LogRec, default
1398bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * is an empty string. Override if additional information is desired.
1399bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     *
1400bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @param msg that was processed
1401bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return information to be logged as a String
1402fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1403bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected String getLogRecString(Message msg) {
1404bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return "";
1405bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1406bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1407bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1408bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return the string for msg.what
1409bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1410bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected String getWhatToString(int what) {
1411bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return null;
1412fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1413fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1414fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1415fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @return Handler
1416fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1417fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final Handler getHandler() {
141864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return mSmHandler;
1419fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1420fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1421fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1422fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Get a message and set Message.target = this.
1423fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1424a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh     * @return message or null if SM has quit
1425fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1426fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final Message obtainMessage()
1427fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    {
1428a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return null;
1429a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
143064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler);
1431fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1432fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1433fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1434fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Get a message and set Message.target = this and what
1435fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1436fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param what is the assigned to Message.what.
1437a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh     * @return message or null if SM has quit
1438fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1439fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final Message obtainMessage(int what) {
1440a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return null;
1441a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
144264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what);
1443fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1444fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1445fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1446fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Get a message and set Message.target = this,
1447fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * what and obj.
1448fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1449fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param what is the assigned to Message.what.
1450fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param obj is assigned to Message.obj.
1451a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh     * @return message or null if SM has quit
1452fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1453fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final Message obtainMessage(int what, Object obj)
1454fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    {
1455a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return null;
1456a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
145764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what, obj);
1458fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1459fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
146091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
146196e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * Get a message and set Message.target = this,
146296e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * what, arg1 and arg2
146396e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     *
146496e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param what  is assigned to Message.what
146596e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg1  is assigned to Message.arg1
146696e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg2  is assigned to Message.arg2
1467a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh     * @return  A Message object from the global pool or null if
1468a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh     *          SM has quit
146996e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     */
147096e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    public final Message obtainMessage(int what, int arg1, int arg2)
147196e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    {
1472a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return null;
1473a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
147464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what, arg1, arg2);
147596e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    }
147696e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff
147796e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    /**
147896e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * Get a message and set Message.target = this,
147996e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * what, arg1, arg2 and obj
148096e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     *
148196e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param what  is assigned to Message.what
148296e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg1  is assigned to Message.arg1
148396e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg2  is assigned to Message.arg2
148496e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param obj is assigned to Message.obj
1485a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh     * @return  A Message object from the global pool or null if
1486a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh     *          SM has quit
148796e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     */
148896e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
148996e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    {
1490a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return null;
1491a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
149264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what, arg1, arg2, obj);
149396e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    }
149496e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff
149596e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    /**
149691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine.
149791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
149891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessage(int what) {
1499a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1500a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return;
1501a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
150264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.sendMessage(obtainMessage(what));
150391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
150491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
150591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
150691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine.
150791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
150891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessage(int what, Object obj) {
1509a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1510a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return;
1511a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
151264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.sendMessage(obtainMessage(what,obj));
151391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
151491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
1515fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1516fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Enqueue a message to this state machine.
1517fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1518fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final void sendMessage(Message msg) {
1519a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1520a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return;
1521a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
152264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.sendMessage(msg);
1523fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1524fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1525fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1526fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Enqueue a message to this state machine after a delay.
1527fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
152891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessageDelayed(int what, long delayMillis) {
1529a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1530a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return;
1531a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
153264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.sendMessageDelayed(obtainMessage(what), delayMillis);
153391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
153491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
153591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
153691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine after a delay.
153791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
153891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessageDelayed(int what, Object obj, long delayMillis) {
1539a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1540a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return;
1541a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
154264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.sendMessageDelayed(obtainMessage(what, obj), delayMillis);
154391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
154491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
154591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
154691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine after a delay.
154791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
1548fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final void sendMessageDelayed(Message msg, long delayMillis) {
1549a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1550a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return;
1551a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
155264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.sendMessageDelayed(msg, delayMillis);
1553fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1554fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1555fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1556fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Enqueue a message to the front of the queue for this state machine.
155764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1558fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
155991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    protected final void sendMessageAtFrontOfQueue(int what, Object obj) {
156064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.sendMessageAtFrontOfQueue(obtainMessage(what, obj));
156191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
156291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
156391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
156491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to the front of the queue for this state machine.
156564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
156691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
156791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    protected final void sendMessageAtFrontOfQueue(int what) {
156864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.sendMessageAtFrontOfQueue(obtainMessage(what));
156991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
157091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
157191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
157291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to the front of the queue for this state machine.
157364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
157491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
1575fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected final void sendMessageAtFrontOfQueue(Message msg) {
157664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.sendMessageAtFrontOfQueue(msg);
1577fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1578fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1579fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1580aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh     * Removes a message from the message queue.
158164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1582aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh     */
1583aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh    protected final void removeMessages(int what) {
158464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.removeMessages(what);
1585aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh    }
1586aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh
1587aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh    /**
1588bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Quit the state machine after all currently queued up messages are processed.
15891b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     */
1590bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected final void quit() {
1591bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        // mSmHandler can be null if the state machine is already stopped.
1592a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return;
1593a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
159464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.quit();
15951b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    }
15961b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
15971b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    /**
1598bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Quit the state machine immediately all currently queued messages will be discarded.
15991b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     */
1600bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected final void quitNow() {
1601bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        // mSmHandler can be null if the state machine is already stopped.
1602bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        if (mSmHandler == null) return;
1603583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
1604bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        mSmHandler.quitNow();
1605583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    }
1606583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
1607583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    /**
1608fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @return if debugging is enabled
1609fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1610fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public boolean isDbg() {
1611a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1612a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return false;
1613a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
161464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return mSmHandler.isDbg();
1615fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1616fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1617fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1618fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Set debug enable/disabled.
1619fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1620fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param dbg is true to enable debugging.
1621fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1622fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void setDbg(boolean dbg) {
1623a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1624a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return;
1625a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
162664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.setDbg(dbg);
1627fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1628fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1629fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1630fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Start the state machine.
1631fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1632fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void start() {
1633a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1634a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        if (mSmHandler == null) return;
1635a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1636fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** Send the complete construction message */
163764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.completeConstruction();
1638fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1639583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
1640583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    /**
1641583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * Dump the current state.
1642583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     *
1643583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * @param fd
1644583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * @param pw
1645583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * @param args
1646583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     */
1647583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1648583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        pw.println(getName() + ":");
1649bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        pw.println(" total records=" + getLogRecCount());
1650bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        for (int i=0; i < getLogRecSize(); i++) {
1651bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            pw.printf(" rec[%d]: %s\n", i, getLogRec(i).toString(this));
1652583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            pw.flush();
1653583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        }
1654583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        pw.println("curState=" + getCurrentState().getName());
1655583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    }
1656fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
1657