StateMachine.java revision ff4fcdb98c9575642c48f1daeafff4b257769e81
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;
30efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Savilleimport java.util.Collection;
31fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport java.util.HashMap;
32d3059487abd526b91b912f70939c1c6994eecf52Wink Savilleimport java.util.Vector;
33fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
34fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville/**
35fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * {@hide}
36fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
3764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>The state machine defined here is a hierarchical state machine which processes messages
3833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * and can have states arranged hierarchically.</p>
3958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville *
4064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>A state is a <code>State</code> object and must implement
4133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <code>processMessage</code> and optionally <code>enter/exit/getName</code>.
42fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * The enter/exit methods are equivalent to the construction and destruction
43fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * in Object Oriented programming and are used to perform initialization and
44fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * cleanup of the state respectively. The <code>getName</code> method returns the
45fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * name of the state the default implementation returns the class name it may be
46fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * desirable to have this return the name of the state instance name instead.
4733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * In particular if a particular state class has multiple instances.</p>
48fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
4933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>When a state machine is created <code>addState</code> is used to build the
50fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * hierarchy and <code>setInitialState</code> is used to identify which of these
51fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * is the initial state. After construction the programmer calls <code>start</code>
52cea056f5894543819898a0e62f98dc7870b27758Wink Saville * which initializes and starts the state machine. The first action the StateMachine
53cea056f5894543819898a0e62f98dc7870b27758Wink Saville * is to the invoke <code>enter</code> for all of the initial state's hierarchy,
54cea056f5894543819898a0e62f98dc7870b27758Wink Saville * starting at its eldest parent. The calls to enter will be done in the context
55cea056f5894543819898a0e62f98dc7870b27758Wink Saville * of the StateMachines Handler not in the context of the call to start and they
56cea056f5894543819898a0e62f98dc7870b27758Wink Saville * will be invoked before any messages are processed. For example, given the simple
57cea056f5894543819898a0e62f98dc7870b27758Wink Saville * state machine below mP1.enter will be invoked and then mS1.enter. Finally,
58cea056f5894543819898a0e62f98dc7870b27758Wink Saville * messages sent to the state machine will be processed by the current state,
59cea056f5894543819898a0e62f98dc7870b27758Wink Saville * in our simple state machine below that would initially be mS1.processMessage.</p>
60fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville<code>
61fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        mP1
62fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville       /   \
63fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville      mS2   mS1 ----> initial state
64fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville</code>
6533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>After the state machine is created and started, messages are sent to a state
66a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * machine using <code>sendMessage</code> and the messages are created using
67fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * <code>obtainMessage</code>. When the state machine receives a message the
68fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * current state's <code>processMessage</code> is invoked. In the above example
69fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * mS1.processMessage will be invoked first. The state may use <code>transitionTo</code>
7033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * to change the current state to a new state</p>
71fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
7233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Each state in the state machine may have a zero or one parent states and if
73fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * a child state is unable to handle a message it may have the message processed
74a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * by its parent by returning false or NOT_HANDLED. If a message is never processed
75a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * <code>unhandledMessage</code> will be invoked to give one last chance for the state machine
7633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * to process the message.</p>
77fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
7833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>When all processing is completed a state machine may choose to call
79fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * <code>transitionToHaltingState</code>. When the current <code>processingMessage</code>
80fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * returns the state machine will transfer to an internal <code>HaltingState</code>
81fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * and invoke <code>halting</code>. Any message subsequently received by the state
8233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * machine will cause <code>haltedProcessMessage</code> to be invoked.</p>
83fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
84bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville * <p>If it is desirable to completely stop the state machine call <code>quit</code> or
85efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville * <code>quitNow</code>. These will call <code>exit</code> of the current state and its parents,
86efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville * call <code>onQuiting</code> and then exit Thread/Loopers.</p>
871b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville *
8864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>In addition to <code>processMessage</code> each <code>State</code> has
8933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * an <code>enter</code> method and <code>exit</exit> method which may be overridden.</p>
90fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
9133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Since the states are arranged in a hierarchy transitioning to a new state
92fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * causes current states to be exited and new states to be entered. To determine
93fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * the list of states to be entered/exited the common parent closest to
94fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * the current state is found. We then exit from the current state and its
95fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * parent's up to but not including the common parent state and then enter all
96fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * of the new states below the common parent down to the destination state.
97fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * If there is no common parent all states are exited and then the new states
9833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * are entered.</p>
99fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
10033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Two other methods that states can use are <code>deferMessage</code> and
101fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * <code>sendMessageAtFrontOfQueue</code>. The <code>sendMessageAtFrontOfQueue</code> sends
102fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * a message but places it on the front of the queue rather than the back. The
103fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * <code>deferMessage</code> causes the message to be saved on a list until a
104fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * transition is made to a new state. At which time all of the deferred messages
105fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * will be put on the front of the state machine queue with the oldest message
106fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * at the front. These will then be processed by the new current state before
107fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * any other messages that are on the queue or might be added later. Both of
10833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * these are protected and may only be invoked from within a state machine.</p>
109fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
11033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>To illustrate some of these properties we'll use state machine with an 8
11133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * state hierarchy:</p>
112fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville<code>
113fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville          mP0
114fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         /   \
115fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        mP1   mS0
116fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville       /   \
117fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville      mS2   mS1
118fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     /  \    \
119fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    mS3  mS4  mS5  ---> initial state
120fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville</code>
12133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>After starting mS5 the list of active states is mP0, mP1, mS1 and mS5.
122fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * So the order of calling processMessage when a message is received is mS5,
123a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * mS1, mP1, mP0 assuming each processMessage indicates it can't handle this
12433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * message by returning false or NOT_HANDLED.</p>
125fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
12633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Now assume mS5.processMessage receives a message it can handle, and during
127a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * the handling determines the machine should change states. It could call
128a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * transitionTo(mS4) and return true or HANDLED. Immediately after returning from
129fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * processMessage the state machine runtime will find the common parent,
130fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * which is mP1. It will then call mS5.exit, mS1.exit, mS2.enter and then
131fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * mS4.enter. The new list of active states is mP0, mP1, mS2 and mS4. So
13233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * when the next message is received mS4.processMessage will be invoked.</p>
133fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
13464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>Now for some concrete examples, here is the canonical HelloWorld as a state machine.
13533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * It responds with "Hello World" being printed to the log for every message.</p>
136fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville<code>
13764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Savilleclass HelloWorld extends StateMachine {
13864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    HelloWorld(String name) {
139fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        super(name);
140fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        addState(mState1);
141fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        setInitialState(mState1);
142fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
143fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
144fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static HelloWorld makeHelloWorld() {
145fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        HelloWorld hw = new HelloWorld("hw");
146fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        hw.start();
147fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        return hw;
148fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
149fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
15064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class State1 extends State {
1510b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
15258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("Hello World");
153a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            return HANDLED;
154fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
155fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
156fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    State1 mState1 = new State1();
157fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
158fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
159fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savillevoid testHelloWorld() {
160fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    HelloWorld hw = makeHelloWorld();
161fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    hw.sendMessage(hw.obtainMessage());
162fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
163fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville</code>
16433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>A more interesting state machine is one with four states
16533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * with two independent parent states.</p>
166fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville<code>
167fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        mP1      mP2
168fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville       /   \
169fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville      mS2   mS1
170fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville</code>
17133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Here is a description of this state machine using pseudo code.</p>
17233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville <code>
17333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillestate mP1 {
17433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     enter { log("mP1.enter"); }
17533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     exit { log("mP1.exit");  }
17633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     on msg {
17733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_2 {
17833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             send(CMD_3);
17933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             defer(msg);
18033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             transitonTo(mS2);
18133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
18233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
18333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         return NOT_HANDLED;
18433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
18533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
18633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville
18733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleINITIAL
18833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillestate mS1 parent mP1 {
18933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     enter { log("mS1.enter"); }
19033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     exit  { log("mS1.exit");  }
19133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     on msg {
19233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_1 {
19333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             transitionTo(mS1);
19433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
19533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
19633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         return NOT_HANDLED;
19733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
19833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
19933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville
20033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillestate mS2 parent mP1 {
20133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     enter { log("mS2.enter"); }
20233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     exit  { log("mS2.exit");  }
20333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     on msg {
20433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_2 {
20533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             send(CMD_4);
20633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
20733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
20833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_3 {
20933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             defer(msg);
21033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             transitionTo(mP2);
21133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
21233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
21333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         return NOT_HANDLED;
21433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
21533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
21633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville
21733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillestate mP2 {
21833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     enter {
21933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         log("mP2.enter");
22033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         send(CMD_5);
22133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
22233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     exit { log("mP2.exit"); }
22333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     on msg {
22433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_3, CMD_4 { return HANDLED; }
22533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_5 {
22633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             transitionTo(HaltingState);
22733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
22833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
22933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         return NOT_HANDLED;
23033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
23133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
23233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville</code>
23364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>The implementation is below and also in StateMachineTest:</p>
234fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville<code>
23564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Savilleclass Hsm1 extends StateMachine {
236fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_1 = 1;
237fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_2 = 2;
238fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_3 = 3;
239fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_4 = 4;
240fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_5 = 5;
241fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
242fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static Hsm1 makeHsm1() {
24358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        log("makeHsm1 E");
244fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Hsm1 sm = new Hsm1("hsm1");
245fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        sm.start();
24658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        log("makeHsm1 X");
247fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        return sm;
248fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
249fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
250fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    Hsm1(String name) {
251fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        super(name);
25258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        log("ctor E");
253fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
254fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        // Add states, use indentation to show hierarchy
255fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        addState(mP1);
256fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS1, mP1);
257fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS2, mP1);
258fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        addState(mP2);
259fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
260fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        // Set the initial state
261fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        setInitialState(mS1);
26258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        log("ctor X");
263fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
264fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
26564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class P1 extends State {
2660b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void enter() {
26758c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mP1.enter");
268fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
2690b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
270fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            boolean retVal;
27158c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mP1.processMessage what=" + message.what);
272fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            switch(message.what) {
273fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case CMD_2:
274fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // CMD_2 will arrive in mS2 before CMD_3
275fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sendMessage(obtainMessage(CMD_3));
276fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                deferMessage(message);
277fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mS2);
278a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = HANDLED;
279fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
280fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            default:
281fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // Any message we don't understand in this state invokes unhandledMessage
282a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = NOT_HANDLED;
283fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
284fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
285fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return retVal;
286fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
2870b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void exit() {
28858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mP1.exit");
289fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
290fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
291fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
29264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class S1 extends State {
2930b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void enter() {
29458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mS1.enter");
295fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
2960b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
29758c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("S1.processMessage what=" + message.what);
298fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (message.what == CMD_1) {
299fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // Transition to ourself to show that enter/exit is called
300fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mS1);
301a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                return HANDLED;
302fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } else {
303fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // Let parent process all other messages
304a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                return NOT_HANDLED;
305fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
306fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3070b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void exit() {
30858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mS1.exit");
309fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
310fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
311fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
31264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class S2 extends State {
3130b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void enter() {
31458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mS2.enter");
315fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3160b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
317fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            boolean retVal;
31858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mS2.processMessage what=" + message.what);
319fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            switch(message.what) {
320fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_2):
321fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sendMessage(obtainMessage(CMD_4));
322a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = HANDLED;
323fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
324fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_3):
325fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                deferMessage(message);
326fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mP2);
327a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = HANDLED;
328fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
329fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            default:
330a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = NOT_HANDLED;
331fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
332fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
333fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return retVal;
334fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3350b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void exit() {
33658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mS2.exit");
337fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
338fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
339fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
34064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class P2 extends State {
3410b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void enter() {
34258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mP2.enter");
343fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            sendMessage(obtainMessage(CMD_5));
344fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3450b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
34658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("P2.processMessage what=" + message.what);
347fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            switch(message.what) {
348fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_3):
349fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
350fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_4):
351fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
352fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_5):
353fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionToHaltingState();
354fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
355fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
356a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            return HANDLED;
357fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3580b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void exit() {
35958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mP2.exit");
360fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
361fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
362fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
3630b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato    &#64;Override
364bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    void onHalting() {
36558c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        log("halting");
366fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (this) {
367fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            this.notifyAll();
368fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
369fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
370fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
371fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    P1 mP1 = new P1();
372fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    S1 mS1 = new S1();
373fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    S2 mS2 = new S2();
374fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    P2 mP2 = new P2();
375fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
376fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville</code>
37733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>If this is executed by sending two messages CMD_1 and CMD_2
37833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * (Note the synchronize is only needed because we use hsm.wait())</p>
37933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville<code>
38033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleHsm1 hsm = makeHsm1();
38133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillesynchronize(hsm) {
38233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     hsm.sendMessage(obtainMessage(hsm.CMD_1));
38333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     hsm.sendMessage(obtainMessage(hsm.CMD_2));
38433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     try {
38533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville          // wait for the messages to be handled
38633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville          hsm.wait();
38733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     } catch (InterruptedException e) {
38858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville          loge("exception while waiting " + e.getMessage());
38933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
39033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
39133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville</code>
39233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>The output is:</p>
39333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville<code>
39433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): makeHsm1 E
39533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): ctor E
39633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): ctor X
39733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP1.enter
39833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.enter
39933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): makeHsm1 X
40033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.processMessage what=1
40133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.exit
40233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.enter
40333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.processMessage what=2
40433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP1.processMessage what=2
40533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.exit
40633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS2.enter
40733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS2.processMessage what=2
40833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS2.processMessage what=3
40933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS2.exit
41033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP1.exit
41133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.enter
41233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.processMessage what=3
41333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.processMessage what=4
41433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.processMessage what=5
41533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.exit
41633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): halting
41733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville</code>
418fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville */
41964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Savillepublic class StateMachine {
42058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    // Name of the state machine and used as logging tag
421fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private String mName;
422fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
423a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /** Message.what value when quitting */
424bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    private static final int SM_QUIT_CMD = -1;
4251b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
426a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /** Message.what value when initializing */
427bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    private static final int SM_INIT_CMD = -2;
428a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
429a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /**
430a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * Convenience constant that maybe returned by processMessage
431a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * to indicate the the message was processed and is not to be
432a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * processed by parent states
433a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     */
434a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    public static final boolean HANDLED = true;
435a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
436a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /**
437a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * Convenience constant that maybe returned by processMessage
438a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * to indicate the the message was NOT processed and is to be
439a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * processed by parent states
440a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     */
441a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    public static final boolean NOT_HANDLED = false;
442a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
443d3059487abd526b91b912f70939c1c6994eecf52Wink Saville    /**
444bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * StateMachine logging record.
445d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * {@hide}
446d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     */
447bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public static class LogRec {
448efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        private StateMachine mSm;
449583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        private long mTime;
450583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        private int mWhat;
451583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        private String mInfo;
452efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        private IState mState;
453efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        private IState mOrgState;
454efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        private IState mDstState;
455d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
456d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
457d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * Constructor
458bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         *
459bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @param msg
460ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * @param state the state which handled the message
461d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param orgState is the first state the received the message but
462d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * did not processes the message.
463ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * @param transToState is the state that was transitioned to after the message was
464ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * processed.
465d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
466efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        LogRec(StateMachine sm, Message msg, String info, IState state, IState orgState,
467efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                IState transToState) {
468efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            update(sm, msg, info, state, orgState, transToState);
469d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
470d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
471d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
472d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * Update the information in the record.
473d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param state that handled the message
474efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville         * @param orgState is the first state the received the message
475efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville         * @param dstState is the state that was the transition target when logging
476d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
477efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        public void update(StateMachine sm, Message msg, String info, IState state, IState orgState,
478efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                IState dstState) {
479efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            mSm = sm;
480583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            mTime = System.currentTimeMillis();
481bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            mWhat = (msg != null) ? msg.what : 0;
482583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            mInfo = info;
483583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            mState = state;
484583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            mOrgState = orgState;
485efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            mDstState = dstState;
486583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        }
487583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
488583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        /**
489583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @return time stamp
490583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         */
491583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        public long getTime() {
492583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return mTime;
493583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        }
494583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
495583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        /**
496583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @return msg.what
497583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         */
498583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        public long getWhat() {
499583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return mWhat;
500d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
501d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
502d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
503d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @return the command that was executing
504d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
505583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        public String getInfo() {
506583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return mInfo;
507d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
508d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
509d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
510d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @return the state that handled this message
511d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
512efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        public IState getState() {
513583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return mState;
514d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
515d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
516d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
517efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville         * @return the state destination state if a transition is occurring or null if none.
518d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
519efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        public IState getDestState() {
520efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            return mDstState;
521d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
522d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
523d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
524efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville         * @return the original state that received the message.
525d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
526efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        public IState getOriginalState() {
527efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            return mOrgState;
528efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        }
529efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
530efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        @Override
531efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        public String toString() {
532d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            StringBuilder sb = new StringBuilder();
533583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append("time=");
534583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            Calendar c = Calendar.getInstance();
535583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            c.setTimeInMillis(mTime);
536583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
537ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            sb.append(" processed=");
538583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append(mState == null ? "<null>" : mState.getName());
539ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            sb.append(" org=");
540583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append(mOrgState == null ? "<null>" : mOrgState.getName());
541ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            sb.append(" dest=");
542efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            sb.append(mDstState == null ? "<null>" : mDstState.getName());
543583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append(" what=");
544efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            String what = mSm != null ? mSm.getWhatToString(mWhat) : "";
545bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            if (TextUtils.isEmpty(what)) {
546bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append(mWhat);
547bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append("(0x");
548bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append(Integer.toHexString(mWhat));
549bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append(")");
550bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            } else {
551bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append(what);
552bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            }
553ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            if (!TextUtils.isEmpty(mInfo)) {
554583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville                sb.append(" ");
555583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville                sb.append(mInfo);
556d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
557583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return sb.toString();
558d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
559d3059487abd526b91b912f70939c1c6994eecf52Wink Saville    }
560d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
561d3059487abd526b91b912f70939c1c6994eecf52Wink Saville    /**
562bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * A list of log records including messages recently processed by the state machine.
563d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     *
564bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * The class maintains a list of log records including messages
565d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * recently processed. The list is finite and may be set in the
566d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * constructor or by calling setSize. The public interface also
567bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * includes size which returns the number of recent records,
568bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * count which is the number of records processed since the
569bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * the last setSize, get which returns a record and
570bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * add which adds a record.
571d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     */
572bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    private static class LogRecords {
573d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
574d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        private static final int DEFAULT_SIZE = 20;
575d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
576ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        private Vector<LogRec> mLogRecVector = new Vector<LogRec>();
577d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        private int mMaxSize = DEFAULT_SIZE;
578d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        private int mOldestIndex = 0;
579d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        private int mCount = 0;
580ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        private boolean mLogOnlyTransitions = false;
581d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
582d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
583583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * private constructor use add
584d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
585bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        private LogRecords() {
586d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
587d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
588d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
589bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * Set size of messages to maintain and clears all current records.
590d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         *
591bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @param maxSize number of records to maintain at anyone time.
592d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        */
593bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized void setSize(int maxSize) {
594d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            mMaxSize = maxSize;
595d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            mCount = 0;
596ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            mLogRecVector.clear();
597ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        }
598ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
599ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        synchronized void setLogOnlyTransitions(boolean enable) {
600ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            mLogOnlyTransitions = enable;
601ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        }
602ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
603ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        synchronized boolean logOnlyTransitions() {
604ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            return mLogOnlyTransitions;
605d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
606d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
607d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
608bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @return the number of recent records.
609d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
610bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized int size() {
611ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            return mLogRecVector.size();
612d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
613d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
614d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
615bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @return the total number of records processed since size was set.
616d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
617bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized int count() {
618d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            return mCount;
619d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
620d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
621d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
622bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * Clear the list of records.
6236f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh         */
624bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized void cleanup() {
625ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            mLogRecVector.clear();
6266f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        }
6276f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh
6286f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        /**
629d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @return the information on a particular record. 0 is the oldest
630d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * record and size()-1 is the newest record. If the index is to
631d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * large null is returned.
632d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
633bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized LogRec get(int index) {
634d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            int nextIndex = mOldestIndex + index;
635d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            if (nextIndex >= mMaxSize) {
636d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                nextIndex -= mMaxSize;
637d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
638d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            if (nextIndex >= size()) {
639d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                return null;
640d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            } else {
641ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff                return mLogRecVector.get(nextIndex);
642d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
643d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
644d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
645d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
646d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * Add a processed message.
647d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         *
648583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @param msg
649583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @param messageInfo to be stored
650d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param state that handled the message
651d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param orgState is the first state the received the message but
652d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * did not processes the message.
653ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * @param transToState is the state that was transitioned to after the message was
654ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * processed.
655ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         *
656d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
657efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        synchronized void add(StateMachine sm, Message msg, String messageInfo, IState state,
658ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                IState orgState, IState transToState) {
659d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            mCount += 1;
660ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            if (mLogRecVector.size() < mMaxSize) {
661efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                mLogRecVector.add(new LogRec(sm, msg, messageInfo, state, orgState, transToState));
662d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            } else {
663ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff                LogRec pmi = mLogRecVector.get(mOldestIndex);
664d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                mOldestIndex += 1;
665d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                if (mOldestIndex >= mMaxSize) {
666d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                    mOldestIndex = 0;
667d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                }
668efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                pmi.update(sm, msg, messageInfo, state, orgState, transToState);
669d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
670d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
671d3059487abd526b91b912f70939c1c6994eecf52Wink Saville    }
672d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
67364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private static class SmHandler extends Handler {
674fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
675fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The debug flag */
676fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private boolean mDbg = false;
677fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
678cea056f5894543819898a0e62f98dc7870b27758Wink Saville        /** The SmHandler object, identifies that message is internal */
679cea056f5894543819898a0e62f98dc7870b27758Wink Saville        private static final Object mSmHandlerObj = new Object();
6801b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
681a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        /** The current message */
682a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        private Message mMsg;
683a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
684bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        /** A list of log records including messages this state machine has processed */
685bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        private LogRecords mLogRecords = new LogRecords();
686fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
687fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** true if construction of the state machine has not been completed */
688fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private boolean mIsConstructionCompleted;
689fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
690fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** Stack used to manage the current hierarchy of states */
691fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateInfo mStateStack[];
692fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
693fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** Top of mStateStack */
694fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mStateStackTopIndex = -1;
695fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
696fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** A temporary stack used to manage the state stack */
697fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateInfo mTempStateStack[];
698fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
699fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The top of the mTempStateStack */
700fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mTempStateStackCount;
701fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
702fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** State used when state machine is halted */
703fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private HaltingState mHaltingState = new HaltingState();
704fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
7051b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        /** State used when state machine is quitting */
7061b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private QuittingState mQuittingState = new QuittingState();
7071b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
70864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** Reference to the StateMachine */
70964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private StateMachine mSm;
710fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
711fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
712fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Information about a state.
713fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Used to maintain the hierarchy.
714fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
715fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private class StateInfo {
716fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /** The state */
71764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            State state;
718fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
719fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /** The parent of this state, null if there is no parent */
720fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo parentStateInfo;
721fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
722fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /** True when the state has been entered and on the stack */
723fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            boolean active;
724fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
725fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
726fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * Convert StateInfo to string
727fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
728fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override
729fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            public String toString() {
730ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                return "state=" + state.getName() + ",active=" + active + ",parent="
731ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + ((parentStateInfo == null) ? "null" : parentStateInfo.state.getName());
732fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
733fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
734fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
735fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The map of all of the states in the state machine */
736ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        private HashMap<State, StateInfo> mStateInfo = new HashMap<State, StateInfo>();
737fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
738fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The initial state that will process the first message */
73964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private State mInitialState;
740fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
741fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The destination state when transitionTo has been invoked */
74264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private State mDestState;
743fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
744fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The list of deferred messages */
745fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ArrayList<Message> mDeferredMessages = new ArrayList<Message>();
746fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
747fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
748fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * State entered when transitionToHaltingState is called.
749fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
75064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private class HaltingState extends State {
751fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override
752fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            public boolean processMessage(Message msg) {
75364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville                mSm.haltedProcessMessage(msg);
754fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
755fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
756fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
757fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
758fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
7591b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville         * State entered when a valid quit message is handled.
7601b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville         */
76164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private class QuittingState extends State {
7621b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            @Override
7631b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            public boolean processMessage(Message msg) {
764a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                return NOT_HANDLED;
7651b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            }
7661b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
7671b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
7681b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        /**
769fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Handle messages sent to the state machine by calling
770fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * the current state's processMessage. It also handles
771fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * the enter/exit calls and placing any deferred messages
772fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * back onto the queue when transitioning to a new state.
773fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
774fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
775fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        public final void handleMessage(Message msg) {
77658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("handleMessage: E msg.what=" + msg.what);
777fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
778a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            /** Save the current message */
779a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            mMsg = msg;
780a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
781ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            /** State that processed the message */
782ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            State msgProcessedState = null;
783cea056f5894543819898a0e62f98dc7870b27758Wink Saville            if (mIsConstructionCompleted) {
784cea056f5894543819898a0e62f98dc7870b27758Wink Saville                /** Normal path */
785ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff                msgProcessedState = processMsg(msg);
786ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            } else if (!mIsConstructionCompleted && (mMsg.what == SM_INIT_CMD)
787ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                    && (mMsg.obj == mSmHandlerObj)) {
788cea056f5894543819898a0e62f98dc7870b27758Wink Saville                /** Initial one time path. */
789cea056f5894543819898a0e62f98dc7870b27758Wink Saville                mIsConstructionCompleted = true;
790cea056f5894543819898a0e62f98dc7870b27758Wink Saville                invokeEnterMethods(0);
791cea056f5894543819898a0e62f98dc7870b27758Wink Saville            } else {
792ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                throw new RuntimeException("StateMachine.handleMessage: "
793ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + "The start method not called, received msg: " + msg);
794fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
795efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            performTransitions(msgProcessedState, msg);
796fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
797efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            // We need to check if mSm == null here as we could be quitting.
798efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            if (mDbg && mSm != null) mSm.log("handleMessage: X");
799e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville        }
800e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville
801e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville        /**
802e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville         * Do any transitions
803ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * @param msgProcessedState is the state that processed the message
804e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville         */
805efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        private void performTransitions(State msgProcessedState, Message msg) {
806fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
807fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * If transitionTo has been called, exit and then enter
808e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * the appropriate states. We loop on this to allow
809e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * enter and exit methods to use transitionTo.
810fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
811ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            State orgState = mStateStack[mStateStackTopIndex].state;
812ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
813efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            /**
814efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville             * Record whether message needs to be logged before we transition and
815efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville             * and we won't log special messages SM_INIT_CMD or SM_QUIT_CMD which
816efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville             * always set msg.obj to the handler.
817efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville             */
818f643069ad56763732a06ab601cea1272e4c1827aWink Saville            boolean recordLogMsg = mSm.recordLogRec(mMsg) && (msg.obj != mSmHandlerObj);
819ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
820efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            if (mLogRecords.logOnlyTransitions()) {
821efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                /** Record only if there is a transition */
822efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                if (mDestState != null) {
823efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState,
824efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                            orgState, mDestState);
825efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                }
826efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            } else if (recordLogMsg) {
827efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                /** Record message */
828ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState, orgState,
829ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        mDestState);
830efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            }
831fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
832efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            State destState = mDestState;
833efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            if (destState != null) {
834fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                /**
835efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                 * Process the transitions including transitions in the enter/exit methods
836e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                 */
837efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                while (true) {
838efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    if (mDbg) mSm.log("handleMessage: new destination call exit/enter");
839e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville
840efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    /**
841efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * Determine the states to exit and enter and return the
842efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * common ancestor state of the enter/exit states. Then
843efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * invoke the exit methods then the enter methods.
844efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     */
845efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
846efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    invokeExitMethods(commonStateInfo);
847efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    int stateStackEnteringIndex = moveTempStateStackToStateStack();
848efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    invokeEnterMethods(stateStackEnteringIndex);
849fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
850efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    /**
851efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * Since we have transitioned to a new state we need to have
852efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * any deferred messages moved to the front of the message queue
853efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * so they will be processed before any other messages in the
854efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * message queue.
855efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     */
856efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    moveDeferredMessageAtFrontOfQueue();
857efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
858efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    if (destState != mDestState) {
859efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                        // A new mDestState so continue looping
860efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                        destState = mDestState;
861efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    } else {
862efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                        // No change in mDestState so we're done
863efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                        break;
864efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    }
865efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                }
866efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                mDestState = null;
867e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            }
868fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
869e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            /**
870e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * After processing all transitions check and
871e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * see if the last transition was to quit or halt.
872e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             */
873e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            if (destState != null) {
874e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                if (destState == mQuittingState) {
875bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    /**
876bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     * Call onQuitting to let subclasses cleanup.
877bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     */
878bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    mSm.onQuitting();
8796f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                    cleanupAfterQuitting();
880e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                } else if (destState == mHaltingState) {
881e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                    /**
882bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     * Call onHalting() if we've transitioned to the halting
883e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                     * state. All subsequent messages will be processed in
884e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                     * in the halting state which invokes haltedProcessMessage(msg);
885e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                     */
886bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    mSm.onHalting();
887fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
888fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
889fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
890fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
891fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
8926f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh         * Cleanup all the static variables and the looper after the SM has been quit.
8936f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh         */
8946f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        private final void cleanupAfterQuitting() {
8956f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            if (mSm.mSmThread != null) {
8966f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                // If we made the thread then quit looper which stops the thread.
8976f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                getLooper().quit();
8986f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                mSm.mSmThread = null;
8996f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            }
9006f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh
9016f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mSm.mSmHandler = null;
9026f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mSm = null;
9036f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mMsg = null;
904bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            mLogRecords.cleanup();
9056f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mStateStack = null;
9066f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mTempStateStack = null;
9076f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mStateInfo.clear();
9086f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mInitialState = null;
9096f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mDestState = null;
9106f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mDeferredMessages.clear();
9116f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        }
9126f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh
9136f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        /**
914fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Complete the construction of the state machine.
915fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
916fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void completeConstruction() {
91758c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("completeConstruction: E");
918fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
919fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
920fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * Determine the maximum depth of the state hierarchy
921fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * so we can allocate the state stacks.
922fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
923fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int maxDepth = 0;
924fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (StateInfo si : mStateInfo.values()) {
925fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                int depth = 0;
926fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                for (StateInfo i = si; i != null; depth++) {
927fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    i = i.parentStateInfo;
928fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
929fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (maxDepth < depth) {
930fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    maxDepth = depth;
931fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
932fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
93358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("completeConstruction: maxDepth=" + maxDepth);
934fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
935fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mStateStack = new StateInfo[maxDepth];
936fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mTempStateStack = new StateInfo[maxDepth];
937fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setupInitialStateStack();
938fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
939cea056f5894543819898a0e62f98dc7870b27758Wink Saville            /** Sending SM_INIT_CMD message to invoke enter methods asynchronously */
940cea056f5894543819898a0e62f98dc7870b27758Wink Saville            sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));
941e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville
94258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("completeConstruction: X");
943fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
944fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
945fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
946fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Process the message. If the current state doesn't handle
947fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * it, call the states parent and so on. If it is never handled then
948fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * call the state machines unhandledMessage method.
949ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * @return the state that processed the message
950fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
951ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        private final State processMsg(Message msg) {
952fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
953fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
95458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                mSm.log("processMsg: " + curStateInfo.state.getName());
955fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
956bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
957bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            if (isQuit(msg)) {
958bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                transitionTo(mQuittingState);
959bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            } else {
960bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                while (!curStateInfo.state.processMessage(msg)) {
961fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    /**
962bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     * Not processed
963fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                     */
964bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    curStateInfo = curStateInfo.parentStateInfo;
965bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    if (curStateInfo == null) {
966bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        /**
967bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                         * No parents left so it's not handled
968bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                         */
969bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        mSm.unhandledMessage(msg);
970bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        break;
971bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    }
972bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    if (mDbg) {
97358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                        mSm.log("processMsg: " + curStateInfo.state.getName());
9741b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                    }
975fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
976ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            }
977ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            return (curStateInfo != null) ? curStateInfo.state : null;
978fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
979fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
980fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
981fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Call the exit method for each state from the top of stack
982fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * up to the common ancestor state.
983fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
984fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void invokeExitMethods(StateInfo commonStateInfo) {
985ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            while ((mStateStackTopIndex >= 0)
986ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                    && (mStateStack[mStateStackTopIndex] != commonStateInfo)) {
98764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville                State curState = mStateStack[mStateStackTopIndex].state;
98858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                if (mDbg) mSm.log("invokeExitMethods: " + curState.getName());
989fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                curState.exit();
990fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[mStateStackTopIndex].active = false;
991fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStackTopIndex -= 1;
992fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
993fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
994fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
995fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
996fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Invoke the enter method starting at the entering index to top of state stack
997fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
998fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void invokeEnterMethods(int stateStackEnteringIndex) {
999fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
100058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                if (mDbg) mSm.log("invokeEnterMethods: " + mStateStack[i].state.getName());
1001fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[i].state.enter();
1002fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[i].active = true;
1003fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1004fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1005fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1006fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1007fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Move the deferred message to the front of the message queue.
1008fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1009fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void moveDeferredMessageAtFrontOfQueue() {
1010fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
1011fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * The oldest messages on the deferred list must be at
1012fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * the front of the queue so start at the back, which
1013fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * as the most resent message and end with the oldest
1014fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * messages at the front of the queue.
1015fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
1016ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            for (int i = mDeferredMessages.size() - 1; i >= 0; i--) {
1017fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Message curMsg = mDeferredMessages.get(i);
101858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                if (mDbg) mSm.log("moveDeferredMessageAtFrontOfQueue; what=" + curMsg.what);
1019fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sendMessageAtFrontOfQueue(curMsg);
1020fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1021fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mDeferredMessages.clear();
1022fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1023fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1024fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1025fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Move the contents of the temporary stack to the state stack
1026fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * reversing the order of the items on the temporary stack as
1027fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * they are moved.
1028fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
102964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville         * @return index into mStateStack where entering needs to start
1030fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1031fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final int moveTempStateStackToStateStack() {
1032fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int startingIndex = mStateStackTopIndex + 1;
1033fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int i = mTempStateStackCount - 1;
1034fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int j = startingIndex;
1035fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            while (i >= 0) {
103658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                if (mDbg) mSm.log("moveTempStackToStateStack: i=" + i + ",j=" + j);
1037fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[j] = mTempStateStack[i];
1038fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                j += 1;
1039fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                i -= 1;
1040fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1041fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1042fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mStateStackTopIndex = j - 1;
1043fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
1044ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                mSm.log("moveTempStackToStateStack: X mStateStackTop=" + mStateStackTopIndex
1045ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + ",startingIndex=" + startingIndex + ",Top="
1046ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + mStateStack[mStateStackTopIndex].state.getName());
1047fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1048fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return startingIndex;
1049fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1050fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1051fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1052fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Setup the mTempStateStack with the states we are going to enter.
1053fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1054fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * This is found by searching up the destState's ancestors for a
1055fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * state that is already active i.e. StateInfo.active == true.
1056fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * The destStae and all of its inactive parents will be on the
1057fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * TempStateStack as the list of states to enter.
1058fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1059fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @return StateInfo of the common ancestor for the destState and
1060fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * current state or null if there is no common parent.
1061fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
106264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final StateInfo setupTempStateStackWithStatesToEnter(State destState) {
1063fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
1064fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * Search up the parent list of the destination state for an active
1065fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * state. Use a do while() loop as the destState must always be entered
1066fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * even if it is active. This can happen if we are exiting/entering
1067fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * the current state.
1068fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
1069fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mTempStateStackCount = 0;
1070fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo curStateInfo = mStateInfo.get(destState);
1071fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            do {
1072fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mTempStateStack[mTempStateStackCount++] = curStateInfo;
1073fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                curStateInfo = curStateInfo.parentStateInfo;
1074fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } while ((curStateInfo != null) && !curStateInfo.active);
1075fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1076fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
107758c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                mSm.log("setupTempStateStackWithStatesToEnter: X mTempStateStackCount="
1078ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + mTempStateStackCount + ",curStateInfo: " + curStateInfo);
1079fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1080fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return curStateInfo;
1081fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1082fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1083fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1084fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Initialize StateStack to mInitialState.
1085fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1086fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void setupInitialStateStack() {
1087fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
1088ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                mSm.log("setupInitialStateStack: E mInitialState=" + mInitialState.getName());
1089fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1090fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1091fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo curStateInfo = mStateInfo.get(mInitialState);
1092fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {
1093fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mTempStateStack[mTempStateStackCount] = curStateInfo;
1094fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                curStateInfo = curStateInfo.parentStateInfo;
1095fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1096fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1097fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Empty the StateStack
1098fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mStateStackTopIndex = -1;
1099fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1100fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            moveTempStateStackToStateStack();
1101fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1102fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1103fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1104a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville         * @return current message
1105a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville         */
1106a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        private final Message getCurrentMessage() {
1107a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            return mMsg;
1108a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        }
1109a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
1110a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        /**
1111fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @return current state
1112fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
111364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final IState getCurrentState() {
1114fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return mStateStack[mStateStackTopIndex].state;
1115fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1116fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1117fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1118fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Add a new state to the state machine. Bottom up addition
1119fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * of states is allowed but the same state may only exist
1120fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * in one hierarchy.
1121fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1122fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @param state the state to add
1123fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @param parent the parent of state
1124fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @return stateInfo for this state
1125fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
112664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final StateInfo addState(State state, State parent) {
1127fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
1128ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                mSm.log("addStateInternal: E state=" + state.getName() + ",parent="
1129ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + ((parent == null) ? "" : parent.getName()));
1130fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1131fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo parentStateInfo = null;
1132fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (parent != null) {
1133fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                parentStateInfo = mStateInfo.get(parent);
1134fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (parentStateInfo == null) {
1135fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    // Recursively add our parent as it's not been added yet.
1136fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    parentStateInfo = addState(parent, null);
1137fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
1138fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1139fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo stateInfo = mStateInfo.get(state);
1140fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (stateInfo == null) {
1141fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                stateInfo = new StateInfo();
1142fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateInfo.put(state, stateInfo);
1143fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1144fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1145fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Validate that we aren't adding the same state in two different hierarchies.
1146ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            if ((stateInfo.parentStateInfo != null)
1147ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                    && (stateInfo.parentStateInfo != parentStateInfo)) {
1148ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                throw new RuntimeException("state already added");
1149fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1150fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            stateInfo.state = state;
1151fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            stateInfo.parentStateInfo = parentStateInfo;
1152fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            stateInfo.active = false;
115358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("addStateInternal: X stateInfo: " + stateInfo);
1154fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return stateInfo;
1155fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1156fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1157fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1158fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Constructor
1159fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1160fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @param looper for dispatching messages
116164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville         * @param sm the hierarchical state machine
1162fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
116364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private SmHandler(Looper looper, StateMachine sm) {
1164fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            super(looper);
116564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            mSm = sm;
1166fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1167fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mHaltingState, null);
11681b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            addState(mQuittingState, null);
1169fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1170fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
117164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#setInitialState(State) */
117264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final void setInitialState(State initialState) {
117358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("setInitialState: initialState=" + initialState.getName());
1174fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mInitialState = initialState;
1175fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1176fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
117764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#transitionTo(IState) */
117864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final void transitionTo(IState destState) {
117964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            mDestState = (State) destState;
118058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("transitionTo: destState=" + mDestState.getName());
1181fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1182fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
118364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#deferMessage(Message) */
1184fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void deferMessage(Message msg) {
118558c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("deferMessage: msg=" + msg.what);
1186fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1187fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /* Copy the "msg" to "newMsg" as "msg" will be recycled */
1188fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Message newMsg = obtainMessage();
1189fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            newMsg.copyFrom(msg);
1190fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1191fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mDeferredMessages.add(newMsg);
1192fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1193fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1194bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        /** @see StateMachine#quit() */
11951b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private final void quit() {
119658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("quit:");
1197cea056f5894543819898a0e62f98dc7870b27758Wink Saville            sendMessage(obtainMessage(SM_QUIT_CMD, mSmHandlerObj));
11981b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
11991b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1200bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        /** @see StateMachine#quitNow() */
1201bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        private final void quitNow() {
120258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("quitNow:");
1203bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            sendMessageAtFrontOfQueue(obtainMessage(SM_QUIT_CMD, mSmHandlerObj));
1204bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        }
1205bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
120658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        /** Validate that the message was sent by quit or quitNow. */
12071b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private final boolean isQuit(Message msg) {
1208cea056f5894543819898a0e62f98dc7870b27758Wink Saville            return (msg.what == SM_QUIT_CMD) && (msg.obj == mSmHandlerObj);
12091b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
12101b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
121164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#isDbg() */
1212fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final boolean isDbg() {
1213fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return mDbg;
1214fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1215fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
121664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#setDbg(boolean) */
1217fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void setDbg(boolean dbg) {
1218fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mDbg = dbg;
1219fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1220fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1221fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1222fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
122364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private SmHandler mSmHandler;
122464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private HandlerThread mSmThread;
1225fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1226fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1227fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Initialize.
1228fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1229fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param looper for this state machine
1230fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param name of the state machine
1231fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1232f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville    private void initStateMachine(String name, Looper looper) {
1233fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        mName = name;
123464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler = new SmHandler(looper, this);
1235fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1236fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1237fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
123864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Constructor creates a StateMachine with its own thread.
1239fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1240fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param name of the state machine
1241fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
124264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected StateMachine(String name) {
124364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmThread = new HandlerThread(name);
124464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmThread.start();
124564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        Looper looper = mSmThread.getLooper();
1246fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1247f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville        initStateMachine(name, looper);
1248fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1249fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1250fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1251f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa     * Constructor creates a StateMachine using the looper.
1252fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1253fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param name of the state machine
1254fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
125564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected StateMachine(String name, Looper looper) {
1256f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville        initStateMachine(name, looper);
1257fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1258fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1259fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1260fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Add a new state to the state machine
1261fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param state the state to add
1262fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param parent the parent of state
1263fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
126464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void addState(State state, State parent) {
126564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.addState(state, parent);
1266fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1267a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
1268a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /**
1269fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Add a new state to the state machine, parent will be null
1270fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param state to add
1271fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
127264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void addState(State state) {
127364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.addState(state, null);
1274fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1275fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1276fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1277fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Set the initial state. This must be invoked before
1278fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * and messages are sent to the state machine.
1279fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1280fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param initialState is the state which will receive the first message.
1281fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
128264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void setInitialState(State initialState) {
128364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.setInitialState(initialState);
1284fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1285fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1286fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1287efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return current message
1288efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     */
1289efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    protected final Message getCurrentMessage() {
1290efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1291efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1292efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return null;
1293efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.getCurrentMessage();
1294efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    }
1295efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1296efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    /**
1297efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return current state
1298efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     */
1299efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    protected final IState getCurrentState() {
1300efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1301efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1302efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return null;
1303efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.getCurrentState();
1304efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    }
1305efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1306efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    /**
1307fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * transition to destination state. Upon returning
1308fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * from processMessage the current state's exit will
1309fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * be executed and upon the next message arriving
1310fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * destState.enter will be invoked.
1311fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1312d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * this function can also be called inside the enter function of the
1313d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * previous transition target, but the behavior is undefined when it is
1314d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * called mid-way through a previous transition (for example, calling this
1315d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * in the enter() routine of a intermediate node when the current transition
1316d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * target is one of the nodes descendants).
1317d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     *
1318fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param destState will be the state that receives the next message.
1319fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
132064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void transitionTo(IState destState) {
132164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.transitionTo(destState);
1322fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1323fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1324fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1325fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * transition to halt state. Upon returning
1326fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * from processMessage we will exit all current
1327bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * states, execute the onHalting() method and then
1328bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * for all subsequent messages haltedProcessMessage
1329fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * will be called.
1330fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1331fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected final void transitionToHaltingState() {
133264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.transitionTo(mSmHandler.mHaltingState);
1333fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1334fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1335fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1336fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Defer this message until next state transition.
1337fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Upon transitioning all deferred messages will be
1338fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * placed on the queue and reprocessed in the original
1339fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * order. (i.e. The next state the oldest messages will
1340fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * be processed first)
1341fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1342fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param msg is deferred until the next transition.
1343fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1344fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected final void deferMessage(Message msg) {
134564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.deferMessage(msg);
1346fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1347fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1348fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1349fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Called when message wasn't handled
1350fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1351fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param msg that couldn't be handled.
1352fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1353fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected void unhandledMessage(Message msg) {
135458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        if (mSmHandler.mDbg) loge(" - unhandledMessage: msg.what=" + msg.what);
1355fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1356fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1357fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1358fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Called for any message that is received after
1359fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * transitionToHalting is called.
1360fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1361fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected void haltedProcessMessage(Message msg) {
1362fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1363fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1364fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1365d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * This will be called once after handling a message that called
1366d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * transitionToHalting. All subsequent messages will invoke
136764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * {@link StateMachine#haltedProcessMessage(Message)}
1368fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1369bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected void onHalting() {
1370fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1371fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1372fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1373d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * This will be called once after a quit message that was NOT handled by
137464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * the derived StateMachine. The StateMachine will stop and any subsequent messages will be
137564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * ignored. In addition, if this StateMachine created the thread, the thread will
1376d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * be stopped after this method returns.
13771b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     */
1378bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected void onQuitting() {
13791b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    }
13801b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
13811b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    /**
1382fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @return the name
1383fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1384fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final String getName() {
1385fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        return mName;
1386fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1387fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1388fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1389bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Set number of log records to maintain and clears all current records.
1390fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1391fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param maxSize number of messages to maintain at anyone time.
1392fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1393bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final void setLogRecSize(int maxSize) {
1394bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        mSmHandler.mLogRecords.setSize(maxSize);
1395bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1396bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1397bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1398ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff     * Set to log only messages that cause a state transition
1399ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff     *
1400ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff     * @param enable {@code true} to enable, {@code false} to disable
1401ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff     */
1402ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff    public final void setLogOnlyTransitions(boolean enable) {
1403ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        mSmHandler.mLogRecords.setLogOnlyTransitions(enable);
1404ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff    }
1405ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
1406ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff    /**
1407bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return number of log records
1408bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1409bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final int getLogRecSize() {
1410efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1411efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1412efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return 0;
1413efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.mLogRecords.size();
1414bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1415bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1416bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1417bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return the total number of records processed
1418bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1419bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final int getLogRecCount() {
1420efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1421efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1422efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return 0;
1423efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.mLogRecords.count();
1424bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1425bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1426bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1427efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return a log record, or null if index is out of range
1428bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1429bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final LogRec getLogRec(int index) {
1430efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1431efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1432efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return null;
1433efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.mLogRecords.get(index);
1434bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1435bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1436bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1437efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return a copy of LogRecs as a collection
1438bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1439efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    public final Collection<LogRec> copyLogRecs() {
1440efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        Vector<LogRec> vlr = new Vector<LogRec>();
1441efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1442efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh != null) {
1443efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            for (LogRec lr : smh.mLogRecords.mLogRecVector) {
1444efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                vlr.add(lr);
1445efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            }
1446efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        }
1447efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return vlr;
1448fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1449fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1450fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1451efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Add the string to LogRecords.
1452bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     *
1453bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @param string
1454fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1455efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    protected void addLogRec(String string) {
1456efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1457efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1458efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1459efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.mLogRecords.add(this, smh.getCurrentMessage(), string, smh.getCurrentState(),
1460efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                smh.mStateStack[smh.mStateStackTopIndex].state, smh.mDestState);
1461fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1462fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1463fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1464bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return true if msg should be saved in the log, default is true.
1465fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1466bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected boolean recordLogRec(Message msg) {
1467bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return true;
1468fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1469fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1470fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1471bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Return a string to be logged by LogRec, default
1472bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * is an empty string. Override if additional information is desired.
1473bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     *
1474bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @param msg that was processed
1475bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return information to be logged as a String
1476fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1477bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected String getLogRecString(Message msg) {
1478bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return "";
1479bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1480bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1481bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1482bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return the string for msg.what
1483bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1484bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected String getWhatToString(int what) {
1485bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return null;
1486fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1487fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1488fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1489efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return Handler, maybe null if state machine has quit.
1490fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1491fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final Handler getHandler() {
149264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return mSmHandler;
1493fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1494fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1495fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1496efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler.
1497fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1498efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1499efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1500efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1501efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1502efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1503efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
1504fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1505ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    public final Message obtainMessage() {
150664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler);
1507fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1508fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1509fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1510efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler, what.
1511efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1512efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1513efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1514efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1515efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1516fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1517fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param what is the assigned to Message.what.
1518efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
1519fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1520fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final Message obtainMessage(int what) {
152164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what);
1522fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1523fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1524fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1525efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler,
1526fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * what and obj.
1527fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1528efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1529efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1530efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1531efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1532efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1533fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param what is the assigned to Message.what.
1534fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param obj is assigned to Message.obj.
1535efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
1536fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1537ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    public final Message obtainMessage(int what, Object obj) {
153864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what, obj);
1539fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1540fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
154191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
1542efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler,
154396e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * what, arg1 and arg2
154496e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     *
1545efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1546efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1547efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1548efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1549efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
155096e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param what  is assigned to Message.what
155196e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg1  is assigned to Message.arg1
155296e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg2  is assigned to Message.arg2
1553efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
155496e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     */
1555ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    public final Message obtainMessage(int what, int arg1, int arg2) {
155664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what, arg1, arg2);
155796e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    }
155896e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff
155996e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    /**
1560efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler,
156196e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * what, arg1, arg2 and obj
156296e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     *
1563efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1564efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1565efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1566efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1567efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
156896e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param what  is assigned to Message.what
156996e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg1  is assigned to Message.arg1
157096e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg2  is assigned to Message.arg2
157196e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param obj is assigned to Message.obj
1572efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
157396e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     */
1574ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    public final Message obtainMessage(int what, int arg1, int arg2, Object obj) {
157564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what, arg1, arg2, obj);
157696e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    }
157796e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff
157896e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    /**
157991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine.
1580efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1581efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
158291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
158391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessage(int what) {
1584a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1585efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1586efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1587a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1588efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessage(obtainMessage(what));
158991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
159091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
159191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
159291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine.
1593efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1594efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
159591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
159691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessage(int what, Object obj) {
1597a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1598efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1599efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1600a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1601ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        smh.sendMessage(obtainMessage(what, obj));
160291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
160391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
1604fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1605fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Enqueue a message to this state machine.
1606efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1607efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
1608fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1609fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final void sendMessage(Message msg) {
1610a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1611efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1612efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1613a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1614efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessage(msg);
1615fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1616fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1617fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1618fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Enqueue a message to this state machine after a delay.
1619efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1620efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
1621fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
162291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessageDelayed(int what, long delayMillis) {
1623a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1624efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1625efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1626a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1627efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageDelayed(obtainMessage(what), delayMillis);
162891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
162991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
163091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
163191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine after a delay.
1632efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1633efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
163491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
163591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessageDelayed(int what, Object obj, long delayMillis) {
1636a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1637efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1638efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1639a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1640efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageDelayed(obtainMessage(what, obj), delayMillis);
164191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
164291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
164391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
164491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine after a delay.
1645efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1646efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
164791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
1648fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final void sendMessageDelayed(Message msg, long delayMillis) {
1649a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1650efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1651efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1652a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1653efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageDelayed(msg, delayMillis);
1654fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1655fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1656fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1657fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Enqueue a message to the front of the queue for this state machine.
165864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1659efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1660efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
1661fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
166291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    protected final void sendMessageAtFrontOfQueue(int what, Object obj) {
1663efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1664efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1665efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1666efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1667efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageAtFrontOfQueue(obtainMessage(what, obj));
166891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
166991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
167091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
167191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to the front of the queue for this state machine.
167264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1673efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1674efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
167591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
167691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    protected final void sendMessageAtFrontOfQueue(int what) {
1677efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1678efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1679efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1680efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1681efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageAtFrontOfQueue(obtainMessage(what));
168291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
168391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
168491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
168591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to the front of the queue for this state machine.
168664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1687efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1688efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
168991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
1690fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected final void sendMessageAtFrontOfQueue(Message msg) {
1691efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1692efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1693efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1694efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1695efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageAtFrontOfQueue(msg);
1696fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1697fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1698fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1699aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh     * Removes a message from the message queue.
170064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1701aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh     */
1702aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh    protected final void removeMessages(int what) {
1703efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1704efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1705efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1706efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1707efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.removeMessages(what);
1708efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    }
1709efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1710efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    /**
1711efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Validate that the message was sent by
1712efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * {@link StateMachine#quit} or {@link StateMachine#quitNow}.
1713efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * */
1714efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    protected final boolean isQuit(Message msg) {
1715efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1716efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1717efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return msg.what == SM_QUIT_CMD;
1718efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1719efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.isQuit(msg);
1720aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh    }
1721aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh
1722aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh    /**
1723bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Quit the state machine after all currently queued up messages are processed.
17241b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     */
1725bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected final void quit() {
1726bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        // mSmHandler can be null if the state machine is already stopped.
1727efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1728efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1729a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1730efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.quit();
17311b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    }
17321b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
17331b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    /**
1734bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Quit the state machine immediately all currently queued messages will be discarded.
17351b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     */
1736bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected final void quitNow() {
1737bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        // mSmHandler can be null if the state machine is already stopped.
1738efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1739efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1740583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
1741efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.quitNow();
1742583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    }
1743583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
1744583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    /**
1745fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @return if debugging is enabled
1746fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1747fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public boolean isDbg() {
1748a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1749efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1750efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return false;
1751a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1752efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.isDbg();
1753fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1754fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1755fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1756fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Set debug enable/disabled.
1757fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1758fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param dbg is true to enable debugging.
1759fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1760fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void setDbg(boolean dbg) {
1761a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1762efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1763efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1764a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1765efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.setDbg(dbg);
1766fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1767fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1768fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1769fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Start the state machine.
1770fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1771fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void start() {
1772a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1773efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1774efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1775a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1776fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** Send the complete construction message */
1777efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.completeConstruction();
1778fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1779583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
1780583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    /**
1781583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * Dump the current state.
1782583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     *
1783583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * @param fd
1784583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * @param pw
1785583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * @param args
1786583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     */
1787583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1788583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        pw.println(getName() + ":");
1789bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        pw.println(" total records=" + getLogRecCount());
1790ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        for (int i = 0; i < getLogRecSize(); i++) {
1791efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            pw.printf(" rec[%d]: %s\n", i, getLogRec(i).toString());
1792583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            pw.flush();
1793583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        }
1794583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        pw.println("curState=" + getCurrentState().getName());
1795583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    }
179658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
1797ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
1798ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with debug and add to the LogRecords.
1799ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
1800ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
1801ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
1802ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    protected void logAndAddLogRec(String s) {
1803ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        addLogRec(s);
1804ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        log(s);
1805ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    }
1806ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville
1807ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
1808ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with debug
1809ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
1810ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
1811ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
181258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void log(String s) {
181358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.d(mName, s);
181458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
181558c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
1816ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
1817ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with debug attribute
1818ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
1819ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
1820ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
1821ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    protected void logd(String s) {
1822ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        Log.d(mName, s);
1823ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    }
1824ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville
1825ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
1826ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with verbose attribute
1827ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
1828ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
1829ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
183058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void logv(String s) {
183158c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.v(mName, s);
183258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
183358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
1834ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
1835ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with info attribute
1836ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
1837ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
1838ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
183958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void logi(String s) {
184058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.i(mName, s);
184158c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
184258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
1843ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
1844ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with warning attribute
1845ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
1846ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
1847ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
184858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void logw(String s) {
184958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.w(mName, s);
185058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
185158c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
1852ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
1853ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with error attribute
1854ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
1855ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
1856ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
185758c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void loge(String s) {
185858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.e(mName, s);
185958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
1860ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville
1861ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
1862ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with error attribute
1863ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
1864ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
1865ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param e is a Throwable which logs additional information.
1866ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
1867ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    protected void loge(String s, Throwable e) {
1868ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        Log.e(mName, s, e);
1869ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    }
1870fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
1871