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;
2854b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Savilleimport java.io.StringWriter;
29fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport java.util.ArrayList;
30583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Savilleimport java.util.Calendar;
31efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Savilleimport java.util.Collection;
32c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panickerimport java.util.Iterator;
33fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport java.util.HashMap;
34d3059487abd526b91b912f70939c1c6994eecf52Wink Savilleimport java.util.Vector;
35fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
36fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville/**
37fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * {@hide}
38fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
3964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>The state machine defined here is a hierarchical state machine which processes messages
4033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * and can have states arranged hierarchically.</p>
4158c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville *
4264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>A state is a <code>State</code> object and must implement
4333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <code>processMessage</code> and optionally <code>enter/exit/getName</code>.
44fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * The enter/exit methods are equivalent to the construction and destruction
45fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * in Object Oriented programming and are used to perform initialization and
46fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * cleanup of the state respectively. The <code>getName</code> method returns the
47e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * name of the state; the default implementation returns the class name. It may be
48e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * desirable to have <code>getName</code> return the the state instance name instead,
49e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * in particular if a particular state class has multiple instances.</p>
50fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
51e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * <p>When a state machine is created, <code>addState</code> is used to build the
52fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * hierarchy and <code>setInitialState</code> is used to identify which of these
53fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * is the initial state. After construction the programmer calls <code>start</code>
54cea056f5894543819898a0e62f98dc7870b27758Wink Saville * which initializes and starts the state machine. The first action the StateMachine
55cea056f5894543819898a0e62f98dc7870b27758Wink Saville * is to the invoke <code>enter</code> for all of the initial state's hierarchy,
56cea056f5894543819898a0e62f98dc7870b27758Wink Saville * starting at its eldest parent. The calls to enter will be done in the context
57e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * of the StateMachine's Handler, not in the context of the call to start, and they
58cea056f5894543819898a0e62f98dc7870b27758Wink Saville * will be invoked before any messages are processed. For example, given the simple
59e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * state machine below, mP1.enter will be invoked and then mS1.enter. Finally,
60e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * messages sent to the state machine will be processed by the current state;
61cea056f5894543819898a0e62f98dc7870b27758Wink Saville * in our simple state machine below that would initially be mS1.processMessage.</p>
62e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee<pre>
63fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        mP1
64fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville       /   \
65e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee      mS2   mS1 ----&gt; initial state
66e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee</pre>
6733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>After the state machine is created and started, messages are sent to a state
68a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * machine using <code>sendMessage</code> and the messages are created using
69fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * <code>obtainMessage</code>. When the state machine receives a message the
70fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * current state's <code>processMessage</code> is invoked. In the above example
71fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * mS1.processMessage will be invoked first. The state may use <code>transitionTo</code>
72e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * to change the current state to a new state.</p>
73fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
74e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * <p>Each state in the state machine may have a zero or one parent states. If
75fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * a child state is unable to handle a message it may have the message processed
76e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * by its parent by returning false or NOT_HANDLED. If a message is not handled by
77e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * a child state or any of its ancestors, <code>unhandledMessage</code> will be invoked
78e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * to give one last chance for the state machine to process the message.</p>
79fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
8033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>When all processing is completed a state machine may choose to call
81fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * <code>transitionToHaltingState</code>. When the current <code>processingMessage</code>
82fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * returns the state machine will transfer to an internal <code>HaltingState</code>
83fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * and invoke <code>halting</code>. Any message subsequently received by the state
8433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * machine will cause <code>haltedProcessMessage</code> to be invoked.</p>
85fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
86bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville * <p>If it is desirable to completely stop the state machine call <code>quit</code> or
87efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville * <code>quitNow</code>. These will call <code>exit</code> of the current state and its parents,
88e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * call <code>onQuitting</code> and then exit Thread/Loopers.</p>
891b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville *
9064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>In addition to <code>processMessage</code> each <code>State</code> has
91e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee * an <code>enter</code> method and <code>exit</code> method which may be overridden.</p>
92fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
9333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Since the states are arranged in a hierarchy transitioning to a new state
94fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * causes current states to be exited and new states to be entered. To determine
95fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * the list of states to be entered/exited the common parent closest to
96fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * the current state is found. We then exit from the current state and its
97fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * parent's up to but not including the common parent state and then enter all
98fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * of the new states below the common parent down to the destination state.
99fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * If there is no common parent all states are exited and then the new states
10033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * are entered.</p>
101fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
10233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Two other methods that states can use are <code>deferMessage</code> and
103fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * <code>sendMessageAtFrontOfQueue</code>. The <code>sendMessageAtFrontOfQueue</code> sends
104fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * a message but places it on the front of the queue rather than the back. The
105fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * <code>deferMessage</code> causes the message to be saved on a list until a
106fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * transition is made to a new state. At which time all of the deferred messages
107fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * will be put on the front of the state machine queue with the oldest message
108fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * at the front. These will then be processed by the new current state before
109fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * any other messages that are on the queue or might be added later. Both of
11033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * these are protected and may only be invoked from within a state machine.</p>
111fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
11233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>To illustrate some of these properties we'll use state machine with an 8
11333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * state hierarchy:</p>
114e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee<pre>
115fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville          mP0
116fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         /   \
117fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        mP1   mS0
118fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville       /   \
119fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville      mS2   mS1
120fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     /  \    \
121e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee    mS3  mS4  mS5  ---&gt; initial state
122e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee</pre>
12333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>After starting mS5 the list of active states is mP0, mP1, mS1 and mS5.
124fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * So the order of calling processMessage when a message is received is mS5,
125a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * mS1, mP1, mP0 assuming each processMessage indicates it can't handle this
12633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * message by returning false or NOT_HANDLED.</p>
127fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
12833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Now assume mS5.processMessage receives a message it can handle, and during
129a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * the handling determines the machine should change states. It could call
130a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville * transitionTo(mS4) and return true or HANDLED. Immediately after returning from
131fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * processMessage the state machine runtime will find the common parent,
132fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * which is mP1. It will then call mS5.exit, mS1.exit, mS2.enter and then
133fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * mS4.enter. The new list of active states is mP0, mP1, mS2 and mS4. So
13433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * when the next message is received mS4.processMessage will be invoked.</p>
135fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
13664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>Now for some concrete examples, here is the canonical HelloWorld as a state machine.
13733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * It responds with "Hello World" being printed to the log for every message.</p>
138e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee<pre>
13964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Savilleclass HelloWorld extends StateMachine {
14064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    HelloWorld(String name) {
141fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        super(name);
142fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        addState(mState1);
143fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        setInitialState(mState1);
144fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
145fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
146fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static HelloWorld makeHelloWorld() {
147fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        HelloWorld hw = new HelloWorld("hw");
148fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        hw.start();
149fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        return hw;
150fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
151fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
15264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class State1 extends State {
1530b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
15458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("Hello World");
155a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            return HANDLED;
156fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
157fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
158fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    State1 mState1 = new State1();
159fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
160fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
161fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savillevoid testHelloWorld() {
162fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    HelloWorld hw = makeHelloWorld();
163fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    hw.sendMessage(hw.obtainMessage());
164fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
165e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee</pre>
16633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>A more interesting state machine is one with four states
16733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * with two independent parent states.</p>
168e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee<pre>
169fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        mP1      mP2
170fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville       /   \
171fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville      mS2   mS1
172e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee</pre>
17333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>Here is a description of this state machine using pseudo code.</p>
174e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee <pre>
17533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillestate mP1 {
17633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     enter { log("mP1.enter"); }
17733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     exit { log("mP1.exit");  }
17833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     on msg {
17933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_2 {
18033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             send(CMD_3);
18133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             defer(msg);
182e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee             transitionTo(mS2);
18333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
18433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
18533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         return NOT_HANDLED;
18633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
18733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
18833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville
18933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleINITIAL
19033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillestate mS1 parent mP1 {
19133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     enter { log("mS1.enter"); }
19233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     exit  { log("mS1.exit");  }
19333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     on msg {
19433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_1 {
19533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             transitionTo(mS1);
19633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
19733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
19833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         return NOT_HANDLED;
19933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
20033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
20133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville
20233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillestate mS2 parent mP1 {
20333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     enter { log("mS2.enter"); }
20433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     exit  { log("mS2.exit");  }
20533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     on msg {
20633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_2 {
20733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             send(CMD_4);
20833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
20933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
21033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_3 {
21133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             defer(msg);
21233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             transitionTo(mP2);
21333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
21433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
21533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         return NOT_HANDLED;
21633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
21733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
21833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville
21933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillestate mP2 {
22033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     enter {
22133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         log("mP2.enter");
22233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         send(CMD_5);
22333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
22433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     exit { log("mP2.exit"); }
22533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     on msg {
22633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_3, CMD_4 { return HANDLED; }
22733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         CMD_5 {
22833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             transitionTo(HaltingState);
22933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville             return HANDLED;
23033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         }
23133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville         return NOT_HANDLED;
23233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
23333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
234e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee</pre>
23564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville * <p>The implementation is below and also in StateMachineTest:</p>
236e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee<pre>
23764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Savilleclass Hsm1 extends StateMachine {
238fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_1 = 1;
239fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_2 = 2;
240fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_3 = 3;
241fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_4 = 4;
242fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_5 = 5;
243fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
244fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static Hsm1 makeHsm1() {
24558c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        log("makeHsm1 E");
246fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Hsm1 sm = new Hsm1("hsm1");
247fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        sm.start();
24858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        log("makeHsm1 X");
249fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        return sm;
250fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
251fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
252fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    Hsm1(String name) {
253fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        super(name);
25458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        log("ctor E");
255fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
256fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        // Add states, use indentation to show hierarchy
257fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        addState(mP1);
258fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS1, mP1);
259fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS2, mP1);
260fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        addState(mP2);
261fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
262fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        // Set the initial state
263fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        setInitialState(mS1);
26458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        log("ctor X");
265fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
266fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
26764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class P1 extends State {
2680b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void enter() {
26958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mP1.enter");
270fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
2710b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
272fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            boolean retVal;
27358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mP1.processMessage what=" + message.what);
274fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            switch(message.what) {
275fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case CMD_2:
276fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // CMD_2 will arrive in mS2 before CMD_3
277fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sendMessage(obtainMessage(CMD_3));
278fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                deferMessage(message);
279fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mS2);
280a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = HANDLED;
281fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
282fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            default:
283fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // Any message we don't understand in this state invokes unhandledMessage
284a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = NOT_HANDLED;
285fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
286fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
287fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return retVal;
288fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
2890b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void exit() {
29058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mP1.exit");
291fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
292fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
293fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
29464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class S1 extends State {
2950b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void enter() {
29658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mS1.enter");
297fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
2980b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
29958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("S1.processMessage what=" + message.what);
300fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (message.what == CMD_1) {
301fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // Transition to ourself to show that enter/exit is called
302fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mS1);
303a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                return HANDLED;
304fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } else {
305fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // Let parent process all other messages
306a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                return NOT_HANDLED;
307fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
308fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3090b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void exit() {
31058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mS1.exit");
311fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
312fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
313fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
31464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class S2 extends State {
3150b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void enter() {
31658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mS2.enter");
317fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3180b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
319fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            boolean retVal;
32058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mS2.processMessage what=" + message.what);
321fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            switch(message.what) {
322fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_2):
323fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sendMessage(obtainMessage(CMD_4));
324a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = HANDLED;
325fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
326fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_3):
327fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                deferMessage(message);
328fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mP2);
329a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = HANDLED;
330fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
331fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            default:
332a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                retVal = NOT_HANDLED;
333fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
334fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
335fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return retVal;
336fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3370b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void exit() {
33858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mS2.exit");
339fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
340fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
341fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
34264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class P2 extends State {
3430b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void enter() {
34458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mP2.enter");
345fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            sendMessage(obtainMessage(CMD_5));
346fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3470b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public boolean processMessage(Message message) {
34858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("P2.processMessage what=" + message.what);
349fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            switch(message.what) {
350fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_3):
351fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
352fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_4):
353fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
354fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_5):
355fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionToHaltingState();
356fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
357fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
358a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            return HANDLED;
359fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
3600b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato        &#64;Override public void exit() {
36158c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            log("mP2.exit");
362fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
363fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
364fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
3650b6232da8995d6fa556d55ea2067dab3c1180919Joe Onorato    &#64;Override
366bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    void onHalting() {
36758c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        log("halting");
368fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (this) {
369fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            this.notifyAll();
370fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
371fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
372fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
373fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    P1 mP1 = new P1();
374fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    S1 mS1 = new S1();
375fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    S2 mS2 = new S2();
376fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    P2 mP2 = new P2();
377fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
378e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee</pre>
37933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>If this is executed by sending two messages CMD_1 and CMD_2
38033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * (Note the synchronize is only needed because we use hsm.wait())</p>
381e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee<pre>
38233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleHsm1 hsm = makeHsm1();
38333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Savillesynchronize(hsm) {
38433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     hsm.sendMessage(obtainMessage(hsm.CMD_1));
38533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     hsm.sendMessage(obtainMessage(hsm.CMD_2));
38633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     try {
38733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville          // wait for the messages to be handled
38833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville          hsm.wait();
38933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     } catch (InterruptedException e) {
39058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville          loge("exception while waiting " + e.getMessage());
39133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville     }
39233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville}
393e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee</pre>
39433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink Saville * <p>The output is:</p>
395e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee<pre>
39633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): makeHsm1 E
39733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): ctor E
39833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): ctor X
39933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP1.enter
40033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.enter
40133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): makeHsm1 X
40233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.processMessage what=1
40333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.exit
40433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.enter
40533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.processMessage what=2
40633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP1.processMessage what=2
40733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS1.exit
40833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS2.enter
40933c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS2.processMessage what=2
41033c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS2.processMessage what=3
41133c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mS2.exit
41233c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP1.exit
41333c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.enter
41433c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.processMessage what=3
41533c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.processMessage what=4
41633c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.processMessage what=5
41733c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): mP2.exit
41833c54e3365d621fcc5b9f7564f18b33dc1e300dfWink SavilleD/hsm1    ( 1999): halting
419e318d8c7d1f8ac7885b6b5536673c0d21878ccd9Kevin Cernekee</pre>
420fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville */
42164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Savillepublic class StateMachine {
42258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    // Name of the state machine and used as logging tag
423fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private String mName;
424fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
425a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /** Message.what value when quitting */
426bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    private static final int SM_QUIT_CMD = -1;
4271b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
428a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /** Message.what value when initializing */
429bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    private static final int SM_INIT_CMD = -2;
430a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
431a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /**
432a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * Convenience constant that maybe returned by processMessage
433a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * to indicate the the message was processed and is not to be
434a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * processed by parent states
435a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     */
436a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    public static final boolean HANDLED = true;
437a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
438a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /**
439a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * Convenience constant that maybe returned by processMessage
440a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * to indicate the the message was NOT processed and is to be
441a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     * processed by parent states
442a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville     */
443a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    public static final boolean NOT_HANDLED = false;
444a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
445d3059487abd526b91b912f70939c1c6994eecf52Wink Saville    /**
446bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * StateMachine logging record.
447d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * {@hide}
448d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     */
449bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public static class LogRec {
450efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        private StateMachine mSm;
451583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        private long mTime;
452583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        private int mWhat;
453583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        private String mInfo;
454efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        private IState mState;
455efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        private IState mOrgState;
456efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        private IState mDstState;
457d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
458d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
459d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * Constructor
460bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         *
461bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @param msg
462ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * @param state the state which handled the message
463d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param orgState is the first state the received the message but
464d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * did not processes the message.
465ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * @param transToState is the state that was transitioned to after the message was
466ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * processed.
467d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
468efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        LogRec(StateMachine sm, Message msg, String info, IState state, IState orgState,
469efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                IState transToState) {
470efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            update(sm, msg, info, state, orgState, transToState);
471d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
472d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
473d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
474d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * Update the information in the record.
475d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param state that handled the message
476efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville         * @param orgState is the first state the received the message
477efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville         * @param dstState is the state that was the transition target when logging
478d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
479efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        public void update(StateMachine sm, Message msg, String info, IState state, IState orgState,
480efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                IState dstState) {
481efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            mSm = sm;
482583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            mTime = System.currentTimeMillis();
483bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            mWhat = (msg != null) ? msg.what : 0;
484583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            mInfo = info;
485583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            mState = state;
486583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            mOrgState = orgState;
487efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            mDstState = dstState;
488583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        }
489583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
490583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        /**
491583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @return time stamp
492583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         */
493583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        public long getTime() {
494583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return mTime;
495583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        }
496583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
497583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        /**
498583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @return msg.what
499583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         */
500583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        public long getWhat() {
501583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return mWhat;
502d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
503d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
504d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
505d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @return the command that was executing
506d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
507583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville        public String getInfo() {
508583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return mInfo;
509d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
510d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
511d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
512d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @return the state that handled this message
513d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
514efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        public IState getState() {
515583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return mState;
516d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
517d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
518d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
519efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville         * @return the state destination state if a transition is occurring or null if none.
520d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
521efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        public IState getDestState() {
522efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            return mDstState;
523d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
524d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
525d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
526efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville         * @return the original state that received the message.
527d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
528efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        public IState getOriginalState() {
529efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            return mOrgState;
530efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        }
531efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
532efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        @Override
533efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        public String toString() {
534d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            StringBuilder sb = new StringBuilder();
535583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append("time=");
536583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            Calendar c = Calendar.getInstance();
537583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            c.setTimeInMillis(mTime);
538583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
539ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            sb.append(" processed=");
540583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append(mState == null ? "<null>" : mState.getName());
541ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            sb.append(" org=");
542583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append(mOrgState == null ? "<null>" : mOrgState.getName());
543ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            sb.append(" dest=");
544efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            sb.append(mDstState == null ? "<null>" : mDstState.getName());
545583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            sb.append(" what=");
546efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            String what = mSm != null ? mSm.getWhatToString(mWhat) : "";
547bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            if (TextUtils.isEmpty(what)) {
548bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append(mWhat);
549bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append("(0x");
550bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append(Integer.toHexString(mWhat));
551bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append(")");
552bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            } else {
553bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                sb.append(what);
554bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            }
555ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            if (!TextUtils.isEmpty(mInfo)) {
556583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville                sb.append(" ");
557583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville                sb.append(mInfo);
558d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
559583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville            return sb.toString();
560d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
561d3059487abd526b91b912f70939c1c6994eecf52Wink Saville    }
562d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
563d3059487abd526b91b912f70939c1c6994eecf52Wink Saville    /**
564bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * A list of log records including messages recently processed by the state machine.
565d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     *
566bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * The class maintains a list of log records including messages
567d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * recently processed. The list is finite and may be set in the
568d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * constructor or by calling setSize. The public interface also
569bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * includes size which returns the number of recent records,
570bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * count which is the number of records processed since the
571bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * the last setSize, get which returns a record and
572bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * add which adds a record.
573d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     */
574bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    private static class LogRecords {
575d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
576d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        private static final int DEFAULT_SIZE = 20;
577d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
578ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        private Vector<LogRec> mLogRecVector = new Vector<LogRec>();
579d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        private int mMaxSize = DEFAULT_SIZE;
580d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        private int mOldestIndex = 0;
581d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        private int mCount = 0;
582ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        private boolean mLogOnlyTransitions = false;
583d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
584d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
585583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * private constructor use add
586d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
587bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        private LogRecords() {
588d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
589d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
590d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
591bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * Set size of messages to maintain and clears all current records.
592d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         *
593bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @param maxSize number of records to maintain at anyone time.
594d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        */
595bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized void setSize(int maxSize) {
5962326e9b21c4a332e00f9709606089a1e6d0e11ebSamuel Tan            // TODO: once b/28217358 is fixed, add unit tests  to verify that these variables are
5972326e9b21c4a332e00f9709606089a1e6d0e11ebSamuel Tan            // cleared after calling this method, and that subsequent calls to get() function as
5982326e9b21c4a332e00f9709606089a1e6d0e11ebSamuel Tan            // expected.
599d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            mMaxSize = maxSize;
6002326e9b21c4a332e00f9709606089a1e6d0e11ebSamuel Tan            mOldestIndex = 0;
601d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            mCount = 0;
602ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            mLogRecVector.clear();
603ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        }
604ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
605ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        synchronized void setLogOnlyTransitions(boolean enable) {
606ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            mLogOnlyTransitions = enable;
607ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        }
608ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
609ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        synchronized boolean logOnlyTransitions() {
610ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            return mLogOnlyTransitions;
611d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
612d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
613d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
614bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @return the number of recent records.
615d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
616bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized int size() {
617ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            return mLogRecVector.size();
618d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
619d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
620d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
621bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @return the total number of records processed since size was set.
622d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
623bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized int count() {
624d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            return mCount;
625d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
626d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
627d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
628bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * Clear the list of records.
6296f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh         */
630bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized void cleanup() {
631ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            mLogRecVector.clear();
6326f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        }
6336f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh
6346f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        /**
635d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @return the information on a particular record. 0 is the oldest
636d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * record and size()-1 is the newest record. If the index is to
637d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * large null is returned.
638d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
639bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized LogRec get(int index) {
640d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            int nextIndex = mOldestIndex + index;
641d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            if (nextIndex >= mMaxSize) {
642d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                nextIndex -= mMaxSize;
643d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
644d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            if (nextIndex >= size()) {
645d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                return null;
646d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            } else {
647ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff                return mLogRecVector.get(nextIndex);
648d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
649d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
650d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
651d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
652d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * Add a processed message.
653d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         *
654583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @param msg
655583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @param messageInfo to be stored
656d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param state that handled the message
657d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param orgState is the first state the received the message but
658d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * did not processes the message.
659ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * @param transToState is the state that was transitioned to after the message was
660ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * processed.
661ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         *
662d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
663efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        synchronized void add(StateMachine sm, Message msg, String messageInfo, IState state,
664ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                IState orgState, IState transToState) {
665d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            mCount += 1;
666ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            if (mLogRecVector.size() < mMaxSize) {
667efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                mLogRecVector.add(new LogRec(sm, msg, messageInfo, state, orgState, transToState));
668d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            } else {
669ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff                LogRec pmi = mLogRecVector.get(mOldestIndex);
670d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                mOldestIndex += 1;
671d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                if (mOldestIndex >= mMaxSize) {
672d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                    mOldestIndex = 0;
673d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                }
674efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                pmi.update(sm, msg, messageInfo, state, orgState, transToState);
675d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
676d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
677d3059487abd526b91b912f70939c1c6994eecf52Wink Saville    }
678d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
67964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private static class SmHandler extends Handler {
680fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
68103812c7894bd51ffc27aece5933791e4a00d679bWink Saville        /** true if StateMachine has quit */
68203812c7894bd51ffc27aece5933791e4a00d679bWink Saville        private boolean mHasQuit = false;
68303812c7894bd51ffc27aece5933791e4a00d679bWink Saville
684fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The debug flag */
685fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private boolean mDbg = false;
686fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
687cea056f5894543819898a0e62f98dc7870b27758Wink Saville        /** The SmHandler object, identifies that message is internal */
688cea056f5894543819898a0e62f98dc7870b27758Wink Saville        private static final Object mSmHandlerObj = new Object();
6891b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
690a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        /** The current message */
691a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        private Message mMsg;
692a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
693bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        /** A list of log records including messages this state machine has processed */
694bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        private LogRecords mLogRecords = new LogRecords();
695fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
696fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** true if construction of the state machine has not been completed */
697fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private boolean mIsConstructionCompleted;
698fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
699fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** Stack used to manage the current hierarchy of states */
700fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateInfo mStateStack[];
701fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
702fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** Top of mStateStack */
703fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mStateStackTopIndex = -1;
704fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
705fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** A temporary stack used to manage the state stack */
706fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateInfo mTempStateStack[];
707fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
708fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The top of the mTempStateStack */
709fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mTempStateStackCount;
710fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
711fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** State used when state machine is halted */
712fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private HaltingState mHaltingState = new HaltingState();
713fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
7141b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        /** State used when state machine is quitting */
7151b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private QuittingState mQuittingState = new QuittingState();
7161b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
71764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** Reference to the StateMachine */
71864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private StateMachine mSm;
719fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
720fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
721fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Information about a state.
722fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Used to maintain the hierarchy.
723fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
724fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private class StateInfo {
725fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /** The state */
72664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            State state;
727fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
728fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /** The parent of this state, null if there is no parent */
729fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo parentStateInfo;
730fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
731fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /** True when the state has been entered and on the stack */
732fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            boolean active;
733fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
734fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
735fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * Convert StateInfo to string
736fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
737fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override
738fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            public String toString() {
739ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                return "state=" + state.getName() + ",active=" + active + ",parent="
740ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + ((parentStateInfo == null) ? "null" : parentStateInfo.state.getName());
741fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
742fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
743fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
744fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The map of all of the states in the state machine */
745ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        private HashMap<State, StateInfo> mStateInfo = new HashMap<State, StateInfo>();
746fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
747fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The initial state that will process the first message */
74864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private State mInitialState;
749fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
750fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The destination state when transitionTo has been invoked */
75164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private State mDestState;
752fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
753fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The list of deferred messages */
754fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ArrayList<Message> mDeferredMessages = new ArrayList<Message>();
755fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
756fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
757fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * State entered when transitionToHaltingState is called.
758fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
75964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private class HaltingState extends State {
760fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override
761fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            public boolean processMessage(Message msg) {
76264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville                mSm.haltedProcessMessage(msg);
763fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
764fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
765fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
766fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
767fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
7681b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville         * State entered when a valid quit message is handled.
7691b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville         */
77064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private class QuittingState extends State {
7711b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            @Override
7721b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            public boolean processMessage(Message msg) {
773a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                return NOT_HANDLED;
7741b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            }
7751b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
7761b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
7771b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        /**
778fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Handle messages sent to the state machine by calling
779fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * the current state's processMessage. It also handles
780fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * the enter/exit calls and placing any deferred messages
781fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * back onto the queue when transitioning to a new state.
782fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
783fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
784fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        public final void handleMessage(Message msg) {
78503812c7894bd51ffc27aece5933791e4a00d679bWink Saville            if (!mHasQuit) {
78674d7d0f10bccb42a879632baf22d0da61baf0ecbHall Liu                if (mSm != null && msg.what != SM_INIT_CMD && msg.what != SM_QUIT_CMD) {
787355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger                    mSm.onPreHandleMessage(msg);
788355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger                }
789355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger
79003812c7894bd51ffc27aece5933791e4a00d679bWink Saville                if (mDbg) mSm.log("handleMessage: E msg.what=" + msg.what);
79103812c7894bd51ffc27aece5933791e4a00d679bWink Saville
79203812c7894bd51ffc27aece5933791e4a00d679bWink Saville                /** Save the current message */
79303812c7894bd51ffc27aece5933791e4a00d679bWink Saville                mMsg = msg;
79403812c7894bd51ffc27aece5933791e4a00d679bWink Saville
79503812c7894bd51ffc27aece5933791e4a00d679bWink Saville                /** State that processed the message */
79603812c7894bd51ffc27aece5933791e4a00d679bWink Saville                State msgProcessedState = null;
79703812c7894bd51ffc27aece5933791e4a00d679bWink Saville                if (mIsConstructionCompleted) {
79803812c7894bd51ffc27aece5933791e4a00d679bWink Saville                    /** Normal path */
79903812c7894bd51ffc27aece5933791e4a00d679bWink Saville                    msgProcessedState = processMsg(msg);
80003812c7894bd51ffc27aece5933791e4a00d679bWink Saville                } else if (!mIsConstructionCompleted && (mMsg.what == SM_INIT_CMD)
80103812c7894bd51ffc27aece5933791e4a00d679bWink Saville                        && (mMsg.obj == mSmHandlerObj)) {
80203812c7894bd51ffc27aece5933791e4a00d679bWink Saville                    /** Initial one time path. */
80303812c7894bd51ffc27aece5933791e4a00d679bWink Saville                    mIsConstructionCompleted = true;
80403812c7894bd51ffc27aece5933791e4a00d679bWink Saville                    invokeEnterMethods(0);
80503812c7894bd51ffc27aece5933791e4a00d679bWink Saville                } else {
80603812c7894bd51ffc27aece5933791e4a00d679bWink Saville                    throw new RuntimeException("StateMachine.handleMessage: "
80703812c7894bd51ffc27aece5933791e4a00d679bWink Saville                            + "The start method not called, received msg: " + msg);
80803812c7894bd51ffc27aece5933791e4a00d679bWink Saville                }
80903812c7894bd51ffc27aece5933791e4a00d679bWink Saville                performTransitions(msgProcessedState, msg);
810fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
81103812c7894bd51ffc27aece5933791e4a00d679bWink Saville                // We need to check if mSm == null here as we could be quitting.
81203812c7894bd51ffc27aece5933791e4a00d679bWink Saville                if (mDbg && mSm != null) mSm.log("handleMessage: X");
813355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger
81474d7d0f10bccb42a879632baf22d0da61baf0ecbHall Liu                if (mSm != null && msg.what != SM_INIT_CMD && msg.what != SM_QUIT_CMD) {
815355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger                    mSm.onPostHandleMessage(msg);
816355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger                }
81703812c7894bd51ffc27aece5933791e4a00d679bWink Saville            }
818e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville        }
819e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville
820e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville        /**
821e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville         * Do any transitions
822ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * @param msgProcessedState is the state that processed the message
823e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville         */
824efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        private void performTransitions(State msgProcessedState, Message msg) {
825fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
826fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * If transitionTo has been called, exit and then enter
827e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * the appropriate states. We loop on this to allow
828e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * enter and exit methods to use transitionTo.
829fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
830ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            State orgState = mStateStack[mStateStackTopIndex].state;
831ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
832efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            /**
833efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville             * Record whether message needs to be logged before we transition and
834efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville             * and we won't log special messages SM_INIT_CMD or SM_QUIT_CMD which
835efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville             * always set msg.obj to the handler.
836efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville             */
837f643069ad56763732a06ab601cea1272e4c1827aWink Saville            boolean recordLogMsg = mSm.recordLogRec(mMsg) && (msg.obj != mSmHandlerObj);
838ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
839efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            if (mLogRecords.logOnlyTransitions()) {
840efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                /** Record only if there is a transition */
841efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                if (mDestState != null) {
842efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState,
843efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                            orgState, mDestState);
844efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                }
845efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            } else if (recordLogMsg) {
846efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                /** Record message */
847ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState, orgState,
848ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        mDestState);
849efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            }
850fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
851efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            State destState = mDestState;
852efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            if (destState != null) {
853fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                /**
854efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                 * Process the transitions including transitions in the enter/exit methods
855e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                 */
856efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                while (true) {
857efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    if (mDbg) mSm.log("handleMessage: new destination call exit/enter");
858e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville
859efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    /**
860efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * Determine the states to exit and enter and return the
861efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * common ancestor state of the enter/exit states. Then
862efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * invoke the exit methods then the enter methods.
863efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     */
864efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
865efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    invokeExitMethods(commonStateInfo);
866efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    int stateStackEnteringIndex = moveTempStateStackToStateStack();
867efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    invokeEnterMethods(stateStackEnteringIndex);
868fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
869efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    /**
870efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * Since we have transitioned to a new state we need to have
871efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * any deferred messages moved to the front of the message queue
872efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * so they will be processed before any other messages in the
873efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * message queue.
874efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     */
875efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    moveDeferredMessageAtFrontOfQueue();
876efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
877efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    if (destState != mDestState) {
878efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                        // A new mDestState so continue looping
879efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                        destState = mDestState;
880efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    } else {
881efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                        // No change in mDestState so we're done
882efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                        break;
883efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    }
884efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                }
885efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                mDestState = null;
886e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            }
887fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
888e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            /**
889e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * After processing all transitions check and
890e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * see if the last transition was to quit or halt.
891e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             */
892e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            if (destState != null) {
893e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                if (destState == mQuittingState) {
894bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    /**
895bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     * Call onQuitting to let subclasses cleanup.
896bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     */
897bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    mSm.onQuitting();
8986f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                    cleanupAfterQuitting();
899e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                } else if (destState == mHaltingState) {
900e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                    /**
901bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     * Call onHalting() if we've transitioned to the halting
902e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                     * state. All subsequent messages will be processed in
903e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                     * in the halting state which invokes haltedProcessMessage(msg);
904e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                     */
905bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    mSm.onHalting();
906fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
907fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
908fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
909fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
910fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
9116f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh         * Cleanup all the static variables and the looper after the SM has been quit.
9126f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh         */
9136f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        private final void cleanupAfterQuitting() {
9146f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            if (mSm.mSmThread != null) {
9156f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                // If we made the thread then quit looper which stops the thread.
9166f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                getLooper().quit();
9176f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                mSm.mSmThread = null;
9186f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            }
9196f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh
9206f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mSm.mSmHandler = null;
9216f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mSm = null;
9226f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mMsg = null;
923bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            mLogRecords.cleanup();
9246f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mStateStack = null;
9256f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mTempStateStack = null;
9266f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mStateInfo.clear();
9276f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mInitialState = null;
9286f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mDestState = null;
9296f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mDeferredMessages.clear();
93003812c7894bd51ffc27aece5933791e4a00d679bWink Saville            mHasQuit = true;
9316f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        }
9326f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh
9336f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        /**
934fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Complete the construction of the state machine.
935fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
936fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void completeConstruction() {
93758c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("completeConstruction: E");
938fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
939fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
940fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * Determine the maximum depth of the state hierarchy
941fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * so we can allocate the state stacks.
942fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
943fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int maxDepth = 0;
944fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (StateInfo si : mStateInfo.values()) {
945fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                int depth = 0;
946fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                for (StateInfo i = si; i != null; depth++) {
947fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    i = i.parentStateInfo;
948fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
949fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (maxDepth < depth) {
950fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    maxDepth = depth;
951fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
952fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
95358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("completeConstruction: maxDepth=" + maxDepth);
954fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
955fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mStateStack = new StateInfo[maxDepth];
956fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mTempStateStack = new StateInfo[maxDepth];
957fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setupInitialStateStack();
958fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
959cea056f5894543819898a0e62f98dc7870b27758Wink Saville            /** Sending SM_INIT_CMD message to invoke enter methods asynchronously */
960cea056f5894543819898a0e62f98dc7870b27758Wink Saville            sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));
961e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville
96258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("completeConstruction: X");
963fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
964fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
965fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
966fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Process the message. If the current state doesn't handle
967fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * it, call the states parent and so on. If it is never handled then
968fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * call the state machines unhandledMessage method.
969ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * @return the state that processed the message
970fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
971ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        private final State processMsg(Message msg) {
972fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
973fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
97458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                mSm.log("processMsg: " + curStateInfo.state.getName());
975fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
976bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
977bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            if (isQuit(msg)) {
978bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                transitionTo(mQuittingState);
979bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            } else {
980bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                while (!curStateInfo.state.processMessage(msg)) {
981fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    /**
982bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     * Not processed
983fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                     */
984bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    curStateInfo = curStateInfo.parentStateInfo;
985bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    if (curStateInfo == null) {
986bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        /**
987bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                         * No parents left so it's not handled
988bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                         */
989bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        mSm.unhandledMessage(msg);
990bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        break;
991bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    }
992bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    if (mDbg) {
99358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                        mSm.log("processMsg: " + curStateInfo.state.getName());
9941b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                    }
995fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
996ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            }
997ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            return (curStateInfo != null) ? curStateInfo.state : null;
998fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
999fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1000fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1001fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Call the exit method for each state from the top of stack
1002fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * up to the common ancestor state.
1003fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1004fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void invokeExitMethods(StateInfo commonStateInfo) {
1005ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            while ((mStateStackTopIndex >= 0)
1006ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                    && (mStateStack[mStateStackTopIndex] != commonStateInfo)) {
100764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville                State curState = mStateStack[mStateStackTopIndex].state;
100858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                if (mDbg) mSm.log("invokeExitMethods: " + curState.getName());
1009fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                curState.exit();
1010fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[mStateStackTopIndex].active = false;
1011fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStackTopIndex -= 1;
1012fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1013fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1014fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1015fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1016fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Invoke the enter method starting at the entering index to top of state stack
1017fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1018fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void invokeEnterMethods(int stateStackEnteringIndex) {
1019fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
102058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                if (mDbg) mSm.log("invokeEnterMethods: " + mStateStack[i].state.getName());
1021fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[i].state.enter();
1022fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[i].active = true;
1023fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1024fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1025fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1026fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1027fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Move the deferred message to the front of the message queue.
1028fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1029fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void moveDeferredMessageAtFrontOfQueue() {
1030fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
1031fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * The oldest messages on the deferred list must be at
1032fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * the front of the queue so start at the back, which
1033fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * as the most resent message and end with the oldest
1034fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * messages at the front of the queue.
1035fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
1036ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            for (int i = mDeferredMessages.size() - 1; i >= 0; i--) {
1037fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Message curMsg = mDeferredMessages.get(i);
103858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                if (mDbg) mSm.log("moveDeferredMessageAtFrontOfQueue; what=" + curMsg.what);
1039fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sendMessageAtFrontOfQueue(curMsg);
1040fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1041fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mDeferredMessages.clear();
1042fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1043fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1044fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1045fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Move the contents of the temporary stack to the state stack
1046fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * reversing the order of the items on the temporary stack as
1047fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * they are moved.
1048fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
104964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville         * @return index into mStateStack where entering needs to start
1050fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1051fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final int moveTempStateStackToStateStack() {
1052fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int startingIndex = mStateStackTopIndex + 1;
1053fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int i = mTempStateStackCount - 1;
1054fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int j = startingIndex;
1055fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            while (i >= 0) {
105658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                if (mDbg) mSm.log("moveTempStackToStateStack: i=" + i + ",j=" + j);
1057fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[j] = mTempStateStack[i];
1058fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                j += 1;
1059fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                i -= 1;
1060fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1061fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1062fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mStateStackTopIndex = j - 1;
1063fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
1064ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                mSm.log("moveTempStackToStateStack: X mStateStackTop=" + mStateStackTopIndex
1065ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + ",startingIndex=" + startingIndex + ",Top="
1066ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + mStateStack[mStateStackTopIndex].state.getName());
1067fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1068fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return startingIndex;
1069fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1070fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1071fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1072fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Setup the mTempStateStack with the states we are going to enter.
1073fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1074fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * This is found by searching up the destState's ancestors for a
1075fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * state that is already active i.e. StateInfo.active == true.
1076fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * The destStae and all of its inactive parents will be on the
1077fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * TempStateStack as the list of states to enter.
1078fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1079fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @return StateInfo of the common ancestor for the destState and
1080fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * current state or null if there is no common parent.
1081fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
108264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final StateInfo setupTempStateStackWithStatesToEnter(State destState) {
1083fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
1084fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * Search up the parent list of the destination state for an active
1085fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * state. Use a do while() loop as the destState must always be entered
1086fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * even if it is active. This can happen if we are exiting/entering
1087fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * the current state.
1088fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
1089fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mTempStateStackCount = 0;
1090fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo curStateInfo = mStateInfo.get(destState);
1091fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            do {
1092fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mTempStateStack[mTempStateStackCount++] = curStateInfo;
1093fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                curStateInfo = curStateInfo.parentStateInfo;
1094fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } while ((curStateInfo != null) && !curStateInfo.active);
1095fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1096fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
109758c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                mSm.log("setupTempStateStackWithStatesToEnter: X mTempStateStackCount="
1098ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + mTempStateStackCount + ",curStateInfo: " + curStateInfo);
1099fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1100fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return curStateInfo;
1101fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1102fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1103fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1104fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Initialize StateStack to mInitialState.
1105fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1106fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void setupInitialStateStack() {
1107fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
1108ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                mSm.log("setupInitialStateStack: E mInitialState=" + mInitialState.getName());
1109fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1110fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1111fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo curStateInfo = mStateInfo.get(mInitialState);
1112fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {
1113fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mTempStateStack[mTempStateStackCount] = curStateInfo;
1114fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                curStateInfo = curStateInfo.parentStateInfo;
1115fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1116fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1117fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Empty the StateStack
1118fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mStateStackTopIndex = -1;
1119fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1120fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            moveTempStateStackToStateStack();
1121fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1122fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1123fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1124a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville         * @return current message
1125a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville         */
1126a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        private final Message getCurrentMessage() {
1127a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            return mMsg;
1128a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        }
1129a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
1130a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        /**
1131fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @return current state
1132fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
113364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final IState getCurrentState() {
1134fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return mStateStack[mStateStackTopIndex].state;
1135fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1136fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1137fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1138fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Add a new state to the state machine. Bottom up addition
1139fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * of states is allowed but the same state may only exist
1140fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * in one hierarchy.
1141fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1142fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @param state the state to add
1143fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @param parent the parent of state
1144fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @return stateInfo for this state
1145fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
114664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final StateInfo addState(State state, State parent) {
1147fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
1148ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                mSm.log("addStateInternal: E state=" + state.getName() + ",parent="
1149ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + ((parent == null) ? "" : parent.getName()));
1150fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1151fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo parentStateInfo = null;
1152fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (parent != null) {
1153fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                parentStateInfo = mStateInfo.get(parent);
1154fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (parentStateInfo == null) {
1155fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    // Recursively add our parent as it's not been added yet.
1156fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    parentStateInfo = addState(parent, null);
1157fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
1158fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1159fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo stateInfo = mStateInfo.get(state);
1160fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (stateInfo == null) {
1161fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                stateInfo = new StateInfo();
1162fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateInfo.put(state, stateInfo);
1163fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1164fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1165fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Validate that we aren't adding the same state in two different hierarchies.
1166ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            if ((stateInfo.parentStateInfo != null)
1167ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                    && (stateInfo.parentStateInfo != parentStateInfo)) {
1168ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                throw new RuntimeException("state already added");
1169fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1170fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            stateInfo.state = state;
1171fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            stateInfo.parentStateInfo = parentStateInfo;
1172fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            stateInfo.active = false;
117358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("addStateInternal: X stateInfo: " + stateInfo);
1174fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return stateInfo;
1175fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1176fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1177fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1178fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Constructor
1179fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1180fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @param looper for dispatching messages
118164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville         * @param sm the hierarchical state machine
1182fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
118364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private SmHandler(Looper looper, StateMachine sm) {
1184fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            super(looper);
118564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            mSm = sm;
1186fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1187fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mHaltingState, null);
11881b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            addState(mQuittingState, null);
1189fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1190fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
119164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#setInitialState(State) */
119264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final void setInitialState(State initialState) {
119358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("setInitialState: initialState=" + initialState.getName());
1194fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mInitialState = initialState;
1195fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1196fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
119764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#transitionTo(IState) */
119864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final void transitionTo(IState destState) {
119964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            mDestState = (State) destState;
120058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("transitionTo: destState=" + mDestState.getName());
1201fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1202fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
120364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#deferMessage(Message) */
1204fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void deferMessage(Message msg) {
120558c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("deferMessage: msg=" + msg.what);
1206fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1207fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /* Copy the "msg" to "newMsg" as "msg" will be recycled */
1208fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Message newMsg = obtainMessage();
1209fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            newMsg.copyFrom(msg);
1210fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1211fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mDeferredMessages.add(newMsg);
1212fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1213fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1214bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        /** @see StateMachine#quit() */
12151b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private final void quit() {
121658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("quit:");
1217cea056f5894543819898a0e62f98dc7870b27758Wink Saville            sendMessage(obtainMessage(SM_QUIT_CMD, mSmHandlerObj));
12181b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
12191b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1220bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        /** @see StateMachine#quitNow() */
1221bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        private final void quitNow() {
122258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("quitNow:");
1223bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            sendMessageAtFrontOfQueue(obtainMessage(SM_QUIT_CMD, mSmHandlerObj));
1224bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        }
1225bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
122658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        /** Validate that the message was sent by quit or quitNow. */
12271b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private final boolean isQuit(Message msg) {
1228cea056f5894543819898a0e62f98dc7870b27758Wink Saville            return (msg.what == SM_QUIT_CMD) && (msg.obj == mSmHandlerObj);
12291b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
12301b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
123164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#isDbg() */
1232fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final boolean isDbg() {
1233fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return mDbg;
1234fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1235fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
123664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#setDbg(boolean) */
1237fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void setDbg(boolean dbg) {
1238fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mDbg = dbg;
1239fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1240fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1241fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1242fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
124364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private SmHandler mSmHandler;
124464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private HandlerThread mSmThread;
1245fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1246fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1247fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Initialize.
1248fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1249fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param looper for this state machine
1250fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param name of the state machine
1251fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1252f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville    private void initStateMachine(String name, Looper looper) {
1253fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        mName = name;
125464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler = new SmHandler(looper, this);
1255fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1256fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1257fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
125864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Constructor creates a StateMachine with its own thread.
1259fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1260fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param name of the state machine
1261fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
126264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected StateMachine(String name) {
126364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmThread = new HandlerThread(name);
126464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmThread.start();
126564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        Looper looper = mSmThread.getLooper();
1266fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1267f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville        initStateMachine(name, looper);
1268fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1269fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1270fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1271f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa     * Constructor creates a StateMachine using the looper.
1272fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1273fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param name of the state machine
1274fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
127564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected StateMachine(String name, Looper looper) {
1276f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville        initStateMachine(name, looper);
1277fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1278fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1279fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
128024d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville     * Constructor creates a StateMachine using the handler.
128124d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville     *
128224d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville     * @param name of the state machine
128324d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville     */
128424d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville    protected StateMachine(String name, Handler handler) {
128524d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville        initStateMachine(name, handler.getLooper());
128624d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville    }
128724d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville
128824d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville    /**
12890c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     * Notifies subclass that the StateMachine handler is about to process the Message msg
12900c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     * @param msg The message that is being handled
12910c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     */
12920c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger    protected void onPreHandleMessage(Message msg) {
12930c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger    }
12940c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger
12950c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger    /**
12960c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     * Notifies subclass that the StateMachine handler has finished processing the Message msg and
12970c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     * has possibly transitioned to a new state.
12980c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     * @param msg The message that is being handled
12990c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     */
13000c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger    protected void onPostHandleMessage(Message msg) {
13010c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger    }
13020c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger
13030c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger    /**
1304fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Add a new state to the state machine
1305fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param state the state to add
1306fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param parent the parent of state
1307fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
130864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void addState(State state, State parent) {
130964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.addState(state, parent);
1310fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1311a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
1312a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /**
1313fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Add a new state to the state machine, parent will be null
1314fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param state to add
1315fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
131664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void addState(State state) {
131764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.addState(state, null);
1318fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1319fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1320fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1321fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Set the initial state. This must be invoked before
1322fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * and messages are sent to the state machine.
1323fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1324fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param initialState is the state which will receive the first message.
1325fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
132664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void setInitialState(State initialState) {
132764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.setInitialState(initialState);
1328fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1329fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1330fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1331efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return current message
1332efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     */
1333efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    protected final Message getCurrentMessage() {
1334efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1335efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1336efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return null;
1337efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.getCurrentMessage();
1338efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    }
1339efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1340efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    /**
1341efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return current state
1342efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     */
1343efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    protected final IState getCurrentState() {
1344efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1345efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1346efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return null;
1347efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.getCurrentState();
1348efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    }
1349efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1350efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    /**
1351fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * transition to destination state. Upon returning
1352fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * from processMessage the current state's exit will
1353fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * be executed and upon the next message arriving
1354fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * destState.enter will be invoked.
1355fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1356d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * this function can also be called inside the enter function of the
1357d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * previous transition target, but the behavior is undefined when it is
1358d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * called mid-way through a previous transition (for example, calling this
1359d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * in the enter() routine of a intermediate node when the current transition
1360d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * target is one of the nodes descendants).
1361d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     *
1362fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param destState will be the state that receives the next message.
1363fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
136464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void transitionTo(IState destState) {
136564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.transitionTo(destState);
1366fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1367fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1368fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1369fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * transition to halt state. Upon returning
1370fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * from processMessage we will exit all current
1371bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * states, execute the onHalting() method and then
1372bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * for all subsequent messages haltedProcessMessage
1373fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * will be called.
1374fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1375fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected final void transitionToHaltingState() {
137664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.transitionTo(mSmHandler.mHaltingState);
1377fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1378fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1379fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1380fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Defer this message until next state transition.
1381fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Upon transitioning all deferred messages will be
1382fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * placed on the queue and reprocessed in the original
1383fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * order. (i.e. The next state the oldest messages will
1384fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * be processed first)
1385fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1386fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param msg is deferred until the next transition.
1387fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1388fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected final void deferMessage(Message msg) {
138964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.deferMessage(msg);
1390fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1391fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1392fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1393fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Called when message wasn't handled
1394fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1395fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param msg that couldn't be handled.
1396fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1397fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected void unhandledMessage(Message msg) {
139858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        if (mSmHandler.mDbg) loge(" - unhandledMessage: msg.what=" + msg.what);
1399fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1400fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1401fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1402fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Called for any message that is received after
1403fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * transitionToHalting is called.
1404fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1405fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected void haltedProcessMessage(Message msg) {
1406fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1407fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1408fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1409d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * This will be called once after handling a message that called
1410d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * transitionToHalting. All subsequent messages will invoke
141164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * {@link StateMachine#haltedProcessMessage(Message)}
1412fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1413bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected void onHalting() {
1414fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1415fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1416fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1417d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * This will be called once after a quit message that was NOT handled by
141864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * the derived StateMachine. The StateMachine will stop and any subsequent messages will be
141964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * ignored. In addition, if this StateMachine created the thread, the thread will
1420d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * be stopped after this method returns.
14211b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     */
1422bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected void onQuitting() {
14231b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    }
14241b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
14251b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    /**
1426fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @return the name
1427fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1428fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final String getName() {
1429fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        return mName;
1430fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1431fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1432fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1433bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Set number of log records to maintain and clears all current records.
1434fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1435fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param maxSize number of messages to maintain at anyone time.
1436fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1437bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final void setLogRecSize(int maxSize) {
1438bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        mSmHandler.mLogRecords.setSize(maxSize);
1439bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1440bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1441bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1442ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff     * Set to log only messages that cause a state transition
1443ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff     *
1444ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff     * @param enable {@code true} to enable, {@code false} to disable
1445ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff     */
1446ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff    public final void setLogOnlyTransitions(boolean enable) {
1447ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        mSmHandler.mLogRecords.setLogOnlyTransitions(enable);
1448ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff    }
1449ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
1450ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff    /**
1451bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return number of log records
1452bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1453bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final int getLogRecSize() {
1454efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1455efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1456efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return 0;
1457efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.mLogRecords.size();
1458bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1459bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1460bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1461bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return the total number of records processed
1462bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1463bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final int getLogRecCount() {
1464efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1465efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1466efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return 0;
1467efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.mLogRecords.count();
1468bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1469bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1470bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1471efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return a log record, or null if index is out of range
1472bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1473bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final LogRec getLogRec(int index) {
1474efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1475efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1476efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return null;
1477efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.mLogRecords.get(index);
1478bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1479bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1480bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1481efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return a copy of LogRecs as a collection
1482bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1483efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    public final Collection<LogRec> copyLogRecs() {
1484efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        Vector<LogRec> vlr = new Vector<LogRec>();
1485efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1486efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh != null) {
1487efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            for (LogRec lr : smh.mLogRecords.mLogRecVector) {
1488efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                vlr.add(lr);
1489efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            }
1490efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        }
1491efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return vlr;
1492fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1493fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1494fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1495efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Add the string to LogRecords.
1496bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     *
1497bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @param string
1498fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1499efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    protected void addLogRec(String string) {
1500efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1501efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1502efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1503efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.mLogRecords.add(this, smh.getCurrentMessage(), string, smh.getCurrentState(),
1504efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                smh.mStateStack[smh.mStateStackTopIndex].state, smh.mDestState);
1505fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1506fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1507fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1508bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return true if msg should be saved in the log, default is true.
1509fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1510bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected boolean recordLogRec(Message msg) {
1511bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return true;
1512fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1513fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1514fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1515bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Return a string to be logged by LogRec, default
1516bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * is an empty string. Override if additional information is desired.
1517bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     *
1518bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @param msg that was processed
1519bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return information to be logged as a String
1520fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1521bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected String getLogRecString(Message msg) {
1522bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return "";
1523bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1524bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1525bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1526bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return the string for msg.what
1527bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1528bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected String getWhatToString(int what) {
1529bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return null;
1530fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1531fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1532fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1533efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return Handler, maybe null if state machine has quit.
1534fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1535fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final Handler getHandler() {
153664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return mSmHandler;
1537fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1538fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1539fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1540efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler.
1541fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1542efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1543efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1544efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1545efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1546efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1547efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
1548fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1549ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    public final Message obtainMessage() {
155064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler);
1551fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1552fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1553fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1554efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler, what.
1555efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1556efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1557efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1558efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1559efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1560fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1561fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param what is the assigned to Message.what.
1562efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
1563fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1564fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final Message obtainMessage(int what) {
156564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what);
1566fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1567fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1568fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1569efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler,
1570fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * what and obj.
1571fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1572efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1573efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1574efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1575efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1576efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1577fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param what is the assigned to Message.what.
1578fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param obj is assigned to Message.obj.
1579efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
1580fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1581ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    public final Message obtainMessage(int what, Object obj) {
158264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what, obj);
1583fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1584fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
158591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
1586efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler,
158796e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * what, arg1 and arg2
158896e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     *
1589efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1590efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1591efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1592efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1593efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
159496e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param what  is assigned to Message.what
159596e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg1  is assigned to Message.arg1
15968b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * @return  A Message object from the global pool
15978b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
15988b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    public final Message obtainMessage(int what, int arg1) {
15998b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // use this obtain so we don't match the obtain(h, what, Object) method
16008b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        return Message.obtain(mSmHandler, what, arg1, 0);
16018b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
16028b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
16038b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
16048b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Get a message and set Message.target state machine handler,
16058b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * what, arg1 and arg2
16068b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
16078b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Note: The handler can be null if the state machine has quit,
16088b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
16098b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
16108b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * StateMachine#sendMessage the message will just be ignored.
16118b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
16128b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * @param what  is assigned to Message.what
16138b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * @param arg1  is assigned to Message.arg1
161496e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg2  is assigned to Message.arg2
1615efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
161696e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     */
1617ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    public final Message obtainMessage(int what, int arg1, int arg2) {
161864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what, arg1, arg2);
161996e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    }
162096e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff
162196e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    /**
1622efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler,
162396e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * what, arg1, arg2 and obj
162496e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     *
1625efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1626efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1627efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1628efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1629efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
163096e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param what  is assigned to Message.what
163196e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg1  is assigned to Message.arg1
163296e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg2  is assigned to Message.arg2
163396e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param obj is assigned to Message.obj
1634efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
163596e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     */
1636ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    public final Message obtainMessage(int what, int arg1, int arg2, Object obj) {
163764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what, arg1, arg2, obj);
163896e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    }
163996e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff
164096e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    /**
164191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine.
1642efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1643efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
164491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
164591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessage(int what) {
1646a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1647efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1648efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1649a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1650efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessage(obtainMessage(what));
165191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
165291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
165391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
165491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine.
1655efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1656efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
165791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
165891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessage(int what, Object obj) {
1659a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1660efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1661efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1662a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1663ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        smh.sendMessage(obtainMessage(what, obj));
166491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
166591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
1666fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1667fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Enqueue a message to this state machine.
1668efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1669efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
1670fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
16718b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    public final void sendMessage(int what, int arg1) {
16728b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // mSmHandler can be null if the state machine has quit.
16738b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        SmHandler smh = mSmHandler;
16748b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        if (smh == null) return;
16758b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
16768b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessage(obtainMessage(what, arg1));
16778b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
16788b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
16798b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
16808b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Enqueue a message to this state machine.
16818b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
16828b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Message is ignored if state machine has quit.
16838b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
16848b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    public final void sendMessage(int what, int arg1, int arg2) {
16858b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // mSmHandler can be null if the state machine has quit.
16868b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        SmHandler smh = mSmHandler;
16878b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        if (smh == null) return;
16888b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
16898b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessage(obtainMessage(what, arg1, arg2));
16908b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
16918b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
16928b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
16938b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Enqueue a message to this state machine.
16948b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
16958b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Message is ignored if state machine has quit.
16968b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
16974753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    public final void sendMessage(int what, int arg1, int arg2, Object obj) {
16984753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        // mSmHandler can be null if the state machine has quit.
16994753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        SmHandler smh = mSmHandler;
17004753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        if (smh == null) return;
17014753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville
17024753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        smh.sendMessage(obtainMessage(what, arg1, arg2, obj));
17034753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    }
17044753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville
17054753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    /**
17064753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Enqueue a message to this state machine.
17074753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     *
17084753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Message is ignored if state machine has quit.
17094753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     */
1710fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final void sendMessage(Message msg) {
1711a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1712efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1713efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1714a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1715efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessage(msg);
1716fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1717fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1718fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1719fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Enqueue a message to this state machine after a delay.
1720efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1721efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
1722fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
172391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessageDelayed(int what, long delayMillis) {
1724a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1725efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1726efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1727a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1728efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageDelayed(obtainMessage(what), delayMillis);
172991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
173091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
173191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
173291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine after a delay.
1733efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1734efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
173591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
173691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessageDelayed(int what, Object obj, long delayMillis) {
1737a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1738efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1739efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1740a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1741efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageDelayed(obtainMessage(what, obj), delayMillis);
174291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
174391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
174491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
174591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine after a delay.
1746efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1747efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
174891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
17498b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    public final void sendMessageDelayed(int what, int arg1, long delayMillis) {
17508b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // mSmHandler can be null if the state machine has quit.
17518b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        SmHandler smh = mSmHandler;
17528b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        if (smh == null) return;
17538b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
17548b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessageDelayed(obtainMessage(what, arg1), delayMillis);
17558b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
17568b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
17578b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
17588b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Enqueue a message to this state machine after a delay.
17598b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
17608b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Message is ignored if state machine has quit.
17618b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
17628b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    public final void sendMessageDelayed(int what, int arg1, int arg2, long delayMillis) {
17638b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // mSmHandler can be null if the state machine has quit.
17648b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        SmHandler smh = mSmHandler;
17658b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        if (smh == null) return;
17668b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
17678b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessageDelayed(obtainMessage(what, arg1, arg2), delayMillis);
17688b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
17698b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
17708b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
17718b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Enqueue a message to this state machine after a delay.
17728b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
17738b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Message is ignored if state machine has quit.
17748b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
17754753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    public final void sendMessageDelayed(int what, int arg1, int arg2, Object obj,
17764753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville            long delayMillis) {
17774753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        // mSmHandler can be null if the state machine has quit.
17784753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        SmHandler smh = mSmHandler;
17794753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        if (smh == null) return;
17804753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville
17814753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        smh.sendMessageDelayed(obtainMessage(what, arg1, arg2, obj), delayMillis);
17824753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    }
17834753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville
17844753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    /**
17854753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Enqueue a message to this state machine after a delay.
17864753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     *
17874753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Message is ignored if state machine has quit.
17884753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     */
1789fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final void sendMessageDelayed(Message msg, long delayMillis) {
1790a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1791efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1792efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1793a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1794efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageDelayed(msg, delayMillis);
1795fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1796fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1797fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1798fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Enqueue a message to the front of the queue for this state machine.
179964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1800efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1801efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
1802fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
18038b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    protected final void sendMessageAtFrontOfQueue(int what) {
18048b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // mSmHandler can be null if the state machine has quit.
18058b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        SmHandler smh = mSmHandler;
18068b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        if (smh == null) return;
18078b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
18088b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessageAtFrontOfQueue(obtainMessage(what));
18098b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
18108b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
18118b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
18128b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Enqueue a message to the front of the queue for this state machine.
18138b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Protected, may only be called by instances of StateMachine.
18148b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
18158b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Message is ignored if state machine has quit.
18168b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
181791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    protected final void sendMessageAtFrontOfQueue(int what, Object obj) {
1818efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1819efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1820efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1821efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1822efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageAtFrontOfQueue(obtainMessage(what, obj));
182391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
182491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
182591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
182691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to the front of the queue for this state machine.
182764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1828efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1829efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
183091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
18318b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    protected final void sendMessageAtFrontOfQueue(int what, int arg1) {
1832efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1833efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1834efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1835efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
18368b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessageAtFrontOfQueue(obtainMessage(what, arg1));
18378b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
18388b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
18398b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
18408b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
18418b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Enqueue a message to the front of the queue for this state machine.
18428b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Protected, may only be called by instances of StateMachine.
18438b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
18448b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Message is ignored if state machine has quit.
18458b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
18468b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    protected final void sendMessageAtFrontOfQueue(int what, int arg1, int arg2) {
18478b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // mSmHandler can be null if the state machine has quit.
18488b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        SmHandler smh = mSmHandler;
18498b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        if (smh == null) return;
18508b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
18518b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessageAtFrontOfQueue(obtainMessage(what, arg1, arg2));
185291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
185391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
185491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
185591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to the front of the queue for this state machine.
185664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1857efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1858efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
185991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
18604753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    protected final void sendMessageAtFrontOfQueue(int what, int arg1, int arg2, Object obj) {
18614753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        // mSmHandler can be null if the state machine has quit.
18624753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        SmHandler smh = mSmHandler;
18634753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        if (smh == null) return;
18644753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville
18654753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        smh.sendMessageAtFrontOfQueue(obtainMessage(what, arg1, arg2, obj));
18664753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    }
18674753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville
18684753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    /**
18694753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Enqueue a message to the front of the queue for this state machine.
18704753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Protected, may only be called by instances of StateMachine.
18714753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     *
18724753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Message is ignored if state machine has quit.
18734753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     */
1874fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected final void sendMessageAtFrontOfQueue(Message msg) {
1875efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1876efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1877efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1878efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1879efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageAtFrontOfQueue(msg);
1880fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1881fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1882fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1883aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh     * Removes a message from the message queue.
188464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1885aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh     */
1886aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh    protected final void removeMessages(int what) {
1887efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1888efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1889efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1890efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1891efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.removeMessages(what);
1892efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    }
1893efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1894efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    /**
1895c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker     * Removes a message from the deferred messages queue.
1896c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker     */
1897c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker    protected final void removeDeferredMessages(int what) {
1898c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker        SmHandler smh = mSmHandler;
1899c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker        if (smh == null) return;
1900c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker
1901c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker        Iterator<Message> iterator = smh.mDeferredMessages.iterator();
1902c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker        while (iterator.hasNext()) {
1903c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker            Message msg = iterator.next();
1904c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker            if (msg.what == what) iterator.remove();
1905c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker        }
1906c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker    }
1907c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker
1908c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker    /**
19098ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan     * Check if there are any pending messages with code 'what' in deferred messages queue.
19108ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan     */
19118ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan    protected final boolean hasDeferredMessages(int what) {
19128ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        SmHandler smh = mSmHandler;
19138ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        if (smh == null) return false;
19148ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan
19158ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        Iterator<Message> iterator = smh.mDeferredMessages.iterator();
19168ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        while (iterator.hasNext()) {
19178ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan            Message msg = iterator.next();
19188ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan            if (msg.what == what) return true;
19198ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        }
19208ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan
19218ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        return false;
19228ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan    }
19238ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan
19248ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan    /**
19258ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan     * Check if there are any pending posts of messages with code 'what' in
19268ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan     * the message queue. This does NOT check messages in deferred message queue.
19278ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan     */
19288ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan    protected final boolean hasMessages(int what) {
19298ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        SmHandler smh = mSmHandler;
19308ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        if (smh == null) return false;
19318ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan
19328ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        return smh.hasMessages(what);
19338ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan    }
19348ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan
19358ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan    /**
1936efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Validate that the message was sent by
1937efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * {@link StateMachine#quit} or {@link StateMachine#quitNow}.
1938efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * */
1939efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    protected final boolean isQuit(Message msg) {
1940efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1941efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1942efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return msg.what == SM_QUIT_CMD;
1943efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1944efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.isQuit(msg);
1945aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh    }
1946aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh
1947aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh    /**
1948bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Quit the state machine after all currently queued up messages are processed.
19491b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     */
1950bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected final void quit() {
1951bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        // mSmHandler can be null if the state machine is already stopped.
1952efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1953efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1954a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1955efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.quit();
19561b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    }
19571b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
19581b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    /**
1959bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Quit the state machine immediately all currently queued messages will be discarded.
19601b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     */
1961bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected final void quitNow() {
1962bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        // mSmHandler can be null if the state machine is already stopped.
1963efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1964efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1965583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
1966efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.quitNow();
1967583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    }
1968583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
1969583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    /**
1970fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @return if debugging is enabled
1971fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1972fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public boolean isDbg() {
1973a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1974efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1975efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return false;
1976a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1977efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.isDbg();
1978fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1979fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1980fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1981fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Set debug enable/disabled.
1982fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1983fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param dbg is true to enable debugging.
1984fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1985fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void setDbg(boolean dbg) {
1986a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1987efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1988efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1989a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1990efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.setDbg(dbg);
1991fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1992fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1993fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1994fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Start the state machine.
1995fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1996fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void start() {
1997a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1998efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1999efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
2000a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
2001fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** Send the complete construction message */
2002efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.completeConstruction();
2003fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
2004583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
2005583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    /**
2006583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * Dump the current state.
2007583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     *
2008583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * @param fd
2009583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * @param pw
2010583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * @param args
2011583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     */
2012583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
201354b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        // Cannot just invoke pw.println(this.toString()) because if the
201454b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        // resulting string is to long it won't be displayed.
201554b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        pw.println(getName() + ":");
201654b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        pw.println(" total records=" + getLogRecCount());
201754b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        for (int i = 0; i < getLogRecSize(); i++) {
201854b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville            pw.println(" rec[" + i + "]: " + getLogRec(i).toString());
201954b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville            pw.flush();
202054b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        }
202154b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        pw.println("curState=" + getCurrentState().getName());
2022726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood    }
2023726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood
2024726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood    @Override
2025726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood    public String toString() {
202654b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        StringWriter sr = new StringWriter();
202754b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        PrintWriter pr = new PrintWriter(sr);
202854b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        dump(null, pr, null);
202954b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        pr.flush();
203054b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        pr.close();
203154b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        return sr.toString();
2032583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    }
203358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
2034ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2035ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with debug and add to the LogRecords.
2036ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2037ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2038ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
2039ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    protected void logAndAddLogRec(String s) {
2040ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        addLogRec(s);
2041ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        log(s);
2042ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    }
2043ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville
2044ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2045ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with debug
2046ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2047ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2048ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
204958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void log(String s) {
205058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.d(mName, s);
205158c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
205258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
2053ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2054ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with debug attribute
2055ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2056ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2057ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
2058ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    protected void logd(String s) {
2059ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        Log.d(mName, s);
2060ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    }
2061ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville
2062ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2063ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with verbose attribute
2064ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2065ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2066ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
206758c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void logv(String s) {
206858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.v(mName, s);
206958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
207058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
2071ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2072ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with info attribute
2073ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2074ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2075ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
207658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void logi(String s) {
207758c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.i(mName, s);
207858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
207958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
2080ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2081ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with warning attribute
2082ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2083ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2084ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
208558c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void logw(String s) {
208658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.w(mName, s);
208758c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
208858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
2089ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2090ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with error attribute
2091ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2092ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2093ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
209458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void loge(String s) {
209558c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.e(mName, s);
209658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
2097ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville
2098ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2099ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with error attribute
2100ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2101ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2102ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param e is a Throwable which logs additional information.
2103ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
2104ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    protected void loge(String s, Throwable e) {
2105ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        Log.e(mName, s, e);
2106ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    }
2107fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
2108