Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3059487 authored by Wink Saville's avatar Wink Saville
Browse files

Move ProcessedMessage into HierarchicalStateMachine.

ProcessedMessage is really private to HSM and so moving
it into the HSM class.

Change-Id: Ida476fc7aae5e9bfb6ac632dac979e11f489b6fc
parent 442b08bc
Loading
Loading
Loading
Loading
+190 −17
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.util.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Vector;

/**
 * {@hide}
@@ -433,6 +434,180 @@ public class HierarchicalStateMachine {
     */
    public static final boolean NOT_HANDLED = false;

    /**
     * {@hide}
     *
     * The information maintained for a processed message.
     */
    public static class ProcessedMessageInfo {
        private int what;
        private HierarchicalState state;
        private HierarchicalState orgState;

        /**
         * Constructor
         * @param message
         * @param state that handled the message
         * @param orgState is the first state the received the message but
         * did not processes the message.
         */
        ProcessedMessageInfo(Message message, HierarchicalState state, HierarchicalState orgState) {
            update(message, state, orgState);
        }

        /**
         * Update the information in the record.
         * @param state that handled the message
         * @param orgState is the first state the received the message but
         * did not processes the message.
         */
        public void update(Message message, HierarchicalState state, HierarchicalState orgState) {
            this.what = message.what;
            this.state = state;
            this.orgState = orgState;
        }

        /**
         * @return the command that was executing
         */
        public int getWhat() {
            return what;
        }

        /**
         * @return the state that handled this message
         */
        public HierarchicalState getState() {
            return state;
        }

        /**
         * @return the original state that received the message.
         */
        public HierarchicalState getOriginalState() {
            return orgState;
        }

        /**
         * @return as string
         */
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("what=");
            sb.append(what);
            sb.append(" state=");
            sb.append(cn(state));
            sb.append(" orgState=");
            sb.append(cn(orgState));
            return sb.toString();
        }

        /**
         * @return an objects class name
         */
        private String cn(Object n) {
            if (n == null) {
                return "null";
            } else {
                String name = n.getClass().getName();
                int lastDollar = name.lastIndexOf('$');
                return name.substring(lastDollar + 1);
            }
        }
    }

    /**
     * A list of messages recently processed by the state machine.
     *
     * The class maintains a list of messages that have been most
     * recently processed. The list is finite and may be set in the
     * constructor or by calling setSize. The public interface also
     * includes size which returns the number of recent messages,
     * count which is the number of message processed since the
     * the last setSize, get which returns a processed message and
     * add which adds a processed messaged.
     */
    private static class ProcessedMessages {

        private static final int DEFAULT_SIZE = 20;

        private Vector<ProcessedMessageInfo> mMessages = new Vector<ProcessedMessageInfo>();
        private int mMaxSize = DEFAULT_SIZE;
        private int mOldestIndex = 0;
        private int mCount = 0;

        /**
         * Constructor
         */
        ProcessedMessages() {
        }

        /**
         * Set size of messages to maintain and clears all current messages.
         *
         * @param maxSize number of messages to maintain at anyone time.
        */
        void setSize(int maxSize) {
            mMaxSize = maxSize;
            mCount = 0;
            mMessages.clear();
        }

        /**
         * @return the number of recent messages.
         */
        int size() {
            return mMessages.size();
        }

        /**
         * @return the total number of messages processed since size was set.
         */
        int count() {
            return mCount;
        }

        /**
         * @return the information on a particular record. 0 is the oldest
         * record and size()-1 is the newest record. If the index is to
         * large null is returned.
         */
        ProcessedMessageInfo get(int index) {
            int nextIndex = mOldestIndex + index;
            if (nextIndex >= mMaxSize) {
                nextIndex -= mMaxSize;
            }
            if (nextIndex >= size()) {
                return null;
            } else {
                return mMessages.get(nextIndex);
            }
        }

        /**
         * Add a processed message.
         *
         * @param message
         * @param state that handled the message
         * @param orgState is the first state the received the message but
         * did not processes the message.
         */
        void add(Message message, HierarchicalState state, HierarchicalState orgState) {
            mCount += 1;
            if (mMessages.size() < mMaxSize) {
                mMessages.add(new ProcessedMessageInfo(message, state, orgState));
            } else {
                ProcessedMessageInfo pmi = mMessages.get(mOldestIndex);
                mOldestIndex += 1;
                if (mOldestIndex >= mMaxSize) {
                    mOldestIndex = 0;
                }
                pmi.update(message, state, orgState);
            }
        }
    }

    private static class HsmHandler extends Handler {

        /** The debug flag */
@@ -441,9 +616,6 @@ public class HierarchicalStateMachine {
        /** The quit object */
        private static final Object mQuitObj = new Object();

        /** The initialization message */
        private static final Message mInitMsg = null;

        /** The current message */
        private Message mMsg;

@@ -615,8 +787,9 @@ public class HierarchicalStateMachine {
                     */
                    mHsm.quitting();
                    if (mHsm.mHsmThread != null) {
                        // If we made the thread then quit looper
                        // If we made the thread then quit looper which stops the thread.
                        getLooper().quit();
                        mHsm.mHsmThread = null;
                    }
                } else if (destState == mHaltingState) {
                    /**
@@ -963,8 +1136,8 @@ public class HierarchicalStateMachine {
            return mProcessedMessages.count();
        }

        /** @see HierarchicalStateMachine#getProcessedMessage(int) */
        private final ProcessedMessages.Info getProcessedMessage(int index) {
        /** @see HierarchicalStateMachine#getProcessedMessageInfo(int) */
        private final ProcessedMessageInfo getProcessedMessageInfo(int index) {
            return mProcessedMessages.get(index);
        }

@@ -1090,9 +1263,7 @@ public class HierarchicalStateMachine {
     * @param msg that couldn't be handled.
     */
    protected void unhandledMessage(Message msg) {
        if (false) {
            Log.e(TAG, mName + " - unhandledMessage: msg.what=" + msg.what);
        }
        if (mHsmHandler.mDbg) Log.e(TAG, mName + " - unhandledMessage: msg.what=" + msg.what);
    }

    /**
@@ -1103,16 +1274,18 @@ public class HierarchicalStateMachine {
    }

    /**
     * Called after the message that called transitionToHalting
     * is called and should be overridden by StateMachine's that
     * call transitionToHalting.
     * This will be called once after handling a message that called
     * transitionToHalting. All subsequent messages will invoke
     * {@link HierarchicalStateMachine#haltedProcessMessage(Message)}
     */
    protected void halting() {
    }

    /**
     * Called after the quitting message was NOT handled and
     * just before the quit actually occurs.
     * This will be called once after a quit message that was NOT handled by
     * the derived HSM. The HSM will stop and any subsequent messages will be
     * ignored. In addition, if this HSM created the thread, the thread will
     * be stopped after this method returns.
     */
    protected void quitting() {
    }
@@ -1148,10 +1321,10 @@ public class HierarchicalStateMachine {
    }

    /**
     * @return a processed message
     * @return a processed message information
     */
    public final ProcessedMessages.Info getProcessedMessage(int index) {
        return mHsmHandler.getProcessedMessage(index);
    public final ProcessedMessageInfo getProcessedMessageInfo(int index) {
        return mHsmHandler.getProcessedMessageInfo(index);
    }

    /**
+0 −198
Original line number Diff line number Diff line
/**
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.util;

import android.os.Message;

import java.util.Vector;

/**
 * {@hide}
 *
 * A list of messages recently processed by the state machine.
 *
 * The class maintains a list of messages that have been most
 * recently processed. The list is finite and may be set in the
 * constructor or by calling setSize. The public interface also
 * includes size which returns the number of recent messages,
 * count which is the number of message processed since the
 * the last setSize, get which returns a processed message and
 * add which adds a processed messaged.
 */
public class ProcessedMessages {

    public static final int DEFAULT_SIZE = 20;

    /**
     * The information maintained for a processed message.
     */
    public class Info {
        private int what;
        private HierarchicalState state;
        private HierarchicalState orgState;

        /**
         * Constructor
         * @param message
         * @param state that handled the message
         * @param orgState is the first state the received the message but
         * did not processes the message.
         */
        Info(Message message, HierarchicalState state, HierarchicalState orgState) {
            update(message, state, orgState);
        }

        /**
         * Update the information in the record.
         * @param state that handled the message
         * @param orgState is the first state the received the message but
         * did not processes the message.
         */
        public void update(Message message, HierarchicalState state, HierarchicalState orgState) {
            this.what = message.what;
            this.state = state;
            this.orgState = orgState;
        }

        /**
         * @return the command that was executing
         */
        public int getWhat() {
            return what;
        }

        /**
         * @return the state that handled this message
         */
        public HierarchicalState getState() {
            return state;
        }

        /**
         * @return the original state that received the message.
         */
        public HierarchicalState getOriginalState() {
            return orgState;
        }

        /**
         * @return as string
         */
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("what=");
            sb.append(what);
            sb.append(" state=");
            sb.append(cn(state));
            sb.append(" orgState=");
            sb.append(cn(orgState));
            return sb.toString();
        }

        /**
         * @return an objects class name
         */
        private String cn(Object n) {
            if (n == null) {
                return "null";
            } else {
                String name = n.getClass().getName();
                int lastDollar = name.lastIndexOf('$');
                return name.substring(lastDollar + 1);
            }
        }
    }

    private Vector<Info> mMessages = new Vector<Info>();
    private int mMaxSize = DEFAULT_SIZE;
    private int mOldestIndex = 0;
    private int mCount = 0;

    /**
     * Constructor
     */
    ProcessedMessages() {
    }

    ProcessedMessages(int maxSize) {
        setSize(maxSize);
    }

    /**
     * Set size of messages to maintain and clears all current messages.
     *
     * @param maxSize number of messages to maintain at anyone time.
    */
    void setSize(int maxSize) {
        mMaxSize = maxSize;
        mCount = 0;
        mMessages.clear();
    }

    /**
     * @return the number of recent messages.
     */
    int size() {
        return mMessages.size();
    }

    /**
     * @return the total number of messages processed since size was set.
     */
    int count() {
        return mCount;
    }

    /**
     * @return the information on a particular record. 0 is the oldest
     * record and size()-1 is the newest record. If the index is to
     * large null is returned.
     */
    Info get(int index) {
        int nextIndex = mOldestIndex + index;
        if (nextIndex >= mMaxSize) {
            nextIndex -= mMaxSize;
        }
        if (nextIndex >= size()) {
            return null;
        } else {
            return mMessages.get(nextIndex);
        }
    }

    /**
     * Add a processed message.
     *
     * @param message
     * @param state that handled the message
     * @param orgState is the first state the received the message but
     * did not processes the message.
     */
    void add(Message message, HierarchicalState state, HierarchicalState orgState) {
        mCount += 1;
        if (mMessages.size() < mMaxSize) {
            mMessages.add(new Info(message, state, orgState));
        } else {
            Info info = mMessages.get(mOldestIndex);
            mOldestIndex += 1;
            if (mOldestIndex >= mMaxSize) {
                mOldestIndex = 0;
            }
            info.update(message, state, orgState);
        }
    }
}
+40 −40
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ import android.os.SystemClock;

import com.android.internal.util.HierarchicalState;
import com.android.internal.util.HierarchicalStateMachine;
import com.android.internal.util.ProcessedMessages;
import com.android.internal.util.HierarchicalStateMachine.ProcessedMessageInfo;

import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
@@ -125,21 +125,21 @@ public class HierarchicalStateMachineTest extends TestCase {

        assertTrue(smQuitTest.getProcessedMessagesCount() == 9);

        ProcessedMessages.Info pmi;
        ProcessedMessageInfo pmi;

        // The first two message didn't quit and were handled by mS1
        pmi = smQuitTest.getProcessedMessage(6);
        pmi = smQuitTest.getProcessedMessageInfo(6);
        assertEquals(HierarchicalStateMachine.HSM_QUIT_CMD, pmi.getWhat());
        assertEquals(smQuitTest.mS1, pmi.getState());
        assertEquals(smQuitTest.mS1, pmi.getOriginalState());

        pmi = smQuitTest.getProcessedMessage(7);
        pmi = smQuitTest.getProcessedMessageInfo(7);
        assertEquals(HierarchicalStateMachine.HSM_QUIT_CMD, pmi.getWhat());
        assertEquals(smQuitTest.mS1, pmi.getState());
        assertEquals(smQuitTest.mS1, pmi.getOriginalState());

        // The last message was never handled so the states are null
        pmi = smQuitTest.getProcessedMessage(8);
        pmi = smQuitTest.getProcessedMessageInfo(8);
        assertEquals(HierarchicalStateMachine.HSM_QUIT_CMD, pmi.getWhat());
        assertEquals(null, pmi.getState());
        assertEquals(null, pmi.getOriginalState());
@@ -285,10 +285,10 @@ public class HierarchicalStateMachineTest extends TestCase {

        assertTrue(smEnterExitTranstionToTest.getProcessedMessagesCount() == 1);

        ProcessedMessages.Info pmi;
        ProcessedMessageInfo pmi;

        // Message should be handled by mS2.
        pmi = smEnterExitTranstionToTest.getProcessedMessage(0);
        pmi = smEnterExitTranstionToTest.getProcessedMessageInfo(0);
        assertEquals(TEST_CMD_1, pmi.getWhat());
        assertEquals(smEnterExitTranstionToTest.mS2, pmi.getState());
        assertEquals(smEnterExitTranstionToTest.mS2, pmi.getOriginalState());
@@ -369,18 +369,18 @@ public class HierarchicalStateMachineTest extends TestCase {
        assertTrue(sm0.getProcessedMessagesCount() == 6);
        assertTrue(sm0.getProcessedMessagesSize() == 3);

        ProcessedMessages.Info pmi;
        pmi = sm0.getProcessedMessage(0);
        ProcessedMessageInfo pmi;
        pmi = sm0.getProcessedMessageInfo(0);
        assertEquals(TEST_CMD_4, pmi.getWhat());
        assertEquals(sm0.mS1, pmi.getState());
        assertEquals(sm0.mS1, pmi.getOriginalState());

        pmi = sm0.getProcessedMessage(1);
        pmi = sm0.getProcessedMessageInfo(1);
        assertEquals(TEST_CMD_5, pmi.getWhat());
        assertEquals(sm0.mS1, pmi.getState());
        assertEquals(sm0.mS1, pmi.getOriginalState());

        pmi = sm0.getProcessedMessage(2);
        pmi = sm0.getProcessedMessageInfo(2);
        assertEquals(TEST_CMD_6, pmi.getWhat());
        assertEquals(sm0.mS1, pmi.getState());
        assertEquals(sm0.mS1, pmi.getOriginalState());
@@ -469,13 +469,13 @@ public class HierarchicalStateMachineTest extends TestCase {

        assertTrue(sm1.getProcessedMessagesSize() == 2);

        ProcessedMessages.Info pmi;
        pmi = sm1.getProcessedMessage(0);
        ProcessedMessageInfo pmi;
        pmi = sm1.getProcessedMessageInfo(0);
        assertEquals(TEST_CMD_1, pmi.getWhat());
        assertEquals(sm1.mS1, pmi.getState());
        assertEquals(sm1.mS1, pmi.getOriginalState());

        pmi = sm1.getProcessedMessage(1);
        pmi = sm1.getProcessedMessageInfo(1);
        assertEquals(TEST_CMD_2, pmi.getWhat());
        assertEquals(sm1.mS1, pmi.getState());
        assertEquals(sm1.mS1, pmi.getOriginalState());
@@ -571,20 +571,20 @@ public class HierarchicalStateMachineTest extends TestCase {

        assertTrue(sm2.getProcessedMessagesSize() == 4);

        ProcessedMessages.Info pmi;
        pmi = sm2.getProcessedMessage(0);
        ProcessedMessageInfo pmi;
        pmi = sm2.getProcessedMessageInfo(0);
        assertEquals(TEST_CMD_1, pmi.getWhat());
        assertEquals(sm2.mS1, pmi.getState());

        pmi = sm2.getProcessedMessage(1);
        pmi = sm2.getProcessedMessageInfo(1);
        assertEquals(TEST_CMD_2, pmi.getWhat());
        assertEquals(sm2.mS1, pmi.getState());

        pmi = sm2.getProcessedMessage(2);
        pmi = sm2.getProcessedMessageInfo(2);
        assertEquals(TEST_CMD_1, pmi.getWhat());
        assertEquals(sm2.mS2, pmi.getState());

        pmi = sm2.getProcessedMessage(3);
        pmi = sm2.getProcessedMessageInfo(3);
        assertEquals(TEST_CMD_2, pmi.getWhat());
        assertEquals(sm2.mS2, pmi.getState());

@@ -663,13 +663,13 @@ public class HierarchicalStateMachineTest extends TestCase {

        assertTrue(sm3.getProcessedMessagesSize() == 2);

        ProcessedMessages.Info pmi;
        pmi = sm3.getProcessedMessage(0);
        ProcessedMessageInfo pmi;
        pmi = sm3.getProcessedMessageInfo(0);
        assertEquals(TEST_CMD_1, pmi.getWhat());
        assertEquals(sm3.mParentState, pmi.getState());
        assertEquals(sm3.mChildState, pmi.getOriginalState());

        pmi = sm3.getProcessedMessage(1);
        pmi = sm3.getProcessedMessageInfo(1);
        assertEquals(TEST_CMD_2, pmi.getWhat());
        assertEquals(sm3.mParentState, pmi.getState());
        assertEquals(sm3.mChildState, pmi.getOriginalState());
@@ -757,13 +757,13 @@ public class HierarchicalStateMachineTest extends TestCase {

        assertTrue(sm4.getProcessedMessagesSize() == 2);

        ProcessedMessages.Info pmi;
        pmi = sm4.getProcessedMessage(0);
        ProcessedMessageInfo pmi;
        pmi = sm4.getProcessedMessageInfo(0);
        assertEquals(TEST_CMD_1, pmi.getWhat());
        assertEquals(sm4.mChildState1, pmi.getState());
        assertEquals(sm4.mChildState1, pmi.getOriginalState());

        pmi = sm4.getProcessedMessage(1);
        pmi = sm4.getProcessedMessageInfo(1);
        assertEquals(TEST_CMD_2, pmi.getWhat());
        assertEquals(sm4.mParentState, pmi.getState());
        assertEquals(sm4.mChildState2, pmi.getOriginalState());
@@ -1050,33 +1050,33 @@ public class HierarchicalStateMachineTest extends TestCase {
        assertEquals(1, sm5.mChildState5EnterCount);
        assertEquals(1, sm5.mChildState5ExitCount);

        ProcessedMessages.Info pmi;
        pmi = sm5.getProcessedMessage(0);
        ProcessedMessageInfo pmi;
        pmi = sm5.getProcessedMessageInfo(0);
        assertEquals(TEST_CMD_1, pmi.getWhat());
        assertEquals(sm5.mChildState1, pmi.getState());
        assertEquals(sm5.mChildState1, pmi.getOriginalState());

        pmi = sm5.getProcessedMessage(1);
        pmi = sm5.getProcessedMessageInfo(1);
        assertEquals(TEST_CMD_2, pmi.getWhat());
        assertEquals(sm5.mChildState2, pmi.getState());
        assertEquals(sm5.mChildState2, pmi.getOriginalState());

        pmi = sm5.getProcessedMessage(2);
        pmi = sm5.getProcessedMessageInfo(2);
        assertEquals(TEST_CMD_3, pmi.getWhat());
        assertEquals(sm5.mChildState5, pmi.getState());
        assertEquals(sm5.mChildState5, pmi.getOriginalState());

        pmi = sm5.getProcessedMessage(3);
        pmi = sm5.getProcessedMessageInfo(3);
        assertEquals(TEST_CMD_4, pmi.getWhat());
        assertEquals(sm5.mChildState3, pmi.getState());
        assertEquals(sm5.mChildState3, pmi.getOriginalState());

        pmi = sm5.getProcessedMessage(4);
        pmi = sm5.getProcessedMessageInfo(4);
        assertEquals(TEST_CMD_5, pmi.getWhat());
        assertEquals(sm5.mChildState4, pmi.getState());
        assertEquals(sm5.mChildState4, pmi.getOriginalState());

        pmi = sm5.getProcessedMessage(5);
        pmi = sm5.getProcessedMessageInfo(5);
        assertEquals(TEST_CMD_6, pmi.getWhat());
        assertEquals(sm5.mParentState2, pmi.getState());
        assertEquals(sm5.mParentState2, pmi.getOriginalState());
@@ -1434,7 +1434,7 @@ public class HierarchicalStateMachineTest extends TestCase {
        for (StateMachineSharedThread sm : sms) {
            assertTrue(sm.getProcessedMessagesCount() == 4);
            for (int i = 0; i < sm.getProcessedMessagesCount(); i++) {
                ProcessedMessages.Info pmi = sm.getProcessedMessage(i);
                ProcessedMessageInfo pmi = sm.getProcessedMessageInfo(i);
                assertEquals(i+1, pmi.getWhat());
                assertEquals(sm.mS1, pmi.getState());
                assertEquals(sm.mS1, pmi.getOriginalState());
@@ -1464,37 +1464,37 @@ public class HierarchicalStateMachineTest extends TestCase {
        }

        assertEquals(7, sm.getProcessedMessagesCount());
        ProcessedMessages.Info pmi = sm.getProcessedMessage(0);
        ProcessedMessageInfo pmi = sm.getProcessedMessageInfo(0);
        assertEquals(Hsm1.CMD_1, pmi.getWhat());
        assertEquals(sm.mS1, pmi.getState());
        assertEquals(sm.mS1, pmi.getOriginalState());

        pmi = sm.getProcessedMessage(1);
        pmi = sm.getProcessedMessageInfo(1);
        assertEquals(Hsm1.CMD_2, pmi.getWhat());
        assertEquals(sm.mP1, pmi.getState());
        assertEquals(sm.mS1, pmi.getOriginalState());

        pmi = sm.getProcessedMessage(2);
        pmi = sm.getProcessedMessageInfo(2);
        assertEquals(Hsm1.CMD_2, pmi.getWhat());
        assertEquals(sm.mS2, pmi.getState());
        assertEquals(sm.mS2, pmi.getOriginalState());

        pmi = sm.getProcessedMessage(3);
        pmi = sm.getProcessedMessageInfo(3);
        assertEquals(Hsm1.CMD_3, pmi.getWhat());
        assertEquals(sm.mS2, pmi.getState());
        assertEquals(sm.mS2, pmi.getOriginalState());

        pmi = sm.getProcessedMessage(4);
        pmi = sm.getProcessedMessageInfo(4);
        assertEquals(Hsm1.CMD_3, pmi.getWhat());
        assertEquals(sm.mP2, pmi.getState());
        assertEquals(sm.mP2, pmi.getOriginalState());

        pmi = sm.getProcessedMessage(5);
        pmi = sm.getProcessedMessageInfo(5);
        assertEquals(Hsm1.CMD_4, pmi.getWhat());
        assertEquals(sm.mP2, pmi.getState());
        assertEquals(sm.mP2, pmi.getOriginalState());

        pmi = sm.getProcessedMessage(6);
        pmi = sm.getProcessedMessageInfo(6);
        assertEquals(Hsm1.CMD_5, pmi.getWhat());
        assertEquals(sm.mP2, pmi.getState());
        assertEquals(sm.mP2, pmi.getOriginalState());