StateMachine.java revision 355f11034d8aa1cbaac5d69e276767cb61ca925f
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) {
596d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            mMaxSize = maxSize;
597d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            mCount = 0;
598ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            mLogRecVector.clear();
599ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        }
600ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
601ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        synchronized void setLogOnlyTransitions(boolean enable) {
602ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            mLogOnlyTransitions = enable;
603ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        }
604ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
605ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        synchronized boolean logOnlyTransitions() {
606ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            return mLogOnlyTransitions;
607d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
608d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
609d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
610bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @return the number of recent records.
611d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
612bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized int size() {
613ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            return mLogRecVector.size();
614d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
615d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
616d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
617bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * @return the total number of records processed since size was set.
618d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
619bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized int count() {
620d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            return mCount;
621d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
622d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
623d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
624bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville         * Clear the list of records.
6256f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh         */
626bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized void cleanup() {
627ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            mLogRecVector.clear();
6286f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        }
6296f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh
6306f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        /**
631d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @return the information on a particular record. 0 is the oldest
632d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * record and size()-1 is the newest record. If the index is to
633d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * large null is returned.
634d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
635bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        synchronized LogRec get(int index) {
636d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            int nextIndex = mOldestIndex + index;
637d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            if (nextIndex >= mMaxSize) {
638d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                nextIndex -= mMaxSize;
639d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
640d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            if (nextIndex >= size()) {
641d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                return null;
642d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            } else {
643ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff                return mLogRecVector.get(nextIndex);
644d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
645d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
646d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
647d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        /**
648d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * Add a processed message.
649d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         *
650583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @param msg
651583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville         * @param messageInfo to be stored
652d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param state that handled the message
653d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * @param orgState is the first state the received the message but
654d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         * did not processes the message.
655ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * @param transToState is the state that was transitioned to after the message was
656ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * processed.
657ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         *
658d3059487abd526b91b912f70939c1c6994eecf52Wink Saville         */
659efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        synchronized void add(StateMachine sm, Message msg, String messageInfo, IState state,
660ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                IState orgState, IState transToState) {
661d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            mCount += 1;
662ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            if (mLogRecVector.size() < mMaxSize) {
663efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                mLogRecVector.add(new LogRec(sm, msg, messageInfo, state, orgState, transToState));
664d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            } else {
665ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff                LogRec pmi = mLogRecVector.get(mOldestIndex);
666d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                mOldestIndex += 1;
667d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                if (mOldestIndex >= mMaxSize) {
668d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                    mOldestIndex = 0;
669d3059487abd526b91b912f70939c1c6994eecf52Wink Saville                }
670efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                pmi.update(sm, msg, messageInfo, state, orgState, transToState);
671d3059487abd526b91b912f70939c1c6994eecf52Wink Saville            }
672d3059487abd526b91b912f70939c1c6994eecf52Wink Saville        }
673d3059487abd526b91b912f70939c1c6994eecf52Wink Saville    }
674d3059487abd526b91b912f70939c1c6994eecf52Wink Saville
67564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private static class SmHandler extends Handler {
676fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
67703812c7894bd51ffc27aece5933791e4a00d679bWink Saville        /** true if StateMachine has quit */
67803812c7894bd51ffc27aece5933791e4a00d679bWink Saville        private boolean mHasQuit = false;
67903812c7894bd51ffc27aece5933791e4a00d679bWink Saville
680fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The debug flag */
681fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private boolean mDbg = false;
682fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
683cea056f5894543819898a0e62f98dc7870b27758Wink Saville        /** The SmHandler object, identifies that message is internal */
684cea056f5894543819898a0e62f98dc7870b27758Wink Saville        private static final Object mSmHandlerObj = new Object();
6851b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
686a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        /** The current message */
687a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        private Message mMsg;
688a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
689bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        /** A list of log records including messages this state machine has processed */
690bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        private LogRecords mLogRecords = new LogRecords();
691fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
692fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** true if construction of the state machine has not been completed */
693fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private boolean mIsConstructionCompleted;
694fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
695fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** Stack used to manage the current hierarchy of states */
696fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateInfo mStateStack[];
697fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
698fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** Top of mStateStack */
699fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mStateStackTopIndex = -1;
700fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
701fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** A temporary stack used to manage the state stack */
702fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateInfo mTempStateStack[];
703fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
704fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The top of the mTempStateStack */
705fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mTempStateStackCount;
706fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
707fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** State used when state machine is halted */
708fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private HaltingState mHaltingState = new HaltingState();
709fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
7101b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        /** State used when state machine is quitting */
7111b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private QuittingState mQuittingState = new QuittingState();
7121b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
71364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** Reference to the StateMachine */
71464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private StateMachine mSm;
715fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
716fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
717fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Information about a state.
718fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Used to maintain the hierarchy.
719fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
720fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private class StateInfo {
721fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /** The state */
72264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            State state;
723fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
724fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /** The parent of this state, null if there is no parent */
725fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo parentStateInfo;
726fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
727fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /** True when the state has been entered and on the stack */
728fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            boolean active;
729fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
730fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
731fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * Convert StateInfo to string
732fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
733fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override
734fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            public String toString() {
735ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                return "state=" + state.getName() + ",active=" + active + ",parent="
736ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + ((parentStateInfo == null) ? "null" : parentStateInfo.state.getName());
737fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
738fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
739fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
740fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The map of all of the states in the state machine */
741ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        private HashMap<State, StateInfo> mStateInfo = new HashMap<State, StateInfo>();
742fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
743fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The initial state that will process the first message */
74464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private State mInitialState;
745fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
746fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The destination state when transitionTo has been invoked */
74764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private State mDestState;
748fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
749fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** The list of deferred messages */
750fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ArrayList<Message> mDeferredMessages = new ArrayList<Message>();
751fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
752fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
753fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * State entered when transitionToHaltingState is called.
754fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
75564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private class HaltingState extends State {
756fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override
757fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            public boolean processMessage(Message msg) {
75864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville                mSm.haltedProcessMessage(msg);
759fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
760fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
761fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
762fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
763fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
7641b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville         * State entered when a valid quit message is handled.
7651b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville         */
76664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private class QuittingState extends State {
7671b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            @Override
7681b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            public boolean processMessage(Message msg) {
769a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville                return NOT_HANDLED;
7701b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            }
7711b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
7721b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
7731b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        /**
774fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Handle messages sent to the state machine by calling
775fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * the current state's processMessage. It also handles
776fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * the enter/exit calls and placing any deferred messages
777fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * back onto the queue when transitioning to a new state.
778fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
779fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
780fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        public final void handleMessage(Message msg) {
78103812c7894bd51ffc27aece5933791e4a00d679bWink Saville            if (!mHasQuit) {
782355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger                if (mSm != null) {
783355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger                    mSm.onPreHandleMessage(msg);
784355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger                }
785355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger
78603812c7894bd51ffc27aece5933791e4a00d679bWink Saville                if (mDbg) mSm.log("handleMessage: E msg.what=" + msg.what);
78703812c7894bd51ffc27aece5933791e4a00d679bWink Saville
78803812c7894bd51ffc27aece5933791e4a00d679bWink Saville                /** Save the current message */
78903812c7894bd51ffc27aece5933791e4a00d679bWink Saville                mMsg = msg;
79003812c7894bd51ffc27aece5933791e4a00d679bWink Saville
79103812c7894bd51ffc27aece5933791e4a00d679bWink Saville                /** State that processed the message */
79203812c7894bd51ffc27aece5933791e4a00d679bWink Saville                State msgProcessedState = null;
79303812c7894bd51ffc27aece5933791e4a00d679bWink Saville                if (mIsConstructionCompleted) {
79403812c7894bd51ffc27aece5933791e4a00d679bWink Saville                    /** Normal path */
79503812c7894bd51ffc27aece5933791e4a00d679bWink Saville                    msgProcessedState = processMsg(msg);
79603812c7894bd51ffc27aece5933791e4a00d679bWink Saville                } else if (!mIsConstructionCompleted && (mMsg.what == SM_INIT_CMD)
79703812c7894bd51ffc27aece5933791e4a00d679bWink Saville                        && (mMsg.obj == mSmHandlerObj)) {
79803812c7894bd51ffc27aece5933791e4a00d679bWink Saville                    /** Initial one time path. */
79903812c7894bd51ffc27aece5933791e4a00d679bWink Saville                    mIsConstructionCompleted = true;
80003812c7894bd51ffc27aece5933791e4a00d679bWink Saville                    invokeEnterMethods(0);
80103812c7894bd51ffc27aece5933791e4a00d679bWink Saville                } else {
80203812c7894bd51ffc27aece5933791e4a00d679bWink Saville                    throw new RuntimeException("StateMachine.handleMessage: "
80303812c7894bd51ffc27aece5933791e4a00d679bWink Saville                            + "The start method not called, received msg: " + msg);
80403812c7894bd51ffc27aece5933791e4a00d679bWink Saville                }
80503812c7894bd51ffc27aece5933791e4a00d679bWink Saville                performTransitions(msgProcessedState, msg);
806fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
80703812c7894bd51ffc27aece5933791e4a00d679bWink Saville                // We need to check if mSm == null here as we could be quitting.
80803812c7894bd51ffc27aece5933791e4a00d679bWink Saville                if (mDbg && mSm != null) mSm.log("handleMessage: X");
809355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger
810355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger                if (mSm != null) {
811355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger                    mSm.onPostHandleMessage(msg);
812355f11034d8aa1cbaac5d69e276767cb61ca925fBrad Ebinger                }
81303812c7894bd51ffc27aece5933791e4a00d679bWink Saville            }
814e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville        }
815e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville
816e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville        /**
817e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville         * Do any transitions
818ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * @param msgProcessedState is the state that processed the message
819e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville         */
820efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        private void performTransitions(State msgProcessedState, Message msg) {
821fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
822fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * If transitionTo has been called, exit and then enter
823e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * the appropriate states. We loop on this to allow
824e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * enter and exit methods to use transitionTo.
825fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
826ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            State orgState = mStateStack[mStateStackTopIndex].state;
827ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
828efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            /**
829efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville             * Record whether message needs to be logged before we transition and
830efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville             * and we won't log special messages SM_INIT_CMD or SM_QUIT_CMD which
831efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville             * always set msg.obj to the handler.
832efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville             */
833f643069ad56763732a06ab601cea1272e4c1827aWink Saville            boolean recordLogMsg = mSm.recordLogRec(mMsg) && (msg.obj != mSmHandlerObj);
834ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
835efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            if (mLogRecords.logOnlyTransitions()) {
836efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                /** Record only if there is a transition */
837efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                if (mDestState != null) {
838efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState,
839efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                            orgState, mDestState);
840efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                }
841efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            } else if (recordLogMsg) {
842efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                /** Record message */
843ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                mLogRecords.add(mSm, mMsg, mSm.getLogRecString(mMsg), msgProcessedState, orgState,
844ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        mDestState);
845efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            }
846fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
847efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            State destState = mDestState;
848efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            if (destState != null) {
849fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                /**
850efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                 * Process the transitions including transitions in the enter/exit methods
851e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                 */
852efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                while (true) {
853efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    if (mDbg) mSm.log("handleMessage: new destination call exit/enter");
854e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville
855efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    /**
856efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * Determine the states to exit and enter and return the
857efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * common ancestor state of the enter/exit states. Then
858efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * invoke the exit methods then the enter methods.
859efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     */
860efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
861efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    invokeExitMethods(commonStateInfo);
862efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    int stateStackEnteringIndex = moveTempStateStackToStateStack();
863efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    invokeEnterMethods(stateStackEnteringIndex);
864fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
865efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    /**
866efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * Since we have transitioned to a new state we need to have
867efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * any deferred messages moved to the front of the message queue
868efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * so they will be processed before any other messages in the
869efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     * message queue.
870efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                     */
871efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    moveDeferredMessageAtFrontOfQueue();
872efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
873efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    if (destState != mDestState) {
874efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                        // A new mDestState so continue looping
875efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                        destState = mDestState;
876efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    } else {
877efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                        // No change in mDestState so we're done
878efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                        break;
879efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                    }
880efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                }
881efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                mDestState = null;
882e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            }
883fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
884e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            /**
885e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * After processing all transitions check and
886e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             * see if the last transition was to quit or halt.
887e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville             */
888e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville            if (destState != null) {
889e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                if (destState == mQuittingState) {
890bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    /**
891bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     * Call onQuitting to let subclasses cleanup.
892bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     */
893bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    mSm.onQuitting();
8946f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                    cleanupAfterQuitting();
895e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                } else if (destState == mHaltingState) {
896e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                    /**
897bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     * Call onHalting() if we've transitioned to the halting
898e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                     * state. All subsequent messages will be processed in
899e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                     * in the halting state which invokes haltedProcessMessage(msg);
900e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville                     */
901bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    mSm.onHalting();
902fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
903fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
904fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
905fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
906fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
9076f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh         * Cleanup all the static variables and the looper after the SM has been quit.
9086f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh         */
9096f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        private final void cleanupAfterQuitting() {
9106f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            if (mSm.mSmThread != null) {
9116f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                // If we made the thread then quit looper which stops the thread.
9126f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                getLooper().quit();
9136f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh                mSm.mSmThread = null;
9146f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            }
9156f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh
9166f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mSm.mSmHandler = null;
9176f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mSm = null;
9186f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mMsg = null;
919bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            mLogRecords.cleanup();
9206f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mStateStack = null;
9216f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mTempStateStack = null;
9226f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mStateInfo.clear();
9236f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mInitialState = null;
9246f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mDestState = null;
9256f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh            mDeferredMessages.clear();
92603812c7894bd51ffc27aece5933791e4a00d679bWink Saville            mHasQuit = true;
9276f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        }
9286f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh
9296f9a61651e7949a5d63a4b44314d435c0105a51fJaikumar Ganesh        /**
930fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Complete the construction of the state machine.
931fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
932fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void completeConstruction() {
93358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("completeConstruction: E");
934fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
935fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
936fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * Determine the maximum depth of the state hierarchy
937fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * so we can allocate the state stacks.
938fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
939fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int maxDepth = 0;
940fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (StateInfo si : mStateInfo.values()) {
941fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                int depth = 0;
942fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                for (StateInfo i = si; i != null; depth++) {
943fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    i = i.parentStateInfo;
944fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
945fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (maxDepth < depth) {
946fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    maxDepth = depth;
947fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
948fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
94958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("completeConstruction: maxDepth=" + maxDepth);
950fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
951fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mStateStack = new StateInfo[maxDepth];
952fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mTempStateStack = new StateInfo[maxDepth];
953fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setupInitialStateStack();
954fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
955cea056f5894543819898a0e62f98dc7870b27758Wink Saville            /** Sending SM_INIT_CMD message to invoke enter methods asynchronously */
956cea056f5894543819898a0e62f98dc7870b27758Wink Saville            sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));
957e7be6a85da5be32348f4e83ede195477a7ec1790Wink Saville
95858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("completeConstruction: X");
959fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
960fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
961fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
962fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Process the message. If the current state doesn't handle
963fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * it, call the states parent and so on. If it is never handled then
964fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * call the state machines unhandledMessage method.
965ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff         * @return the state that processed the message
966fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
967ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        private final State processMsg(Message msg) {
968fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
969fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
97058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                mSm.log("processMsg: " + curStateInfo.state.getName());
971fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
972bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
973bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            if (isQuit(msg)) {
974bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                transitionTo(mQuittingState);
975bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            } else {
976bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                while (!curStateInfo.state.processMessage(msg)) {
977fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    /**
978bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                     * Not processed
979fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                     */
980bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    curStateInfo = curStateInfo.parentStateInfo;
981bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    if (curStateInfo == null) {
982bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        /**
983bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                         * No parents left so it's not handled
984bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                         */
985bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        mSm.unhandledMessage(msg);
986bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                        break;
987bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    }
988bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville                    if (mDbg) {
98958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                        mSm.log("processMsg: " + curStateInfo.state.getName());
9901b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                    }
991fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
992ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            }
993ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff            return (curStateInfo != null) ? curStateInfo.state : null;
994fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
995fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
996fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
997fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Call the exit method for each state from the top of stack
998fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * up to the common ancestor state.
999fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1000fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void invokeExitMethods(StateInfo commonStateInfo) {
1001ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            while ((mStateStackTopIndex >= 0)
1002ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                    && (mStateStack[mStateStackTopIndex] != commonStateInfo)) {
100364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville                State curState = mStateStack[mStateStackTopIndex].state;
100458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                if (mDbg) mSm.log("invokeExitMethods: " + curState.getName());
1005fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                curState.exit();
1006fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[mStateStackTopIndex].active = false;
1007fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStackTopIndex -= 1;
1008fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1009fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1010fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1011fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1012fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Invoke the enter method starting at the entering index to top of state stack
1013fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1014fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void invokeEnterMethods(int stateStackEnteringIndex) {
1015fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {
101658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                if (mDbg) mSm.log("invokeEnterMethods: " + mStateStack[i].state.getName());
1017fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[i].state.enter();
1018fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[i].active = true;
1019fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1020fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1021fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1022fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1023fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Move the deferred message to the front of the message queue.
1024fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1025fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void moveDeferredMessageAtFrontOfQueue() {
1026fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
1027fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * The oldest messages on the deferred list must be at
1028fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * the front of the queue so start at the back, which
1029fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * as the most resent message and end with the oldest
1030fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * messages at the front of the queue.
1031fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
1032ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            for (int i = mDeferredMessages.size() - 1; i >= 0; i--) {
1033fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Message curMsg = mDeferredMessages.get(i);
103458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                if (mDbg) mSm.log("moveDeferredMessageAtFrontOfQueue; what=" + curMsg.what);
1035fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sendMessageAtFrontOfQueue(curMsg);
1036fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1037fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mDeferredMessages.clear();
1038fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1039fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1040fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1041fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Move the contents of the temporary stack to the state stack
1042fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * reversing the order of the items on the temporary stack as
1043fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * they are moved.
1044fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
104564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville         * @return index into mStateStack where entering needs to start
1046fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1047fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final int moveTempStateStackToStateStack() {
1048fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int startingIndex = mStateStackTopIndex + 1;
1049fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int i = mTempStateStackCount - 1;
1050fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            int j = startingIndex;
1051fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            while (i >= 0) {
105258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                if (mDbg) mSm.log("moveTempStackToStateStack: i=" + i + ",j=" + j);
1053fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateStack[j] = mTempStateStack[i];
1054fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                j += 1;
1055fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                i -= 1;
1056fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1057fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1058fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mStateStackTopIndex = j - 1;
1059fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
1060ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                mSm.log("moveTempStackToStateStack: X mStateStackTop=" + mStateStackTopIndex
1061ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + ",startingIndex=" + startingIndex + ",Top="
1062ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + mStateStack[mStateStackTopIndex].state.getName());
1063fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1064fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return startingIndex;
1065fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1066fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1067fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1068fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Setup the mTempStateStack with the states we are going to enter.
1069fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1070fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * This is found by searching up the destState's ancestors for a
1071fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * state that is already active i.e. StateInfo.active == true.
1072fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * The destStae and all of its inactive parents will be on the
1073fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * TempStateStack as the list of states to enter.
1074fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1075fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @return StateInfo of the common ancestor for the destState and
1076fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * current state or null if there is no common parent.
1077fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
107864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final StateInfo setupTempStateStackWithStatesToEnter(State destState) {
1079fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /**
1080fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * Search up the parent list of the destination state for an active
1081fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * state. Use a do while() loop as the destState must always be entered
1082fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * even if it is active. This can happen if we are exiting/entering
1083fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             * the current state.
1084fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville             */
1085fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mTempStateStackCount = 0;
1086fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo curStateInfo = mStateInfo.get(destState);
1087fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            do {
1088fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mTempStateStack[mTempStateStackCount++] = curStateInfo;
1089fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                curStateInfo = curStateInfo.parentStateInfo;
1090fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } while ((curStateInfo != null) && !curStateInfo.active);
1091fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1092fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
109358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville                mSm.log("setupTempStateStackWithStatesToEnter: X mTempStateStackCount="
1094ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + mTempStateStackCount + ",curStateInfo: " + curStateInfo);
1095fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1096fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return curStateInfo;
1097fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1098fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1099fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1100fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Initialize StateStack to mInitialState.
1101fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1102fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void setupInitialStateStack() {
1103fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
1104ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                mSm.log("setupInitialStateStack: E mInitialState=" + mInitialState.getName());
1105fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1106fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1107fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo curStateInfo = mStateInfo.get(mInitialState);
1108fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {
1109fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mTempStateStack[mTempStateStackCount] = curStateInfo;
1110fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                curStateInfo = curStateInfo.parentStateInfo;
1111fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1112fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1113fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Empty the StateStack
1114fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mStateStackTopIndex = -1;
1115fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1116fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            moveTempStateStackToStateStack();
1117fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1118fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1119fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1120a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville         * @return current message
1121a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville         */
1122a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        private final Message getCurrentMessage() {
1123a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville            return mMsg;
1124a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        }
1125a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
1126a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville        /**
1127fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @return current state
1128fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
112964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final IState getCurrentState() {
1130fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return mStateStack[mStateStackTopIndex].state;
1131fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1132fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1133fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1134fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Add a new state to the state machine. Bottom up addition
1135fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * of states is allowed but the same state may only exist
1136fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * in one hierarchy.
1137fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1138fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @param state the state to add
1139fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @param parent the parent of state
1140fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @return stateInfo for this state
1141fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
114264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final StateInfo addState(State state, State parent) {
1143fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (mDbg) {
1144ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                mSm.log("addStateInternal: E state=" + state.getName() + ",parent="
1145ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                        + ((parent == null) ? "" : parent.getName()));
1146fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1147fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo parentStateInfo = null;
1148fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (parent != null) {
1149fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                parentStateInfo = mStateInfo.get(parent);
1150fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (parentStateInfo == null) {
1151fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    // Recursively add our parent as it's not been added yet.
1152fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    parentStateInfo = addState(parent, null);
1153fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
1154fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1155fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            StateInfo stateInfo = mStateInfo.get(state);
1156fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (stateInfo == null) {
1157fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                stateInfo = new StateInfo();
1158fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mStateInfo.put(state, stateInfo);
1159fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1160fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1161fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Validate that we aren't adding the same state in two different hierarchies.
1162ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville            if ((stateInfo.parentStateInfo != null)
1163ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                    && (stateInfo.parentStateInfo != parentStateInfo)) {
1164ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville                throw new RuntimeException("state already added");
1165fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1166fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            stateInfo.state = state;
1167fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            stateInfo.parentStateInfo = parentStateInfo;
1168fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            stateInfo.active = false;
116958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("addStateInternal: X stateInfo: " + stateInfo);
1170fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return stateInfo;
1171fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1172fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1173fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1174fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * Constructor
1175fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         *
1176fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * @param looper for dispatching messages
117764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville         * @param sm the hierarchical state machine
1178fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
117964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private SmHandler(Looper looper, StateMachine sm) {
1180fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            super(looper);
118164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            mSm = sm;
1182fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1183fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mHaltingState, null);
11841b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            addState(mQuittingState, null);
1185fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1186fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
118764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#setInitialState(State) */
118864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final void setInitialState(State initialState) {
118958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("setInitialState: initialState=" + initialState.getName());
1190fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mInitialState = initialState;
1191fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1192fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
119364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#transitionTo(IState) */
119464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        private final void transitionTo(IState destState) {
119564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville            mDestState = (State) destState;
119658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("transitionTo: destState=" + mDestState.getName());
1197fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1198fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
119964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#deferMessage(Message) */
1200fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void deferMessage(Message msg) {
120158c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("deferMessage: msg=" + msg.what);
1202fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1203fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            /* Copy the "msg" to "newMsg" as "msg" will be recycled */
1204fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Message newMsg = obtainMessage();
1205fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            newMsg.copyFrom(msg);
1206fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1207fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mDeferredMessages.add(newMsg);
1208fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1209fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1210bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        /** @see StateMachine#quit() */
12111b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private final void quit() {
121258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("quit:");
1213cea056f5894543819898a0e62f98dc7870b27758Wink Saville            sendMessage(obtainMessage(SM_QUIT_CMD, mSmHandlerObj));
12141b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
12151b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1216bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        /** @see StateMachine#quitNow() */
1217bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        private final void quitNow() {
121858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville            if (mDbg) mSm.log("quitNow:");
1219bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville            sendMessageAtFrontOfQueue(obtainMessage(SM_QUIT_CMD, mSmHandlerObj));
1220bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        }
1221bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
122258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        /** Validate that the message was sent by quit or quitNow. */
12231b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private final boolean isQuit(Message msg) {
1224cea056f5894543819898a0e62f98dc7870b27758Wink Saville            return (msg.what == SM_QUIT_CMD) && (msg.obj == mSmHandlerObj);
12251b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
12261b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
122764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#isDbg() */
1228fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final boolean isDbg() {
1229fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return mDbg;
1230fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1231fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
123264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        /** @see StateMachine#setDbg(boolean) */
1233fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final void setDbg(boolean dbg) {
1234fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mDbg = dbg;
1235fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1236fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1237fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1238fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
123964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private SmHandler mSmHandler;
124064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private HandlerThread mSmThread;
1241fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1242fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1243fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Initialize.
1244fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1245fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param looper for this state machine
1246fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param name of the state machine
1247fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1248f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville    private void initStateMachine(String name, Looper looper) {
1249fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        mName = name;
125064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler = new SmHandler(looper, this);
1251fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1252fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1253fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
125464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Constructor creates a StateMachine with its own thread.
1255fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1256fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param name of the state machine
1257fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
125864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected StateMachine(String name) {
125964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmThread = new HandlerThread(name);
126064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmThread.start();
126164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        Looper looper = mSmThread.getLooper();
1262fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1263f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville        initStateMachine(name, looper);
1264fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1265fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1266fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1267f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa     * Constructor creates a StateMachine using the looper.
1268fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1269fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param name of the state machine
1270fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
127164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected StateMachine(String name, Looper looper) {
1272f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville        initStateMachine(name, looper);
1273fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1274fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1275fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
127624d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville     * Constructor creates a StateMachine using the handler.
127724d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville     *
127824d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville     * @param name of the state machine
127924d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville     */
128024d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville    protected StateMachine(String name, Handler handler) {
128124d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville        initStateMachine(name, handler.getLooper());
128224d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville    }
128324d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville
128424d248acdf5eee9fc9a209d5207eaeceb00fa3e3Wink Saville    /**
12850c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     * Notifies subclass that the StateMachine handler is about to process the Message msg
12860c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     * @param msg The message that is being handled
12870c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     */
12880c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger    protected void onPreHandleMessage(Message msg) {
12890c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger    }
12900c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger
12910c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger    /**
12920c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     * Notifies subclass that the StateMachine handler has finished processing the Message msg and
12930c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     * has possibly transitioned to a new state.
12940c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     * @param msg The message that is being handled
12950c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger     */
12960c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger    protected void onPostHandleMessage(Message msg) {
12970c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger    }
12980c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger
12990c71404e772f96927668ee9f52f789ca209fa979Brad Ebinger    /**
1300fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Add a new state to the state machine
1301fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param state the state to add
1302fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param parent the parent of state
1303fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
130464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void addState(State state, State parent) {
130564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.addState(state, parent);
1306fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1307a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville
1308a4f3bec29c85ef9e0d07fdd551fe3c50f28b9adcWink Saville    /**
1309fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Add a new state to the state machine, parent will be null
1310fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param state to add
1311fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
131264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void addState(State state) {
131364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.addState(state, null);
1314fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1315fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1316fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1317fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Set the initial state. This must be invoked before
1318fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * and messages are sent to the state machine.
1319fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1320fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param initialState is the state which will receive the first message.
1321fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
132264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void setInitialState(State initialState) {
132364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.setInitialState(initialState);
1324fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1325fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1326fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1327efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return current message
1328efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     */
1329efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    protected final Message getCurrentMessage() {
1330efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1331efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1332efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return null;
1333efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.getCurrentMessage();
1334efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    }
1335efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1336efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    /**
1337efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return current state
1338efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     */
1339efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    protected final IState getCurrentState() {
1340efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1341efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1342efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return null;
1343efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.getCurrentState();
1344efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    }
1345efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1346efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    /**
1347fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * transition to destination state. Upon returning
1348fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * from processMessage the current state's exit will
1349fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * be executed and upon the next message arriving
1350fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * destState.enter will be invoked.
1351fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1352d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * this function can also be called inside the enter function of the
1353d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * previous transition target, but the behavior is undefined when it is
1354d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * called mid-way through a previous transition (for example, calling this
1355d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * in the enter() routine of a intermediate node when the current transition
1356d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     * target is one of the nodes descendants).
1357d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy     *
1358fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param destState will be the state that receives the next message.
1359fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
136064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    protected final void transitionTo(IState destState) {
136164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.transitionTo(destState);
1362fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1363fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1364fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1365fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * transition to halt state. Upon returning
1366fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * from processMessage we will exit all current
1367bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * states, execute the onHalting() method and then
1368bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * for all subsequent messages haltedProcessMessage
1369fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * will be called.
1370fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1371fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected final void transitionToHaltingState() {
137264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.transitionTo(mSmHandler.mHaltingState);
1373fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1374fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1375fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1376fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Defer this message until next state transition.
1377fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Upon transitioning all deferred messages will be
1378fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * placed on the queue and reprocessed in the original
1379fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * order. (i.e. The next state the oldest messages will
1380fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * be processed first)
1381fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1382fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param msg is deferred until the next transition.
1383fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1384fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected final void deferMessage(Message msg) {
138564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        mSmHandler.deferMessage(msg);
1386fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1387fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1388fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1389fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Called when message wasn't handled
1390fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1391fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param msg that couldn't be handled.
1392fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1393fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected void unhandledMessage(Message msg) {
139458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        if (mSmHandler.mDbg) loge(" - unhandledMessage: msg.what=" + msg.what);
1395fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1396fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1397fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1398fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Called for any message that is received after
1399fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * transitionToHalting is called.
1400fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1401fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected void haltedProcessMessage(Message msg) {
1402fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1403fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1404fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1405d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * This will be called once after handling a message that called
1406d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * transitionToHalting. All subsequent messages will invoke
140764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * {@link StateMachine#haltedProcessMessage(Message)}
1408fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1409bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected void onHalting() {
1410fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1411fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1412fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1413d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * This will be called once after a quit message that was NOT handled by
141464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * the derived StateMachine. The StateMachine will stop and any subsequent messages will be
141564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * ignored. In addition, if this StateMachine created the thread, the thread will
1416d3059487abd526b91b912f70939c1c6994eecf52Wink Saville     * be stopped after this method returns.
14171b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     */
1418bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected void onQuitting() {
14191b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    }
14201b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
14211b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    /**
1422fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @return the name
1423fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1424fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final String getName() {
1425fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        return mName;
1426fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1427fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1428fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1429bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Set number of log records to maintain and clears all current records.
1430fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1431fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param maxSize number of messages to maintain at anyone time.
1432fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1433bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final void setLogRecSize(int maxSize) {
1434bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        mSmHandler.mLogRecords.setSize(maxSize);
1435bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1436bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1437bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1438ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff     * Set to log only messages that cause a state transition
1439ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff     *
1440ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff     * @param enable {@code true} to enable, {@code false} to disable
1441ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff     */
1442ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff    public final void setLogOnlyTransitions(boolean enable) {
1443ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff        mSmHandler.mLogRecords.setLogOnlyTransitions(enable);
1444ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff    }
1445ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff
1446ef8da9fe0b70fdbbb54bb0645ac66f75f58f31b8Irfan Sheriff    /**
1447bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return number of log records
1448bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1449bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final int getLogRecSize() {
1450efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1451efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1452efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return 0;
1453efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.mLogRecords.size();
1454bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1455bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1456bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1457bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return the total number of records processed
1458bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1459bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final int getLogRecCount() {
1460efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1461efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1462efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return 0;
1463efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.mLogRecords.count();
1464bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1465bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1466bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1467efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return a log record, or null if index is out of range
1468bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1469bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    public final LogRec getLogRec(int index) {
1470efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1471efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1472efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return null;
1473efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.mLogRecords.get(index);
1474bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1475bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1476bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1477efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return a copy of LogRecs as a collection
1478bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1479efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    public final Collection<LogRec> copyLogRecs() {
1480efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        Vector<LogRec> vlr = new Vector<LogRec>();
1481efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1482efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh != null) {
1483efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            for (LogRec lr : smh.mLogRecords.mLogRecVector) {
1484efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                vlr.add(lr);
1485efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville            }
1486efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        }
1487efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return vlr;
1488fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1489fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1490fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1491efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Add the string to LogRecords.
1492bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     *
1493bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @param string
1494fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1495efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    protected void addLogRec(String string) {
1496efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1497efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1498efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1499efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.mLogRecords.add(this, smh.getCurrentMessage(), string, smh.getCurrentState(),
1500efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville                smh.mStateStack[smh.mStateStackTopIndex].state, smh.mDestState);
1501fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1502fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1503fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1504bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return true if msg should be saved in the log, default is true.
1505fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1506bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected boolean recordLogRec(Message msg) {
1507bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return true;
1508fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1509fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1510fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1511bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Return a string to be logged by LogRec, default
1512bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * is an empty string. Override if additional information is desired.
1513bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     *
1514bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @param msg that was processed
1515bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return information to be logged as a String
1516fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1517bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected String getLogRecString(Message msg) {
1518bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return "";
1519bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    }
1520bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville
1521bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    /**
1522bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * @return the string for msg.what
1523bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     */
1524bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected String getWhatToString(int what) {
1525bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        return null;
1526fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1527fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1528fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1529efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return Handler, maybe null if state machine has quit.
1530fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1531fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final Handler getHandler() {
153264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return mSmHandler;
1533fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1534fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1535fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1536efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler.
1537fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1538efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1539efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1540efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1541efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1542efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1543efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
1544fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1545ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    public final Message obtainMessage() {
154664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler);
1547fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1548fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1549fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1550efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler, what.
1551efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1552efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1553efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1554efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1555efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1556fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1557fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param what is the assigned to Message.what.
1558efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
1559fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1560fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final Message obtainMessage(int what) {
156164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what);
1562fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1563fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1564fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1565efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler,
1566fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * what and obj.
1567fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1568efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1569efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1570efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1571efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1572efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1573fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param what is the assigned to Message.what.
1574fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param obj is assigned to Message.obj.
1575efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
1576fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1577ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    public final Message obtainMessage(int what, Object obj) {
157864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what, obj);
1579fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1580fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
158191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
1582efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler,
158396e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * what, arg1 and arg2
158496e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     *
1585efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1586efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1587efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1588efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1589efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
159096e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param what  is assigned to Message.what
159196e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg1  is assigned to Message.arg1
15928b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * @return  A Message object from the global pool
15938b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
15948b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    public final Message obtainMessage(int what, int arg1) {
15958b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // use this obtain so we don't match the obtain(h, what, Object) method
15968b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        return Message.obtain(mSmHandler, what, arg1, 0);
15978b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
15988b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
15998b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
16008b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Get a message and set Message.target state machine handler,
16018b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * what, arg1 and arg2
16028b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
16038b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Note: The handler can be null if the state machine has quit,
16048b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
16058b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
16068b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * StateMachine#sendMessage the message will just be ignored.
16078b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
16088b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * @param what  is assigned to Message.what
16098b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * @param arg1  is assigned to Message.arg1
161096e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg2  is assigned to Message.arg2
1611efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
161296e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     */
1613ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    public final Message obtainMessage(int what, int arg1, int arg2) {
161464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what, arg1, arg2);
161596e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    }
161696e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff
161796e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    /**
1618efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Get a message and set Message.target state machine handler,
161996e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * what, arg1, arg2 and obj
162096e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     *
1621efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Note: The handler can be null if the state machine has quit,
1622efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * which means target will be null and may cause a AndroidRuntimeException
1623efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * in MessageQueue#enqueMessage if sent directly or if sent using
1624efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * StateMachine#sendMessage the message will just be ignored.
1625efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
162696e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param what  is assigned to Message.what
162796e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg1  is assigned to Message.arg1
162896e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param arg2  is assigned to Message.arg2
162996e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     * @param obj is assigned to Message.obj
1630efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * @return  A Message object from the global pool
163196e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff     */
1632ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    public final Message obtainMessage(int what, int arg1, int arg2, Object obj) {
163364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville        return Message.obtain(mSmHandler, what, arg1, arg2, obj);
163496e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    }
163596e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff
163696e6bdb033b2997a4215b70acc3777fe495b9acaIrfan Sheriff    /**
163791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine.
1638efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1639efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
164091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
164191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessage(int what) {
1642a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1643efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1644efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1645a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1646efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessage(obtainMessage(what));
164791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
164891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
164991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
165091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine.
1651efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1652efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
165391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
165491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessage(int what, Object obj) {
1655a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1656efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1657efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1658a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1659ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        smh.sendMessage(obtainMessage(what, obj));
166091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
166191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
1662fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1663fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Enqueue a message to this state machine.
1664efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1665efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
1666fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
16678b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    public final void sendMessage(int what, int arg1) {
16688b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // mSmHandler can be null if the state machine has quit.
16698b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        SmHandler smh = mSmHandler;
16708b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        if (smh == null) return;
16718b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
16728b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessage(obtainMessage(what, arg1));
16738b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
16748b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
16758b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
16768b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Enqueue a message to this state machine.
16778b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
16788b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Message is ignored if state machine has quit.
16798b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
16808b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    public final void sendMessage(int what, int arg1, int arg2) {
16818b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // mSmHandler can be null if the state machine has quit.
16828b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        SmHandler smh = mSmHandler;
16838b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        if (smh == null) return;
16848b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
16858b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessage(obtainMessage(what, arg1, arg2));
16868b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
16878b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
16888b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
16898b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Enqueue a message to this state machine.
16908b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
16918b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Message is ignored if state machine has quit.
16928b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
16934753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    public final void sendMessage(int what, int arg1, int arg2, Object obj) {
16944753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        // mSmHandler can be null if the state machine has quit.
16954753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        SmHandler smh = mSmHandler;
16964753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        if (smh == null) return;
16974753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville
16984753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        smh.sendMessage(obtainMessage(what, arg1, arg2, obj));
16994753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    }
17004753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville
17014753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    /**
17024753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Enqueue a message to this state machine.
17034753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     *
17044753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Message is ignored if state machine has quit.
17054753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     */
1706fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final void sendMessage(Message msg) {
1707a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1708efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1709efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1710a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1711efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessage(msg);
1712fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1713fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1714fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1715fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Enqueue a message to this state machine after a delay.
1716efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1717efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
1718fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
171991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessageDelayed(int what, long delayMillis) {
1720a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1721efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1722efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1723a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1724efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageDelayed(obtainMessage(what), delayMillis);
172591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
172691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
172791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
172891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine after a delay.
1729efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1730efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
173191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
173291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    public final void sendMessageDelayed(int what, Object obj, long delayMillis) {
1733a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1734efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1735efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1736a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1737efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageDelayed(obtainMessage(what, obj), delayMillis);
173891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
173991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
174091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
174191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to this state machine after a delay.
1742efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1743efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
174491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
17458b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    public final void sendMessageDelayed(int what, int arg1, long delayMillis) {
17468b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // mSmHandler can be null if the state machine has quit.
17478b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        SmHandler smh = mSmHandler;
17488b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        if (smh == null) return;
17498b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
17508b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessageDelayed(obtainMessage(what, arg1), delayMillis);
17518b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
17528b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
17538b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
17548b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Enqueue a message to this state machine after a delay.
17558b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
17568b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Message is ignored if state machine has quit.
17578b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
17588b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    public final void sendMessageDelayed(int what, int arg1, int arg2, long delayMillis) {
17598b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // mSmHandler can be null if the state machine has quit.
17608b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        SmHandler smh = mSmHandler;
17618b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        if (smh == null) return;
17628b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
17638b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessageDelayed(obtainMessage(what, arg1, arg2), delayMillis);
17648b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
17658b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
17668b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
17678b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Enqueue a message to this state machine after a delay.
17688b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
17698b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Message is ignored if state machine has quit.
17708b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
17714753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    public final void sendMessageDelayed(int what, int arg1, int arg2, Object obj,
17724753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville            long delayMillis) {
17734753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        // mSmHandler can be null if the state machine has quit.
17744753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        SmHandler smh = mSmHandler;
17754753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        if (smh == null) return;
17764753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville
17774753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        smh.sendMessageDelayed(obtainMessage(what, arg1, arg2, obj), delayMillis);
17784753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    }
17794753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville
17804753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    /**
17814753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Enqueue a message to this state machine after a delay.
17824753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     *
17834753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Message is ignored if state machine has quit.
17844753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     */
1785fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public final void sendMessageDelayed(Message msg, long delayMillis) {
1786a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1787efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1788efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1789a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1790efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageDelayed(msg, delayMillis);
1791fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1792fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1793fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1794fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Enqueue a message to the front of the queue for this state machine.
179564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1796efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1797efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
1798fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
17998b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    protected final void sendMessageAtFrontOfQueue(int what) {
18008b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // mSmHandler can be null if the state machine has quit.
18018b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        SmHandler smh = mSmHandler;
18028b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        if (smh == null) return;
18038b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
18048b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessageAtFrontOfQueue(obtainMessage(what));
18058b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
18068b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
18078b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
18088b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Enqueue a message to the front of the queue for this state machine.
18098b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Protected, may only be called by instances of StateMachine.
18108b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
18118b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Message is ignored if state machine has quit.
18128b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
181391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    protected final void sendMessageAtFrontOfQueue(int what, Object obj) {
1814efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1815efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1816efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1817efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1818efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageAtFrontOfQueue(obtainMessage(what, obj));
181991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
182091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
182191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
182291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to the front of the queue for this state machine.
182364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1824efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1825efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
182691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
18278b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    protected final void sendMessageAtFrontOfQueue(int what, int arg1) {
1828efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1829efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1830efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1831efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
18328b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessageAtFrontOfQueue(obtainMessage(what, arg1));
18338b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    }
18348b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
18358b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
18368b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    /**
18378b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Enqueue a message to the front of the queue for this state machine.
18388b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Protected, may only be called by instances of StateMachine.
18398b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     *
18408b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     * Message is ignored if state machine has quit.
18418b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville     */
18428b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville    protected final void sendMessageAtFrontOfQueue(int what, int arg1, int arg2) {
18438b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        // mSmHandler can be null if the state machine has quit.
18448b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        SmHandler smh = mSmHandler;
18458b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        if (smh == null) return;
18468b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville
18478b0db520405c88414bcf8fdcb96293fb7075e524Wink Saville        smh.sendMessageAtFrontOfQueue(obtainMessage(what, arg1, arg2));
184891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    }
184991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville
185091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville    /**
185191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     * Enqueue a message to the front of the queue for this state machine.
185264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1853efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     *
1854efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Message is ignored if state machine has quit.
185591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville     */
18564753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    protected final void sendMessageAtFrontOfQueue(int what, int arg1, int arg2, Object obj) {
18574753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        // mSmHandler can be null if the state machine has quit.
18584753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        SmHandler smh = mSmHandler;
18594753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        if (smh == null) return;
18604753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville
18614753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville        smh.sendMessageAtFrontOfQueue(obtainMessage(what, arg1, arg2, obj));
18624753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    }
18634753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville
18644753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville    /**
18654753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Enqueue a message to the front of the queue for this state machine.
18664753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Protected, may only be called by instances of StateMachine.
18674753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     *
18684753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     * Message is ignored if state machine has quit.
18694753cd2014b3db7ab47a9d408601e9e17f790a21Wink Saville     */
1870fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected final void sendMessageAtFrontOfQueue(Message msg) {
1871efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1872efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1873efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1874efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1875efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.sendMessageAtFrontOfQueue(msg);
1876fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1877fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1878fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1879aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh     * Removes a message from the message queue.
188064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville     * Protected, may only be called by instances of StateMachine.
1881aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh     */
1882aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh    protected final void removeMessages(int what) {
1883efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1884efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1885efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1886efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1887efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.removeMessages(what);
1888efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    }
1889efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1890efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    /**
1891c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker     * Removes a message from the deferred messages queue.
1892c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker     */
1893c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker    protected final void removeDeferredMessages(int what) {
1894c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker        SmHandler smh = mSmHandler;
1895c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker        if (smh == null) return;
1896c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker
1897c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker        Iterator<Message> iterator = smh.mDeferredMessages.iterator();
1898c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker        while (iterator.hasNext()) {
1899c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker            Message msg = iterator.next();
1900c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker            if (msg.what == what) iterator.remove();
1901c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker        }
1902c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker    }
1903c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker
1904c211978650580904a4b11b7c5b899e9d2f7ed294Ajay Panicker    /**
19058ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan     * Check if there are any pending messages with code 'what' in deferred messages queue.
19068ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan     */
19078ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan    protected final boolean hasDeferredMessages(int what) {
19088ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        SmHandler smh = mSmHandler;
19098ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        if (smh == null) return false;
19108ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan
19118ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        Iterator<Message> iterator = smh.mDeferredMessages.iterator();
19128ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        while (iterator.hasNext()) {
19138ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan            Message msg = iterator.next();
19148ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan            if (msg.what == what) return true;
19158ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        }
19168ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan
19178ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        return false;
19188ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan    }
19198ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan
19208ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan    /**
19218ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan     * Check if there are any pending posts of messages with code 'what' in
19228ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan     * the message queue. This does NOT check messages in deferred message queue.
19238ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan     */
19248ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan    protected final boolean hasMessages(int what) {
19258ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        SmHandler smh = mSmHandler;
19268ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        if (smh == null) return false;
19278ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan
19288ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan        return smh.hasMessages(what);
19298ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan    }
19308ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan
19318ed715e31e4be65b4bc752a2d230a21adce2bb3aAmit Mahajan    /**
1932efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * Validate that the message was sent by
1933efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * {@link StateMachine#quit} or {@link StateMachine#quitNow}.
1934efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville     * */
1935efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville    protected final boolean isQuit(Message msg) {
1936efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        // mSmHandler can be null if the state machine has quit.
1937efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1938efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return msg.what == SM_QUIT_CMD;
1939efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville
1940efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.isQuit(msg);
1941aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh    }
1942aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh
1943aa4b235dd720d1f2861681cdfabf3b5fabc61fb0Jaikumar Ganesh    /**
1944bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Quit the state machine after all currently queued up messages are processed.
19451b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     */
1946bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected final void quit() {
1947bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        // mSmHandler can be null if the state machine is already stopped.
1948efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1949efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1950a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1951efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.quit();
19521b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    }
19531b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
19541b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    /**
1955bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville     * Quit the state machine immediately all currently queued messages will be discarded.
19561b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     */
1957bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville    protected final void quitNow() {
1958bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville        // mSmHandler can be null if the state machine is already stopped.
1959efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1960efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1961583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
1962efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.quitNow();
1963583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    }
1964583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
1965583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    /**
1966fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @return if debugging is enabled
1967fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1968fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public boolean isDbg() {
1969a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1970efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1971efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return false;
1972a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1973efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        return smh.isDbg();
1974fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1975fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1976fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1977fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Set debug enable/disabled.
1978fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     *
1979fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * @param dbg is true to enable debugging.
1980fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1981fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void setDbg(boolean dbg) {
1982a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1983efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1984efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1985a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1986efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.setDbg(dbg);
1987fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1988fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1989fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1990fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Start the state machine.
1991fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1992fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void start() {
1993a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh        // mSmHandler can be null if the state machine has quit.
1994efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        SmHandler smh = mSmHandler;
1995efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        if (smh == null) return;
1996a544d467f2a876f2ada2880214b3157cfaef769fJaikumar Ganesh
1997fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /** Send the complete construction message */
1998efcc3d35661c0cd978bb2b2f808fade4c4734e21Wink Saville        smh.completeConstruction();
1999fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
2000583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville
2001583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    /**
2002583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * Dump the current state.
2003583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     *
2004583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * @param fd
2005583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * @param pw
2006583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     * @param args
2007583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville     */
2008583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
200954b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        // Cannot just invoke pw.println(this.toString()) because if the
201054b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        // resulting string is to long it won't be displayed.
201154b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        pw.println(getName() + ":");
201254b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        pw.println(" total records=" + getLogRecCount());
201354b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        for (int i = 0; i < getLogRecSize(); i++) {
201454b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville            pw.println(" rec[" + i + "]: " + getLogRec(i).toString());
201554b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville            pw.flush();
201654b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        }
201754b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        pw.println("curState=" + getCurrentState().getName());
2018726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood    }
2019726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood
2020726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood    @Override
2021726d4de780dea9afded2e44a010b793f7ac29c23Mike Lockwood    public String toString() {
202254b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        StringWriter sr = new StringWriter();
202354b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        PrintWriter pr = new PrintWriter(sr);
202454b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        dump(null, pr, null);
202554b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        pr.flush();
202654b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        pr.close();
202754b1b1a07ad3edd1df060889aad453aa0e1cc79aWink Saville        return sr.toString();
2028583eaaa57c51b28bf14da2a5cc94a2e6091cccf5Wink Saville    }
202958c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
2030ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2031ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with debug and add to the LogRecords.
2032ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2033ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2034ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
2035ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    protected void logAndAddLogRec(String s) {
2036ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        addLogRec(s);
2037ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        log(s);
2038ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    }
2039ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville
2040ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2041ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with debug
2042ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2043ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2044ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
204558c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void log(String s) {
204658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.d(mName, s);
204758c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
204858c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
2049ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2050ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with debug attribute
2051ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2052ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2053ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
2054ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    protected void logd(String s) {
2055ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        Log.d(mName, s);
2056ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    }
2057ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville
2058ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2059ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with verbose attribute
2060ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2061ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2062ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
206358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void logv(String s) {
206458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.v(mName, s);
206558c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
206658c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
2067ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2068ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with info attribute
2069ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2070ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2071ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
207258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void logi(String s) {
207358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.i(mName, s);
207458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
207558c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
2076ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2077ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with warning attribute
2078ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2079ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2080ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
208158c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void logw(String s) {
208258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.w(mName, s);
208358c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
208458c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville
2085ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2086ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with error attribute
2087ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2088ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2089ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
209058c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    protected void loge(String s) {
209158c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville        Log.e(mName, s);
209258c73c3f76c231cf128041aefadd4b6a6bcefac2Wink Saville    }
2093ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville
2094ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    /**
2095ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * Log with error attribute
2096ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     *
2097ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param s is string log
2098ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     * @param e is a Throwable which logs additional information.
2099ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville     */
2100ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    protected void loge(String s, Throwable e) {
2101ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville        Log.e(mName, s, e);
2102ff4fcdb98c9575642c48f1daeafff4b257769e81Wink Saville    }
2103fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
2104