StateMachineTest.java revision 91fbd56757751a7aca8ef2b4d936e587509e6eef
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
171a44d5dcabc18cd5ef111f732ccff91683a1a093Neal Nguyenpackage android.os;
18fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
19fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport junit.framework.TestCase;
20fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
21fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport android.os.Debug;
22fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport android.os.HandlerThread;
23fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport android.os.Looper;
24fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport android.os.Message;
25fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport android.os.SystemClock;
26fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport android.test.suitebuilder.annotation.SmallTest;
27fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
28fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport android.util.Log;
29fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
30fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport com.android.internal.util.HierarchicalStateMachine;
31fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport com.android.internal.util.HierarchicalState;
32fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport com.android.internal.util.ProcessedMessages;
33fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
34fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport java.util.ArrayList;
35fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleimport java.util.Arrays;
36fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
37fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville/**
38fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * Test for HierarchicalStateMachine.
39fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville *
40fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville * @author wink@google.com (Wink Saville)
41fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville */
42fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savillepublic class HierarchicalStateMachineTest extends TestCase {
43fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private static final int TEST_CMD_1 = 1;
44fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private static final int TEST_CMD_2 = 2;
45fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private static final int TEST_CMD_3 = 3;
46fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private static final int TEST_CMD_4 = 4;
47fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private static final int TEST_CMD_5 = 5;
48fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private static final int TEST_CMD_6 = 6;
49fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
50fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private static final boolean DBG = true;
51fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private static final boolean WAIT_FOR_DEBUGGER = false;
52fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private static final String TAG = "HierarchicalStateMachineTest";
53fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
54fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
551b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     * Tests that we can quit the state machine.
561b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville     */
571b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    class StateMachineQuitTest extends HierarchicalStateMachine {
581b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private int mQuitCount = 0;
591b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
601b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        StateMachineQuitTest(String name) {
611b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            super(name);
621b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            mThisSm = this;
631b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            setDbg(DBG);
641b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
651b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            // Setup state machine with 1 state
661b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            addState(mS1);
671b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
681b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            // Set the initial state
691b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            setInitialState(mS1);
701b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
711b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
721b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        class S1 extends HierarchicalState {
731b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            @Override protected boolean processMessage(Message message) {
741b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                if (isQuit(message)) {
751b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                    mQuitCount += 1;
761b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                    if (mQuitCount > 2) {
771b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                        // Returning false to actually quit
781b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                        return false;
791b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                    } else {
801b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                        // Do NOT quit
811b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                        return true;
821b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                    }
831b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                } else  {
841b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                    // All other message are handled
851b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                    return true;
861b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                }
871b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            }
881b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
891b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
901b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        @Override
911b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        protected void quitting() {
921b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            synchronized (mThisSm) {
931b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                mThisSm.notifyAll();
941b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            }
951b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
961b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
971b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private StateMachineQuitTest mThisSm;
981b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        private S1 mS1 = new S1();
991b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    }
1001b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1011b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    @SmallTest
1021b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    public void testStateMachineQuitTest() throws Exception {
1031b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        //if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
1041b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1051b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        StateMachineQuitTest smQuitTest = new StateMachineQuitTest("smQuitTest");
1061b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        smQuitTest.start();
1071b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        if (smQuitTest.isDbg()) Log.d(TAG, "testStateMachineQuitTest E");
1081b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1091b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        synchronized (smQuitTest) {
1101b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            // Send 6 messages
1111b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            for (int i = 1; i <= 6; i++) {
11291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville                smQuitTest.sendMessage(i);
1131b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            }
1141b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1151b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            // First two are ignored
1161b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            smQuitTest.quit();
1171b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            smQuitTest.quit();
1181b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1191b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            // Now we will quit
1201b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            smQuitTest.quit();
1211b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1221b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            try {
1231b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                // wait for the messages to be handled
1241b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                smQuitTest.wait();
1251b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            } catch (InterruptedException e) {
1261b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville                Log.e(TAG, "testStateMachineQuitTest: exception while waiting " + e.getMessage());
1271b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville            }
1281b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        }
1291b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1301b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        assertTrue(smQuitTest.getProcessedMessagesCount() == 9);
1311b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1321b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        ProcessedMessages.Info pmi;
1331b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1341b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        // The first two message didn't quit and were handled by mS1
1351b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        pmi = smQuitTest.getProcessedMessage(6);
1361b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        assertEquals(HierarchicalStateMachine.HSM_QUIT_CMD, pmi.getWhat());
1371b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        assertEquals(smQuitTest.mS1, pmi.getState());
1381b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        assertEquals(smQuitTest.mS1, pmi.getOriginalState());
1391b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1401b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        pmi = smQuitTest.getProcessedMessage(7);
1411b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        assertEquals(HierarchicalStateMachine.HSM_QUIT_CMD, pmi.getWhat());
1421b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        assertEquals(smQuitTest.mS1, pmi.getState());
1431b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        assertEquals(smQuitTest.mS1, pmi.getOriginalState());
1441b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1451b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        // The last message was never handled so the states are null
1461b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        pmi = smQuitTest.getProcessedMessage(8);
1471b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        assertEquals(HierarchicalStateMachine.HSM_QUIT_CMD, pmi.getWhat());
1481b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        assertEquals(null, pmi.getState());
1491b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        assertEquals(null, pmi.getOriginalState());
1501b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1511b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        if (smQuitTest.isDbg()) Log.d(TAG, "testStateMachineQuitTest X");
1521b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    }
1531b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville
1541b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville    /**
155fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Tests that ProcessedMessage works as a circular buffer.
156fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
157fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class StateMachine0 extends HierarchicalStateMachine {
158fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine0(String name) {
159fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            super(name);
160fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mThisSm = this;
161fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setDbg(DBG);
162fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setProcessedMessagesSize(3);
163fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
164fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Setup state machine with 1 state
165fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS1);
166fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
167fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Set the initial state
168fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setInitialState(mS1);
169fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
170fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
171fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class S1 extends HierarchicalState {
172fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
173fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (message.what == TEST_CMD_6) {
174fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    transitionToHaltingState();
175fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
176fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
177fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
178fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
179fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
180fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
181fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        protected void halting() {
182fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            synchronized (mThisSm) {
183fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mThisSm.notifyAll();
184fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
185fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
186fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
187fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateMachine0 mThisSm;
188fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private S1 mS1 = new S1();
189fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
190fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
191fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    @SmallTest
192fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void testStateMachine0() throws Exception {
1931b8b98b3db5dcf0b01d1a632aafea076cc91f5a4Wink Saville        //if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
194fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
195fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine0 sm0 = new StateMachine0("sm0");
196fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        sm0.start();
197fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm0.isDbg()) Log.d(TAG, "testStateMachine0 E");
198fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
199fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (sm0) {
200fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Send 6 messages
201fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (int i = 1; i <= 6; i++) {
202fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sm0.sendMessage(sm0.obtainMessage(i));
203fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
204fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
205fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            try {
206fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // wait for the messages to be handled
207fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sm0.wait();
208fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } catch (InterruptedException e) {
209fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.e(TAG, "testStateMachine0: exception while waiting " + e.getMessage());
210fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
211fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
212fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
213fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertTrue(sm0.getProcessedMessagesCount() == 6);
214fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertTrue(sm0.getProcessedMessagesSize() == 3);
215fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
216fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        ProcessedMessages.Info pmi;
217fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm0.getProcessedMessage(0);
218fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_4, pmi.getWhat());
219fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm0.mS1, pmi.getState());
220fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm0.mS1, pmi.getOriginalState());
221fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
222fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm0.getProcessedMessage(1);
223fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_5, pmi.getWhat());
224fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm0.mS1, pmi.getState());
225fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm0.mS1, pmi.getOriginalState());
226fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
227fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm0.getProcessedMessage(2);
228fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_6, pmi.getWhat());
229fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm0.mS1, pmi.getState());
230fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm0.mS1, pmi.getOriginalState());
231fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
232fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm0.isDbg()) Log.d(TAG, "testStateMachine0 X");
233fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
234fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
235fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
236fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * This tests enter/exit and transitions to the same state.
237fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * The state machine has one state, it receives two messages
238fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * in state mS1. With the first message it transitions to
239fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * itself which causes it to be exited and reentered.
240fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
241fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class StateMachine1 extends HierarchicalStateMachine {
242fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine1(String name) {
243fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            super(name);
244fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mThisSm = this;
245fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setDbg(DBG);
246fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
247fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Setup state machine with 1 state
248fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS1);
249fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
250fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Set the initial state
251fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setInitialState(mS1);
252fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (DBG) Log.d(TAG, "StateMachine1: ctor X");
253fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
254fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
255fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class S1 extends HierarchicalState {
256fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void enter() {
257fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mEnterCount++;
258fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
259fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
260fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
261fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (message.what == TEST_CMD_1) {
262fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    assertEquals(1, mEnterCount);
263fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    assertEquals(0, mExitCount);
264fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    transitionTo(mS1);
265fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                } else if (message.what == TEST_CMD_2) {
266fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    assertEquals(2, mEnterCount);
267fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    assertEquals(1, mExitCount);
268fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    transitionToHaltingState();
269fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
270fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
271fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
272fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
273fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void exit() {
274fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mExitCount++;
275fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
276fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
277fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
278fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
279fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        protected void halting() {
280fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            synchronized (mThisSm) {
281fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mThisSm.notifyAll();
282fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
283fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
284fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
285fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateMachine1 mThisSm;
286fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private S1 mS1 = new S1();
287fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
288fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mEnterCount;
289fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mExitCount;
290fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
291fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
292fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    @SmallTest
293fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void testStateMachine1() throws Exception {
294fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine1 sm1 = new StateMachine1("sm1");
295fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        sm1.start();
296fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm1.isDbg()) Log.d(TAG, "testStateMachine1 E");
297fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
298fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (sm1) {
299fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Send two messages
30091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm1.sendMessage(TEST_CMD_1);
30191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm1.sendMessage(TEST_CMD_2);
302fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
303fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            try {
304fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // wait for the messages to be handled
305fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sm1.wait();
306fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } catch (InterruptedException e) {
307fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.e(TAG, "testStateMachine1: exception while waiting " + e.getMessage());
308fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
309fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
310fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
311fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(2, sm1.mEnterCount);
312fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(2, sm1.mExitCount);
313fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
314fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertTrue(sm1.getProcessedMessagesSize() == 2);
315fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
316fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        ProcessedMessages.Info pmi;
317fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm1.getProcessedMessage(0);
318fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_1, pmi.getWhat());
319fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm1.mS1, pmi.getState());
320fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm1.mS1, pmi.getOriginalState());
321fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
322fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm1.getProcessedMessage(1);
323fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_2, pmi.getWhat());
324fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm1.mS1, pmi.getState());
325fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm1.mS1, pmi.getOriginalState());
326fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
327fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(2, sm1.mEnterCount);
328fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(2, sm1.mExitCount);
329fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
330fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm1.isDbg()) Log.d(TAG, "testStateMachine1 X");
331fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
332fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
333fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
334fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Test deferring messages and states with no parents. The state machine
335fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * has two states, it receives two messages in state mS1 deferring them
336fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * until what == TEST_CMD_2 and then transitions to state mS2. State
337fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * mS2 then receives both of the deferred messages first TEST_CMD_1 and
338fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * then TEST_CMD_2.
339fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
340fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class StateMachine2 extends HierarchicalStateMachine {
341fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine2(String name) {
342fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            super(name);
343fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mThisSm = this;
344fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setDbg(DBG);
345fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
346fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Setup the hierarchy
347fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS1);
348fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS2);
349fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
350fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Set the initial state
351fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setInitialState(mS1);
352fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (DBG) Log.d(TAG, "StateMachine2: ctor X");
353fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
354fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
355fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class S1 extends HierarchicalState {
356fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void enter() {
357fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mDidEnter = true;
358fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
359fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
360fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
361fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                deferMessage(message);
362fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (message.what == TEST_CMD_2) {
363fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    transitionTo(mS2);
364fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
365fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
366fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
367fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
368fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void exit() {
369fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mDidExit = true;
370fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
371fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
372fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
373fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class S2 extends HierarchicalState {
374fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
375fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (message.what == TEST_CMD_2) {
376fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    transitionToHaltingState();
377fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
378fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
379fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
380fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
381fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
382fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
383fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        protected void halting() {
384fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            synchronized (mThisSm) {
385fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mThisSm.notifyAll();
386fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
387fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
388fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
389fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateMachine2 mThisSm;
390fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private S1 mS1 = new S1();
391fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private S2 mS2 = new S2();
392fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
393fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private boolean mDidEnter = false;
394fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private boolean mDidExit = false;
395fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
396fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
397fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    @SmallTest
398fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void testStateMachine2() throws Exception {
399fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine2 sm2 = new StateMachine2("sm2");
400fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        sm2.start();
401fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm2.isDbg()) Log.d(TAG, "testStateMachine2 E");
402fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
403fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (sm2) {
404fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Send two messages
40591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm2.sendMessage(TEST_CMD_1);
40691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm2.sendMessage(TEST_CMD_2);
407fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
408fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            try {
409fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // wait for the messages to be handled
410fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sm2.wait();
411fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } catch (InterruptedException e) {
412fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.e(TAG, "testStateMachine2: exception while waiting " + e.getMessage());
413fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
414fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
415fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
416fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertTrue(sm2.getProcessedMessagesSize() == 4);
417fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
418fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        ProcessedMessages.Info pmi;
419fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm2.getProcessedMessage(0);
420fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_1, pmi.getWhat());
421fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm2.mS1, pmi.getState());
422fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
423fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm2.getProcessedMessage(1);
424fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_2, pmi.getWhat());
425fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm2.mS1, pmi.getState());
426fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
427fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm2.getProcessedMessage(2);
428fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_1, pmi.getWhat());
429fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm2.mS2, pmi.getState());
430fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
431fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm2.getProcessedMessage(3);
432fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_2, pmi.getWhat());
433fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm2.mS2, pmi.getState());
434fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
435fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertTrue(sm2.mDidEnter);
436fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertTrue(sm2.mDidExit);
437fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
438fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm2.isDbg()) Log.d(TAG, "testStateMachine2 X");
439fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
440fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
441fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
442fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Test that unhandled messages in a child are handled by the parent.
443fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * When TEST_CMD_2 is received.
444fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
445fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class StateMachine3 extends HierarchicalStateMachine {
446fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine3(String name) {
447fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            super(name);
448fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mThisSm = this;
449fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setDbg(DBG);
450fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
451fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Setup the simplest hierarchy of two states
452fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // mParentState and mChildState.
453fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // (Use indentation to help visualize hierarchy)
454fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mParentState);
455fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                addState(mChildState, mParentState);
456fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
457fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Set the initial state will be the child
458fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setInitialState(mChildState);
459fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (DBG) Log.d(TAG, "StateMachine3: ctor X");
460fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
461fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
462fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class ParentState extends HierarchicalState {
463fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
464fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (message.what == TEST_CMD_2) {
465fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    transitionToHaltingState();
466fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
467fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
468fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
469fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
470fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
471fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class ChildState extends HierarchicalState {
472fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
473fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return false;
474fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
475fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
476fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
477fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
478fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        protected void halting() {
479fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            synchronized (mThisSm) {
480fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mThisSm.notifyAll();
481fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
482fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
483fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
484fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateMachine3 mThisSm;
485fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ParentState mParentState = new ParentState();
486fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ChildState mChildState = new ChildState();
487fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
488fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
489fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    @SmallTest
490fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void testStateMachine3() throws Exception {
491fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine3 sm3 = new StateMachine3("sm3");
492fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        sm3.start();
493fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm3.isDbg()) Log.d(TAG, "testStateMachine3 E");
494fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
495fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (sm3) {
496fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Send two messages
49791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm3.sendMessage(TEST_CMD_1);
49891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm3.sendMessage(TEST_CMD_2);
499fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
500fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            try {
501fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // wait for the messages to be handled
502fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sm3.wait();
503fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } catch (InterruptedException e) {
504fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.e(TAG, "testStateMachine3: exception while waiting " + e.getMessage());
505fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
506fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
507fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
508fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertTrue(sm3.getProcessedMessagesSize() == 2);
509fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
510fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        ProcessedMessages.Info pmi;
511fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm3.getProcessedMessage(0);
512fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_1, pmi.getWhat());
513fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm3.mParentState, pmi.getState());
514fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm3.mChildState, pmi.getOriginalState());
515fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
516fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm3.getProcessedMessage(1);
517fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_2, pmi.getWhat());
518fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm3.mParentState, pmi.getState());
519fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm3.mChildState, pmi.getOriginalState());
520fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
521fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm3.isDbg()) Log.d(TAG, "testStateMachine3 X");
522fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
523fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
524fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
525fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Test a hierarchy of 3 states a parent and two children
526fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * with transition from child 1 to child 2 and child 2
527fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * lets the parent handle the messages.
528fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
529fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class StateMachine4 extends HierarchicalStateMachine {
530fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine4(String name) {
531fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            super(name);
532fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mThisSm = this;
533fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setDbg(DBG);
534fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
535fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Setup a hierarchy of three states
536fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // mParentState, mChildState1 & mChildState2
537fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // (Use indentation to help visualize hierarchy)
538fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mParentState);
539fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                addState(mChildState1, mParentState);
540fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                addState(mChildState2, mParentState);
541fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
542fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Set the initial state will be child 1
543fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setInitialState(mChildState1);
544fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (DBG) Log.d(TAG, "StateMachine4: ctor X");
545fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
546fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
547fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class ParentState extends HierarchicalState {
548fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
549fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (message.what == TEST_CMD_2) {
550fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    transitionToHaltingState();
551fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
552fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
553fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
554fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
555fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
556fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class ChildState1 extends HierarchicalState {
557fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
558fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mChildState2);
559fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
560fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
561fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
562fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
563fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class ChildState2 extends HierarchicalState {
564fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
565fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return false;
566fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
567fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
568fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
569fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
570fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        protected void halting() {
571fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            synchronized (mThisSm) {
572fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mThisSm.notifyAll();
573fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
574fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
575fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
576fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateMachine4 mThisSm;
577fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ParentState mParentState = new ParentState();
578fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ChildState1 mChildState1 = new ChildState1();
579fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ChildState2 mChildState2 = new ChildState2();
580fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
581fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
582fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    @SmallTest
583fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void testStateMachine4() throws Exception {
584fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine4 sm4 = new StateMachine4("sm4");
585fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        sm4.start();
586fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm4.isDbg()) Log.d(TAG, "testStateMachine4 E");
587fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
588fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (sm4) {
589fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Send two messages
59091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm4.sendMessage(TEST_CMD_1);
59191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm4.sendMessage(TEST_CMD_2);
592fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
593fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            try {
594fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // wait for the messages to be handled
595fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sm4.wait();
596fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } catch (InterruptedException e) {
597fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.e(TAG, "testStateMachine4: exception while waiting " + e.getMessage());
598fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
599fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
600fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
601fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
602fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertTrue(sm4.getProcessedMessagesSize() == 2);
603fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
604fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        ProcessedMessages.Info pmi;
605fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm4.getProcessedMessage(0);
606fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_1, pmi.getWhat());
607fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm4.mChildState1, pmi.getState());
608fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm4.mChildState1, pmi.getOriginalState());
609fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
610fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm4.getProcessedMessage(1);
611fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_2, pmi.getWhat());
612fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm4.mParentState, pmi.getState());
613fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm4.mChildState2, pmi.getOriginalState());
614fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
615fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm4.isDbg()) Log.d(TAG, "testStateMachine4 X");
616fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
617fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
618fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
619fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Test transition from one child to another of a "complex"
620fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * hierarchy with two parents and multiple children.
621fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
622fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class StateMachine5 extends HierarchicalStateMachine {
623fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine5(String name) {
624fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            super(name);
625fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mThisSm = this;
626fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setDbg(DBG);
627fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
628fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Setup a hierarchy with two parents and some children.
629fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // (Use indentation to help visualize hierarchy)
630fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mParentState1);
631fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                addState(mChildState1, mParentState1);
632fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                addState(mChildState2, mParentState1);
633fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
634fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mParentState2);
635fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                addState(mChildState3, mParentState2);
636fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                addState(mChildState4, mParentState2);
637fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    addState(mChildState5, mChildState4);
638fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
639fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Set the initial state will be the child
640fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setInitialState(mChildState1);
641fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (DBG) Log.d(TAG, "StateMachine5: ctor X");
642fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
643fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
644fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class ParentState1 extends HierarchicalState {
645fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void enter() {
646fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mParentState1EnterCount += 1;
647fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
648fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
649fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
650fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
651fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void exit() {
652fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mParentState1ExitCount += 1;
653fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
654fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
655fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
656fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class ChildState1 extends HierarchicalState {
657fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void enter() {
658fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mChildState1EnterCount += 1;
659fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
660fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
661fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState1EnterCount);
662fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mParentState1ExitCount);
663fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState1EnterCount);
664fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState1ExitCount);
665fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState2EnterCount);
666fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState2ExitCount);
667fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mParentState2EnterCount);
668fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mParentState2ExitCount);
669fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState3EnterCount);
670fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState3ExitCount);
671fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState4EnterCount);
672fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState4ExitCount);
673fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState5EnterCount);
674fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState5ExitCount);
675fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
676fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mChildState2);
677fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
678fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
679fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void exit() {
680fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mChildState1ExitCount += 1;
681fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
682fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
683fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
684fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class ChildState2 extends HierarchicalState {
685fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void enter() {
686fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mChildState2EnterCount += 1;
687fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
688fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
689fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState1EnterCount);
690fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mParentState1ExitCount);
691fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState1EnterCount);
692fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState1ExitCount);
693fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState2EnterCount);
694fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState2ExitCount);
695fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mParentState2EnterCount);
696fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mParentState2ExitCount);
697fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState3EnterCount);
698fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState3ExitCount);
699fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState4EnterCount);
700fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState4ExitCount);
701fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState5EnterCount);
702fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState5ExitCount);
703fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
704fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mChildState5);
705fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
706fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
707fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void exit() {
708fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mChildState2ExitCount += 1;
709fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
710fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
711fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
712fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class ParentState2 extends HierarchicalState {
713fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void enter() {
714fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mParentState2EnterCount += 1;
715fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
716fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
717fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState1EnterCount);
718fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState1ExitCount);
719fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState1EnterCount);
720fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState1ExitCount);
721fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState2EnterCount);
722fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState2ExitCount);
723fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(2, mParentState2EnterCount);
724fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState2ExitCount);
725fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState3EnterCount);
726fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState3ExitCount);
727fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(2, mChildState4EnterCount);
728fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(2, mChildState4ExitCount);
729fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState5EnterCount);
730fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState5ExitCount);
731fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
732fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionToHaltingState();
733fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
734fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
735fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void exit() {
736fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mParentState2ExitCount += 1;
737fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
738fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
739fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
740fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class ChildState3 extends HierarchicalState {
741fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void enter() {
742fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mChildState3EnterCount += 1;
743fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
744fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
745fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState1EnterCount);
746fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState1ExitCount);
747fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState1EnterCount);
748fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState1ExitCount);
749fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState2EnterCount);
750fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState2ExitCount);
751fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState2EnterCount);
752fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mParentState2ExitCount);
753fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState3EnterCount);
754fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState3ExitCount);
755fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState4EnterCount);
756fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState4ExitCount);
757fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState5EnterCount);
758fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState5ExitCount);
759fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
760fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mChildState4);
761fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
762fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
763fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void exit() {
764fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mChildState3ExitCount += 1;
765fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
766fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
767fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
768fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class ChildState4 extends HierarchicalState {
769fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void enter() {
770fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mChildState4EnterCount += 1;
771fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
772fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
773fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState1EnterCount);
774fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState1ExitCount);
775fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState1EnterCount);
776fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState1ExitCount);
777fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState2EnterCount);
778fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState2ExitCount);
779fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState2EnterCount);
780fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mParentState2ExitCount);
781fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState3EnterCount);
782fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState3ExitCount);
783fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(2, mChildState4EnterCount);
784fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState4ExitCount);
785fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState5EnterCount);
786fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState5ExitCount);
787fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
788fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mParentState2);
789fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
790fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
791fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void exit() {
792fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mChildState4ExitCount += 1;
793fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
794fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
795fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
796fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class ChildState5 extends HierarchicalState {
797fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void enter() {
798fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mChildState5EnterCount += 1;
799fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
800fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
801fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState1EnterCount);
802fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState1ExitCount);
803fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState1EnterCount);
804fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState1ExitCount);
805fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState2EnterCount);
806fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState2ExitCount);
807fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mParentState2EnterCount);
808fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mParentState2ExitCount);
809fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState3EnterCount);
810fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState3ExitCount);
811fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState4EnterCount);
812fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState4ExitCount);
813fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(1, mChildState5EnterCount);
814fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(0, mChildState5ExitCount);
815fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
816fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mChildState3);
817fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
818fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
819fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void exit() {
820fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mChildState5ExitCount += 1;
821fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
822fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
823fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
824fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
825fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        protected void halting() {
826fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            synchronized (mThisSm) {
827fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mThisSm.notifyAll();
828fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
829fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
830fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
831fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateMachine5 mThisSm;
832fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ParentState1 mParentState1 = new ParentState1();
833fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ChildState1 mChildState1 = new ChildState1();
834fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ChildState2 mChildState2 = new ChildState2();
835fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ParentState2 mParentState2 = new ParentState2();
836fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ChildState3 mChildState3 = new ChildState3();
837fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ChildState4 mChildState4 = new ChildState4();
838fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private ChildState5 mChildState5 = new ChildState5();
839fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
840fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mParentState1EnterCount = 0;
841fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mParentState1ExitCount = 0;
842fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mChildState1EnterCount = 0;
843fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mChildState1ExitCount = 0;
844fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mChildState2EnterCount = 0;
845fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mChildState2ExitCount = 0;
846fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mParentState2EnterCount = 0;
847fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mParentState2ExitCount = 0;
848fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mChildState3EnterCount = 0;
849fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mChildState3ExitCount = 0;
850fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mChildState4EnterCount = 0;
851fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mChildState4ExitCount = 0;
852fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mChildState5EnterCount = 0;
853fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mChildState5ExitCount = 0;
854fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
855fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
856fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    @SmallTest
857fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void testStateMachine5() throws Exception {
858fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine5 sm5 = new StateMachine5("sm5");
859fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        sm5.start();
860fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm5.isDbg()) Log.d(TAG, "testStateMachine5 E");
861fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
862fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (sm5) {
863fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Send 6 messages
86491fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm5.sendMessage(TEST_CMD_1);
86591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm5.sendMessage(TEST_CMD_2);
86691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm5.sendMessage(TEST_CMD_3);
86791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm5.sendMessage(TEST_CMD_4);
86891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm5.sendMessage(TEST_CMD_5);
86991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm5.sendMessage(TEST_CMD_6);
870fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
871fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            try {
872fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // wait for the messages to be handled
873fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sm5.wait();
874fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } catch (InterruptedException e) {
875fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.e(TAG, "testStateMachine5: exception while waiting " + e.getMessage());
876fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
877fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
878fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
879fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
880fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertTrue(sm5.getProcessedMessagesSize() == 6);
881fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
882fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(1, sm5.mParentState1EnterCount);
883fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(1, sm5.mParentState1ExitCount);
884fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(1, sm5.mChildState1EnterCount);
885fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(1, sm5.mChildState1ExitCount);
886fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(1, sm5.mChildState2EnterCount);
887fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(1, sm5.mChildState2ExitCount);
888fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(2, sm5.mParentState2EnterCount);
889fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(2, sm5.mParentState2ExitCount);
890fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(1, sm5.mChildState3EnterCount);
891fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(1, sm5.mChildState3ExitCount);
892fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(2, sm5.mChildState4EnterCount);
893fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(2, sm5.mChildState4ExitCount);
894fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(1, sm5.mChildState5EnterCount);
895fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(1, sm5.mChildState5ExitCount);
896fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
897fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        ProcessedMessages.Info pmi;
898fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm5.getProcessedMessage(0);
899fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_1, pmi.getWhat());
900fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm5.mChildState1, pmi.getState());
901fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm5.mChildState1, pmi.getOriginalState());
902fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
903fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm5.getProcessedMessage(1);
904fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_2, pmi.getWhat());
905fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm5.mChildState2, pmi.getState());
906fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm5.mChildState2, pmi.getOriginalState());
907fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
908fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm5.getProcessedMessage(2);
909fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_3, pmi.getWhat());
910fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm5.mChildState5, pmi.getState());
911fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm5.mChildState5, pmi.getOriginalState());
912fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
913fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm5.getProcessedMessage(3);
914fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_4, pmi.getWhat());
915fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm5.mChildState3, pmi.getState());
916fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm5.mChildState3, pmi.getOriginalState());
917fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
918fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm5.getProcessedMessage(4);
919fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_5, pmi.getWhat());
920fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm5.mChildState4, pmi.getState());
921fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm5.mChildState4, pmi.getOriginalState());
922fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
923fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm5.getProcessedMessage(5);
924fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(TEST_CMD_6, pmi.getWhat());
925fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm5.mParentState2, pmi.getState());
926fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm5.mParentState2, pmi.getOriginalState());
927fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
928fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm5.isDbg()) Log.d(TAG, "testStateMachine5 X");
929fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
930fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
931fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
932fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Test that the initial state enter is invoked immediately
933fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * after construction and before any other messages arrive and that
934fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * sendMessageDelayed works.
935fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
936fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class StateMachine6 extends HierarchicalStateMachine {
937fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine6(String name) {
938fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            super(name);
939fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mThisSm = this;
940fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setDbg(DBG);
941fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
942fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Setup state machine with 1 state
943fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS1);
944fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
945fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Set the initial state
946fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setInitialState(mS1);
947fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (DBG) Log.d(TAG, "StateMachine6: ctor X");
948fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
949fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
950fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class S1 extends HierarchicalState {
951fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
952fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void enter() {
95391fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville                sendMessage(TEST_CMD_1);
954fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
955fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
956fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
957fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (message.what == TEST_CMD_1) {
958fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    mArrivalTimeMsg1 = SystemClock.elapsedRealtime();
959fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                } else if (message.what == TEST_CMD_2) {
960fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    mArrivalTimeMsg2 = SystemClock.elapsedRealtime();
961fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    transitionToHaltingState();
962fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
963fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
964fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
965fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
966fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void exit() {
967fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
968fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
969fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
970fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
971fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        protected void halting() {
972fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            synchronized (mThisSm) {
973fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mThisSm.notifyAll();
974fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
975fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
976fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
977fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateMachine6 mThisSm;
978fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private S1 mS1 = new S1();
979fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
980fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private long mArrivalTimeMsg1;
981fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private long mArrivalTimeMsg2;
982fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
983fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
984fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    @SmallTest
985fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void testStateMachine6() throws Exception {
986fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        long sentTimeMsg2;
987fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        final int DELAY_TIME = 250;
988fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        final int DELAY_FUDGE = 20;
989fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
990fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine6 sm6 = new StateMachine6("sm6");
991fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        sm6.start();
992fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm6.isDbg()) Log.d(TAG, "testStateMachine6 E");
993fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
994fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (sm6) {
995fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Send a message
996fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            sentTimeMsg2 = SystemClock.elapsedRealtime();
99791fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm6.sendMessageDelayed(TEST_CMD_2, DELAY_TIME);
998fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
999fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            try {
1000fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // wait for the messages to be handled
1001fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sm6.wait();
1002fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } catch (InterruptedException e) {
1003fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.e(TAG, "testStateMachine6: exception while waiting " + e.getMessage());
1004fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1005fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1006fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1007fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1008fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * TEST_CMD_1 was sent in enter and must always have been processed
1009fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * immediately after construction and hence the arrival time difference
1010fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * should always >= to the DELAY_TIME
1011fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1012fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        long arrivalTimeDiff = sm6.mArrivalTimeMsg2 - sm6.mArrivalTimeMsg1;
1013fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        long expectedDelay = DELAY_TIME - DELAY_FUDGE;
1014fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm6.isDbg()) Log.d(TAG, "testStateMachine6: expect " + arrivalTimeDiff
1015fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                                    + " >= " + expectedDelay);
1016fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertTrue(arrivalTimeDiff >= expectedDelay);
1017fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1018fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm6.isDbg()) Log.d(TAG, "testStateMachine6 X");
1019fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1020fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1021fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1022fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Test that enter is invoked immediately after exit. This validates
1023fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * that enter can be used to send a watch dog message for its state.
1024fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1025fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class StateMachine7 extends HierarchicalStateMachine {
1026fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private final int SM7_DELAY_TIME = 250;
1027fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1028fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine7(String name) {
1029fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            super(name);
1030fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mThisSm = this;
1031fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setDbg(DBG);
1032fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1033fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Setup state machine with 1 state
1034fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS1);
1035fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS2);
1036fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1037fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Set the initial state
1038fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setInitialState(mS1);
1039fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (DBG) Log.d(TAG, "StateMachine7: ctor X");
1040fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1041fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1042fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class S1 extends HierarchicalState {
1043fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
1044fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mS2);
1045fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
1046fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1047fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void exit() {
104891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville                sendMessage(TEST_CMD_2);
1049fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1050fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1051fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1052fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class S2 extends HierarchicalState {
1053fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1054fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void enter() {
1055fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // Send a delayed message as a watch dog
105691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville                sendMessageDelayed(TEST_CMD_3, SM7_DELAY_TIME);
1057fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1058fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1059fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
1060fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (message.what == TEST_CMD_2) {
1061fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    mMsgCount += 1;
1062fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    mArrivalTimeMsg2 = SystemClock.elapsedRealtime();
1063fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                } else if (message.what == TEST_CMD_3) {
1064fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    mMsgCount += 1;
1065fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    mArrivalTimeMsg3 = SystemClock.elapsedRealtime();
1066fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
1067fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1068fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (mMsgCount == 2) {
1069fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    transitionToHaltingState();
1070fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
1071fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
1072fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1073fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1074fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected void exit() {
1075fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1076fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1077fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1078fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
1079fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        protected void halting() {
1080fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            synchronized (mThisSm) {
1081fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mThisSm.notifyAll();
1082fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1083fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1084fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1085fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateMachine7 mThisSm;
1086fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private S1 mS1 = new S1();
1087fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private S2 mS2 = new S2();
1088fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1089fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mMsgCount = 0;
1090fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private long mArrivalTimeMsg2;
1091fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private long mArrivalTimeMsg3;
1092fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1093fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1094fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    @SmallTest
1095fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void testStateMachine7() throws Exception {
1096fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        long sentTimeMsg2;
1097fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        final int SM7_DELAY_FUDGE = 20;
1098fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1099fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachine7 sm7 = new StateMachine7("sm7");
1100fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        sm7.start();
1101fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm7.isDbg()) Log.d(TAG, "testStateMachine7 E");
1102fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1103fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (sm7) {
1104fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Send a message
1105fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            sentTimeMsg2 = SystemClock.elapsedRealtime();
110691fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sm7.sendMessage(TEST_CMD_1);
1107fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1108fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            try {
1109fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // wait for the messages to be handled
1110fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sm7.wait();
1111fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } catch (InterruptedException e) {
1112fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.e(TAG, "testStateMachine7: exception while waiting " + e.getMessage());
1113fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1114fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1115fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1116fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        /**
1117fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * TEST_CMD_3 was sent in S2.enter with a delay and must always have been
1118fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * processed immediately after S1.exit. Since S1.exit sent TEST_CMD_2
1119fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         * without a delay the arrival time difference should always >= to SM7_DELAY_TIME.
1120fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville         */
1121fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        long arrivalTimeDiff = sm7.mArrivalTimeMsg3 - sm7.mArrivalTimeMsg2;
1122fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        long expectedDelay = sm7.SM7_DELAY_TIME - SM7_DELAY_FUDGE;
1123fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm7.isDbg()) Log.d(TAG, "testStateMachine7: expect " + arrivalTimeDiff
1124fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                                    + " >= " + expectedDelay);
1125fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertTrue(arrivalTimeDiff >= expectedDelay);
1126fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1127fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm7.isDbg()) Log.d(TAG, "testStateMachine7 X");
1128fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1129fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1130fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1131fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Test unhandledMessage.
1132fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1133fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class StateMachineUnhandledMessage extends HierarchicalStateMachine {
1134fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachineUnhandledMessage(String name) {
1135fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            super(name);
1136fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mThisSm = this;
1137fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setDbg(DBG);
1138fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1139fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Setup state machine with 1 state
1140fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS1);
1141fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1142fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Set the initial state
1143fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setInitialState(mS1);
1144fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1145fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1146fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override protected void unhandledMessage(Message message) {
1147fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mUnhandledMessageCount += 1;
1148fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1149fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1150fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class S1 extends HierarchicalState {
1151fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
1152fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (message.what == TEST_CMD_2) {
1153fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    transitionToHaltingState();
1154fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
1155fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return false;
1156fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1157fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1158fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1159fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
1160fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        protected void halting() {
1161fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            synchronized (mThisSm) {
1162fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                mThisSm.notifyAll();
1163fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1164fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1165fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1166fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private StateMachineUnhandledMessage mThisSm;
1167fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mUnhandledMessageCount;
1168fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private S1 mS1 = new S1();
1169fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1170fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1171fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    @SmallTest
1172fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void testStateMachineUnhandledMessage() throws Exception {
1173fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1174fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachineUnhandledMessage sm = new StateMachineUnhandledMessage("sm");
1175fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        sm.start();
1176fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm.isDbg()) Log.d(TAG, "testStateMachineUnhandledMessage E");
1177fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1178fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (sm) {
1179fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Send 2 messages
1180fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (int i = 1; i <= 2; i++) {
118191fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville                sm.sendMessage(i);
1182fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1183fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1184fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            try {
1185fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // wait for the messages to be handled
1186fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sm.wait();
1187fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } catch (InterruptedException e) {
1188fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.e(TAG, "testStateMachineUnhandledMessage: exception while waiting "
1189fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                        + e.getMessage());
1190fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1191fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1192fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1193fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertTrue(sm.getProcessedMessagesCount() == 2);
1194fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(2, sm.mUnhandledMessageCount);
1195fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1196fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (sm.isDbg()) Log.d(TAG, "testStateMachineUnhandledMessage X");
1197fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1198fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1199fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    /**
1200fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * Test state machines sharing the same thread/looper. Multiple instances
1201fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * of the same state machine will be created. They will all share the
1202fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * same thread and thus each can update <code>sharedCounter</code> which
1203fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * will be used to notify testStateMachineSharedThread that the test is
1204fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     * complete.
1205fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville     */
1206fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class StateMachineSharedThread extends HierarchicalStateMachine {
1207f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville        StateMachineSharedThread(String name, Looper looper, int maxCount) {
1208f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville            super(name, looper);
1209fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            mMaxCount = maxCount;
1210fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setDbg(DBG);
1211fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1212fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Setup state machine with 1 state
1213fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS1);
1214fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1215fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Set the initial state
1216fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            setInitialState(mS1);
1217fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1218fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1219fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        class S1 extends HierarchicalState {
1220fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            @Override protected boolean processMessage(Message message) {
1221fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                if (message.what == TEST_CMD_4) {
1222fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    transitionToHaltingState();
1223fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
1224fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
1225fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1226fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1227fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1228fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override
1229fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        protected void halting() {
1230fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Update the shared counter, which is OK since all state
1231fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // machines are using the same thread.
1232fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            sharedCounter += 1;
1233fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (sharedCounter == mMaxCount) {
1234fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                synchronized (waitObject) {
1235fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                    waitObject.notifyAll();
1236fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
1237fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1238fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1239fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1240fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private int mMaxCount;
1241fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        private S1 mS1 = new S1();
1242fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1243fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private static int sharedCounter = 0;
1244fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private static Object waitObject = new Object();
1245fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1246fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    @SmallTest
1247fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void testStateMachineSharedThread() throws Exception {
1248fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (DBG) Log.d(TAG, "testStateMachineSharedThread E");
1249fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1250fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        // Create and start the handler thread
1251fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        HandlerThread smThread = new HandlerThread("testStateMachineSharedThread");
1252fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        smThread.start();
1253fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1254fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        // Create the state machines
1255fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        StateMachineSharedThread sms[] = new StateMachineSharedThread[10];
1256fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        for (int i = 0; i < sms.length; i++) {
1257f0f566ec4607376583e59964a6a8a6dcb0265c20Wink Saville            sms[i] = new StateMachineSharedThread("sm", smThread.getLooper(), sms.length);
1258fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            sms[i].start();
1259fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1260fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1261fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (waitObject) {
1262fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Send messages to each of the state machines
1263fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (StateMachineSharedThread sm : sms) {
1264fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                for (int i = 1; i <= 4; i++) {
126591fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville                    sm.sendMessage(i);
1266fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                }
1267fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1268fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1269fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Wait for the last state machine to notify its done
1270fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            try {
1271fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                waitObject.wait();
1272fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } catch (InterruptedException e) {
1273fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.e(TAG, "testStateMachineSharedThread: exception while waiting "
1274fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                        + e.getMessage());
1275fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1276fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1277fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1278fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        for (StateMachineSharedThread sm : sms) {
1279fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            assertTrue(sm.getProcessedMessagesCount() == 4);
1280fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            for (int i = 0; i < sm.getProcessedMessagesCount(); i++) {
1281fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                ProcessedMessages.Info pmi = sm.getProcessedMessage(i);
1282fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(i+1, pmi.getWhat());
1283fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(sm.mS1, pmi.getState());
1284fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                assertEquals(sm.mS1, pmi.getOriginalState());
1285fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1286fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1287fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1288fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (DBG) Log.d(TAG, "testStateMachineSharedThread X");
1289fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1290fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1291fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    @SmallTest
1292fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public void testHsm1() throws Exception {
1293fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (DBG) Log.d(TAG, "testHsm1 E");
1294fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1295fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Hsm1 sm = Hsm1.makeHsm1();
1296fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1297fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        // Send messages
129891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville        sm.sendMessage(Hsm1.CMD_1);
129991fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville        sm.sendMessage(Hsm1.CMD_2);
1300fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1301fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (sm) {
1302fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            // Wait for the last state machine to notify its done
1303fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            try {
1304fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                sm.wait();
1305fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } catch (InterruptedException e) {
1306fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                Log.e(TAG, "testHsm1: exception while waiting " + e.getMessage());
1307fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1308fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1309fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1310fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(7, sm.getProcessedMessagesCount());
1311fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        ProcessedMessages.Info pmi = sm.getProcessedMessage(0);
1312fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(Hsm1.CMD_1, pmi.getWhat());
1313fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mS1, pmi.getState());
1314fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mS1, pmi.getOriginalState());
1315fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1316fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm.getProcessedMessage(1);
1317fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(Hsm1.CMD_2, pmi.getWhat());
1318fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mP1, pmi.getState());
1319fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mS1, pmi.getOriginalState());
1320fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1321fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm.getProcessedMessage(2);
1322fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(Hsm1.CMD_2, pmi.getWhat());
1323fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mS2, pmi.getState());
1324fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mS2, pmi.getOriginalState());
1325fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1326fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm.getProcessedMessage(3);
1327fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(Hsm1.CMD_3, pmi.getWhat());
1328fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mS2, pmi.getState());
1329fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mS2, pmi.getOriginalState());
1330fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1331fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm.getProcessedMessage(4);
1332fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(Hsm1.CMD_3, pmi.getWhat());
1333fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mP2, pmi.getState());
1334fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mP2, pmi.getOriginalState());
1335fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1336fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm.getProcessedMessage(5);
1337fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(Hsm1.CMD_4, pmi.getWhat());
1338fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mP2, pmi.getState());
1339fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mP2, pmi.getOriginalState());
1340fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1341fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        pmi = sm.getProcessedMessage(6);
1342fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(Hsm1.CMD_5, pmi.getWhat());
1343fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mP2, pmi.getState());
1344fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        assertEquals(sm.mP2, pmi.getOriginalState());
1345fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1346fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        if (DBG) Log.d(TAG, "testStateMachineSharedThread X");
1347fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1348fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
1349fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1350fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Savilleclass Hsm1 extends HierarchicalStateMachine {
1351fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    private static final String TAG = "hsm1";
1352fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1353fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_1 = 1;
1354fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_2 = 2;
1355fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_3 = 3;
1356fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_4 = 4;
1357fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static final int CMD_5 = 5;
1358fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1359fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    public static Hsm1 makeHsm1() {
1360fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Log.d(TAG, "makeHsm1 E");
1361fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Hsm1 sm = new Hsm1("hsm1");
1362fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        sm.start();
1363fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Log.d(TAG, "makeHsm1 X");
1364fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        return sm;
1365fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1366fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1367fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    Hsm1(String name) {
1368fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        super(name);
1369fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Log.d(TAG, "ctor E");
1370fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1371fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        // Add states, use indentation to show hierarchy
1372fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        addState(mP1);
1373fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS1, mP1);
1374fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            addState(mS2, mP1);
1375fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        addState(mP2);
1376fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1377fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        // Set the initial state
1378fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        setInitialState(mS1);
1379fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Log.d(TAG, "ctor X");
1380fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1381fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1382fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class P1 extends HierarchicalState {
1383fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override protected void enter() {
1384fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "P1.enter");
1385fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1386fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override protected boolean processMessage(Message message) {
1387fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            boolean retVal;
1388fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "P1.processMessage what=" + message.what);
1389fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            switch(message.what) {
1390fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case CMD_2:
1391fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // CMD_2 will arrive in mS2 before CMD_3
139291fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville                sendMessage(CMD_3);
1393fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                deferMessage(message);
1394fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mS2);
1395fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                retVal = true;
1396fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
1397fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            default:
1398fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // Any message we don't understand in this state invokes unhandledMessage
1399fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                retVal = false;
1400fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
1401fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1402fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return retVal;
1403fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1404fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override protected void exit() {
1405fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "P1.exit");
1406fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1407fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1408fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1409fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class S1 extends HierarchicalState {
1410fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override protected void enter() {
1411fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "S1.enter");
1412fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1413fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override protected boolean processMessage(Message message) {
1414fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "S1.processMessage what=" + message.what);
1415fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            if (message.what == CMD_1) {
1416fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // Transition to ourself to show that enter/exit is called
1417fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mS1);
1418fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return true;
1419fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            } else {
1420fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                // Let parent process all other messages
1421fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                return false;
1422fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1423fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1424fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override protected void exit() {
1425fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "S1.exit");
1426fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1427fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1428fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1429fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class S2 extends HierarchicalState {
1430fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override protected void enter() {
1431fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "S2.enter");
1432fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1433fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override protected boolean processMessage(Message message) {
1434fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            boolean retVal;
1435fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "S2.processMessage what=" + message.what);
1436fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            switch(message.what) {
1437fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_2):
143891fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville                sendMessage(CMD_4);
1439fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                retVal = true;
1440fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
1441fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_3):
1442fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                deferMessage(message);
1443fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionTo(mP2);
1444fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                retVal = true;
1445fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
1446fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            default:
1447fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                retVal = false;
1448fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
1449fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1450fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return retVal;
1451fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1452fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override protected void exit() {
1453fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "S2.exit");
1454fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1455fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1456fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1457fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    class P2 extends HierarchicalState {
1458fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override protected void enter() {
1459fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "P2.enter");
146091fbd56757751a7aca8ef2b4d936e587509e6eefWink Saville            sendMessage(CMD_5);
1461fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1462fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override protected boolean processMessage(Message message) {
1463fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "P2.processMessage what=" + message.what);
1464fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            switch(message.what) {
1465fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_3):
1466fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
1467fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_4):
1468fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
1469fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            case(CMD_5):
1470fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                transitionToHaltingState();
1471fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville                break;
1472fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            }
1473fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            return true;
1474fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1475fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        @Override protected void exit() {
1476fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            Log.d(TAG, "P2.exit");
1477fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1478fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1479fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1480fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    @Override
1481fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    protected void halting() {
1482fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        Log.d(TAG, "halting");
1483fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        synchronized (this) {
1484fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville            this.notifyAll();
1485fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville        }
1486fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    }
1487fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville
1488fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    P1 mP1 = new P1();
1489fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    S1 mS1 = new S1();
1490fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    S2 mS2 = new S2();
1491fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville    P2 mP2 = new P2();
1492fc5b4802a544b6ca304aa7e58a26018ef714d233Wink Saville}
1493