Loading core/java/android/bluetooth/BluetoothDeviceProfileState.java +28 −20 Original line number Diff line number Diff line Loading @@ -304,6 +304,25 @@ public final class BluetoothDeviceProfileState extends StateMachine { } } @Override protected void onQuitting() { mContext.unregisterReceiver(mBroadcastReceiver); mBroadcastReceiver = null; mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadsetService); mBluetoothProfileServiceListener = null; mOutgoingHandsfree = null; mPbap = null; mPbapService.close(); mPbapService = null; mIncomingHid = null; mOutgoingHid = null; mIncomingHandsfree = null; mOutgoingHandsfree = null; mIncomingA2dp = null; mOutgoingA2dp = null; mBondedDevice = null; } private class BondedDevice extends State { @Override public void enter() { Loading Loading @@ -416,26 +435,6 @@ public final class BluetoothDeviceProfileState extends StateMachine { case TRANSITION_TO_STABLE: // ignore. break; case SM_QUIT_CMD: mContext.unregisterReceiver(mBroadcastReceiver); mBroadcastReceiver = null; mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadsetService); mBluetoothProfileServiceListener = null; mOutgoingHandsfree = null; mPbap = null; mPbapService.close(); mPbapService = null; mIncomingHid = null; mOutgoingHid = null; mIncomingHandsfree = null; mOutgoingHandsfree = null; mIncomingA2dp = null; mOutgoingA2dp = null; mBondedDevice = null; // There is a problem in the State Machine code // where things are not cleaned up properly, when quit message // is handled so return NOT_HANDLED as a workaround. return NOT_HANDLED; default: return NOT_HANDLED; } Loading Loading @@ -1341,6 +1340,15 @@ public final class BluetoothDeviceProfileState extends StateMachine { return mDevice; } /** * Quit the state machine, only to be called by BluetoothService. * * @hide */ public void doQuit() { this.quit(); } private void log(String message) { if (DBG) { Log.i(TAG, "Device:" + mDevice + " Message:" + message); Loading core/java/android/net/DhcpStateMachine.java +13 −4 Original line number Diff line number Diff line Loading @@ -163,7 +163,20 @@ public class DhcpStateMachine extends StateMachine { mRegisteredForPreDhcpNotification = true; } /** * Quit the DhcpStateMachine. * * @hide */ public void doQuit() { quit(); } class DefaultState extends State { @Override public void exit() { mContext.unregisterReceiver(mBroadcastReceiver); } @Override public boolean processMessage(Message message) { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); Loading @@ -172,10 +185,6 @@ public class DhcpStateMachine extends StateMachine { Log.e(TAG, "Error! Failed to handle a DHCP renewal on " + mInterfaceName); mDhcpRenewWakeLock.release(); break; case SM_QUIT_CMD: mContext.unregisterReceiver(mBroadcastReceiver); //let parent kill the state machine return NOT_HANDLED; default: Log.e(TAG, "Error! unhandled message " + message); break; Loading core/java/android/server/BluetoothService.java +1 −1 Original line number Diff line number Diff line Loading @@ -2448,7 +2448,7 @@ public class BluetoothService extends IBluetooth.Stub { BluetoothDeviceProfileState state = mDeviceProfileState.get(address); if (state == null) return; state.quit(); state.doQuit(); mDeviceProfileState.remove(address); } Loading core/java/com/android/internal/util/StateMachine.java +164 −147 Original line number Diff line number Diff line Loading @@ -80,9 +80,9 @@ import java.util.Vector; * and invoke <code>halting</code>. Any message subsequently received by the state * machine will cause <code>haltedProcessMessage</code> to be invoked.</p> * * <p>If it is desirable to completely stop the state machine call <code>quit</code>. This * will exit the current state and its parent and then exit from the controlling thread * and no further messages will be processed.</p> * <p>If it is desirable to completely stop the state machine call <code>quit</code> or * <code>abort</code>. These will call <code>exit</code> of the current state and its parents, call * <code>onQuiting</code> and then exit Thread/Loopers.</p> * * <p>In addition to <code>processMessage</code> each <code>State</code> has * an <code>enter</code> method and <code>exit</exit> method which may be overridden.</p> Loading Loading @@ -362,7 +362,7 @@ class Hsm1 extends StateMachine { } @Override void halting() { void onHalting() { Log.d(TAG, "halting"); synchronized (this) { this.notifyAll(); Loading Loading @@ -423,10 +423,10 @@ public class StateMachine { private String mName; /** Message.what value when quitting */ public static final int SM_QUIT_CMD = -1; private static final int SM_QUIT_CMD = -1; /** Message.what value when initializing */ public static final int SM_INIT_CMD = -2; private static final int SM_INIT_CMD = -2; /** * Convenience constant that maybe returned by processMessage Loading @@ -443,11 +443,10 @@ public class StateMachine { public static final boolean NOT_HANDLED = false; /** * StateMachine logging record. * {@hide} * * The information maintained for a processed message. */ public static class ProcessedMessageInfo { public static class LogRec { private long mTime; private int mWhat; private String mInfo; Loading @@ -456,12 +455,13 @@ public class StateMachine { /** * Constructor * @param message * * @param msg * @param state that handled the message * @param orgState is the first state the received the message but * did not processes the message. */ ProcessedMessageInfo(Message msg, String info, State state, State orgState) { LogRec(Message msg, String info, State state, State orgState) { update(msg, info, state, orgState); } Loading @@ -473,7 +473,7 @@ public class StateMachine { */ public void update(Message msg, String info, State state, State orgState) { mTime = System.currentTimeMillis(); mWhat = msg.what; mWhat = (msg != null) ? msg.what : 0; mInfo = info; mState = state; mOrgState = orgState; Loading Loading @@ -517,8 +517,7 @@ public class StateMachine { /** * @return as string */ @Override public String toString() { public String toString(StateMachine sm) { StringBuilder sb = new StringBuilder(); sb.append("time="); Calendar c = Calendar.getInstance(); Loading @@ -529,10 +528,15 @@ public class StateMachine { sb.append(" orgState="); sb.append(mOrgState == null ? "<null>" : mOrgState.getName()); sb.append(" what="); String what = sm.getWhatToString(mWhat); if (TextUtils.isEmpty(what)) { sb.append(mWhat); sb.append("(0x"); sb.append(Integer.toHexString(mWhat)); sb.append(")"); } else { sb.append(what); } if ( ! TextUtils.isEmpty(mInfo)) { sb.append(" "); sb.append(mInfo); Loading @@ -542,21 +546,21 @@ public class StateMachine { } /** * A list of messages recently processed by the state machine. * A list of log records including messages recently processed by the state machine. * * The class maintains a list of messages that have been most * The class maintains a list of log records including messages * 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. * includes size which returns the number of recent records, * count which is the number of records processed since the * the last setSize, get which returns a record and * add which adds a record. */ private static class ProcessedMessages { private static class LogRecords { private static final int DEFAULT_SIZE = 20; private Vector<ProcessedMessageInfo> mMessages = new Vector<ProcessedMessageInfo>(); private Vector<LogRec> mLogRecords = new Vector<LogRec>(); private int mMaxSize = DEFAULT_SIZE; private int mOldestIndex = 0; private int mCount = 0; Loading @@ -564,39 +568,39 @@ public class StateMachine { /** * private constructor use add */ private ProcessedMessages() { private LogRecords() { } /** * Set size of messages to maintain and clears all current messages. * Set size of messages to maintain and clears all current records. * * @param maxSize number of messages to maintain at anyone time. * @param maxSize number of records to maintain at anyone time. */ void setSize(int maxSize) { synchronized void setSize(int maxSize) { mMaxSize = maxSize; mCount = 0; mMessages.clear(); mLogRecords.clear(); } /** * @return the number of recent messages. * @return the number of recent records. */ int size() { return mMessages.size(); synchronized int size() { return mLogRecords.size(); } /** * @return the total number of messages processed since size was set. * @return the total number of records processed since size was set. */ int count() { synchronized int count() { return mCount; } /** * Clear the list of Processed Message Info. * Clear the list of records. */ void cleanup() { mMessages.clear(); synchronized void cleanup() { mLogRecords.clear(); } /** Loading @@ -604,7 +608,7 @@ public class StateMachine { * record and size()-1 is the newest record. If the index is to * large null is returned. */ ProcessedMessageInfo get(int index) { synchronized LogRec get(int index) { int nextIndex = mOldestIndex + index; if (nextIndex >= mMaxSize) { nextIndex -= mMaxSize; Loading @@ -612,7 +616,7 @@ public class StateMachine { if (nextIndex >= size()) { return null; } else { return mMessages.get(nextIndex); return mLogRecords.get(nextIndex); } } Loading @@ -625,12 +629,12 @@ public class StateMachine { * @param orgState is the first state the received the message but * did not processes the message. */ void add(Message msg, String messageInfo, State state, State orgState) { synchronized void add(Message msg, String messageInfo, State state, State orgState) { mCount += 1; if (mMessages.size() < mMaxSize) { mMessages.add(new ProcessedMessageInfo(msg, messageInfo, state, orgState)); if (mLogRecords.size() < mMaxSize) { mLogRecords.add(new LogRec(msg, messageInfo, state, orgState)); } else { ProcessedMessageInfo pmi = mMessages.get(mOldestIndex); LogRec pmi = mLogRecords.get(mOldestIndex); mOldestIndex += 1; if (mOldestIndex >= mMaxSize) { mOldestIndex = 0; Loading @@ -652,8 +656,8 @@ public class StateMachine { /** The current message */ private Message mMsg; /** A list of messages that this state machine has processed */ private ProcessedMessages mProcessedMessages = new ProcessedMessages(); /** A list of log records including messages this state machine has processed */ private LogRecords mLogRecords = new LogRecords(); /** true if construction of the state machine has not been completed */ private boolean mIsConstructionCompleted; Loading Loading @@ -814,15 +818,18 @@ public class StateMachine { */ if (destState != null) { if (destState == mQuittingState) { /** * Call onQuitting to let subclasses cleanup. */ mSm.onQuitting(); cleanupAfterQuitting(); } else if (destState == mHaltingState) { /** * Call halting() if we've transitioned to the halting * Call onHalting() if we've transitioned to the halting * state. All subsequent messages will be processed in * in the halting state which invokes haltedProcessMessage(msg); */ mSm.halting(); mSm.onHalting(); } } } Loading @@ -831,7 +838,6 @@ public class StateMachine { * Cleanup all the static variables and the looper after the SM has been quit. */ private final void cleanupAfterQuitting() { mSm.quitting(); if (mSm.mSmThread != null) { // If we made the thread then quit looper which stops the thread. getLooper().quit(); Loading @@ -841,7 +847,7 @@ public class StateMachine { mSm.mSmHandler = null; mSm = null; mMsg = null; mProcessedMessages.cleanup(); mLogRecords.cleanup(); mStateStack = null; mTempStateStack = null; mStateInfo.clear(); Loading Loading @@ -892,6 +898,10 @@ public class StateMachine { if (mDbg) { Log.d(TAG, "processMsg: " + curStateInfo.state.getName()); } if (isQuit(msg)) { transitionTo(mQuittingState); } else { while (!curStateInfo.state.processMessage(msg)) { /** * Not processed Loading @@ -902,9 +912,6 @@ public class StateMachine { * No parents left so it's not handled */ mSm.unhandledMessage(msg); if (isQuit(msg)) { transitionTo(mQuittingState); } break; } if (mDbg) { Loading @@ -915,13 +922,14 @@ public class StateMachine { /** * Record that we processed the message */ if (mSm.recordProcessedMessage(msg)) { if (mSm.recordLogRec(msg)) { if (curStateInfo != null) { State orgState = mStateStack[mStateStackTopIndex].state; mProcessedMessages.add(msg, mSm.getMessageInfo(msg), curStateInfo.state, mLogRecords.add(msg, mSm.getLogRecString(msg), curStateInfo.state, orgState); } else { mProcessedMessages.add(msg, mSm.getMessageInfo(msg), null, null); mLogRecords.add(msg, mSm.getLogRecString(msg), null, null); } } } } Loading Loading @@ -1141,13 +1149,19 @@ public class StateMachine { mDeferredMessages.add(newMsg); } /** @see StateMachine#deferMessage(Message) */ /** @see StateMachine#quit() */ private final void quit() { if (mDbg) Log.d(TAG, "quit:"); sendMessage(obtainMessage(SM_QUIT_CMD, mSmHandlerObj)); } /** @see StateMachine#isQuit(Message) */ /** @see StateMachine#quitNow() */ private final void quitNow() { if (mDbg) Log.d(TAG, "abort:"); sendMessageAtFrontOfQueue(obtainMessage(SM_QUIT_CMD, mSmHandlerObj)); } /** Validate that the message was sent by quit or abort. */ private final boolean isQuit(Message msg) { return (msg.what == SM_QUIT_CMD) && (msg.obj == mSmHandlerObj); } Loading @@ -1162,26 +1176,6 @@ public class StateMachine { mDbg = dbg; } /** @see StateMachine#setProcessedMessagesSize(int) */ private final void setProcessedMessagesSize(int maxSize) { mProcessedMessages.setSize(maxSize); } /** @see StateMachine#getProcessedMessagesSize() */ private final int getProcessedMessagesSize() { return mProcessedMessages.size(); } /** @see StateMachine#getProcessedMessagesCount() */ private final int getProcessedMessagesCount() { return mProcessedMessages.count(); } /** @see StateMachine#getProcessedMessageInfo(int) */ private final ProcessedMessageInfo getProcessedMessageInfo(int index) { return mProcessedMessages.get(index); } } private SmHandler mSmHandler; Loading Loading @@ -1282,8 +1276,8 @@ public class StateMachine { /** * transition to halt state. Upon returning * from processMessage we will exit all current * states, execute the halting() method and then * all subsequent messages haltedProcessMesage * states, execute the onHalting() method and then * for all subsequent messages haltedProcessMessage * will be called. */ protected final void transitionToHaltingState() { Loading @@ -1303,7 +1297,6 @@ public class StateMachine { mSmHandler.deferMessage(msg); } /** * Called when message wasn't handled * Loading @@ -1325,7 +1318,7 @@ public class StateMachine { * transitionToHalting. All subsequent messages will invoke * {@link StateMachine#haltedProcessMessage(Message)} */ protected void halting() { protected void onHalting() { } /** Loading @@ -1334,7 +1327,7 @@ public class StateMachine { * ignored. In addition, if this StateMachine created the thread, the thread will * be stopped after this method returns. */ protected void quitting() { protected void onQuitting() { } /** Loading @@ -1345,33 +1338,77 @@ public class StateMachine { } /** * Set size of messages to maintain and clears all current messages. * Set number of log records to maintain and clears all current records. * * @param maxSize number of messages to maintain at anyone time. */ public final void setProcessedMessagesSize(int maxSize) { mSmHandler.setProcessedMessagesSize(maxSize); public final void setLogRecSize(int maxSize) { mSmHandler.mLogRecords.setSize(maxSize); } /** * @return number of log records */ public final int getLogRecSize() { return mSmHandler.mLogRecords.size(); } /** * @return the total number of records processed */ public final int getLogRecCount() { return mSmHandler.mLogRecords.count(); } /** * @return a log record */ public final LogRec getLogRec(int index) { return mSmHandler.mLogRecords.get(index); } /** * @return number of messages processed * Add the string to LogRecords. * * @param string */ public final int getProcessedMessagesSize() { return mSmHandler.getProcessedMessagesSize(); protected void addLogRec(String string) { mSmHandler.mLogRecords.add(null, string, null, null); } /** * @return the total number of messages processed * Add the string and state to LogRecords * * @param string * @param state current state */ protected void addLogRec(String string, State state) { mSmHandler.mLogRecords.add(null, string, state, null); } /** * @return true if msg should be saved in the log, default is true. */ protected boolean recordLogRec(Message msg) { return true; } /** * Return a string to be logged by LogRec, default * is an empty string. Override if additional information is desired. * * @param msg that was processed * @return information to be logged as a String */ public final int getProcessedMessagesCount() { return mSmHandler.getProcessedMessagesCount(); protected String getLogRecString(Message msg) { return ""; } /** * @return a processed message information * @return the string for msg.what */ public final ProcessedMessageInfo getProcessedMessageInfo(int index) { return mSmHandler.getProcessedMessageInfo(index); protected String getWhatToString(int what) { return null; } /** Loading Loading @@ -1548,43 +1585,23 @@ public class StateMachine { } /** * Conditionally quit the looper and stop execution. * * This sends the SM_QUIT_MSG to the state machine and * if not handled by any state's processMessage then the * state machine will be stopped and no further messages * will be processed. * Quit the state machine after all currently queued up messages are processed. */ public final void quit() { // mSmHandler can be null if the state machine has quit. protected final void quit() { // mSmHandler can be null if the state machine is already stopped. if (mSmHandler == null) return; mSmHandler.quit(); } /** * @return ture if msg is quit * Quit the state machine immediately all currently queued messages will be discarded. */ protected final boolean isQuit(Message msg) { return mSmHandler.isQuit(msg); } /** * @return true if msg should be saved in ProcessedMessage, default is true. */ protected boolean recordProcessedMessage(Message msg) { return true; } protected final void quitNow() { // mSmHandler can be null if the state machine is already stopped. if (mSmHandler == null) return; /** * Return message info to be logged by ProcessedMessageInfo, default * is an empty string. Override if additional information is desired. * * @param msg that was processed * @return information to be logged as a String */ protected String getMessageInfo(Message msg) { return ""; mSmHandler.quitNow(); } /** Loading Loading @@ -1629,9 +1646,9 @@ public class StateMachine { */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(getName() + ":"); pw.println(" total messages=" + getProcessedMessagesCount()); for (int i=0; i < getProcessedMessagesSize(); i++) { pw.printf(" msg[%d]: %s\n", i, getProcessedMessageInfo(i)); pw.println(" total records=" + getLogRecCount()); for (int i=0; i < getLogRecSize(); i++) { pw.printf(" rec[%d]: %s\n", i, getLogRec(i).toString(this)); pw.flush(); } pw.println("curState=" + getCurrentState().getName()); Loading core/tests/coretests/src/com/android/internal/util/StateMachineTest.java +366 −236 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/bluetooth/BluetoothDeviceProfileState.java +28 −20 Original line number Diff line number Diff line Loading @@ -304,6 +304,25 @@ public final class BluetoothDeviceProfileState extends StateMachine { } } @Override protected void onQuitting() { mContext.unregisterReceiver(mBroadcastReceiver); mBroadcastReceiver = null; mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadsetService); mBluetoothProfileServiceListener = null; mOutgoingHandsfree = null; mPbap = null; mPbapService.close(); mPbapService = null; mIncomingHid = null; mOutgoingHid = null; mIncomingHandsfree = null; mOutgoingHandsfree = null; mIncomingA2dp = null; mOutgoingA2dp = null; mBondedDevice = null; } private class BondedDevice extends State { @Override public void enter() { Loading Loading @@ -416,26 +435,6 @@ public final class BluetoothDeviceProfileState extends StateMachine { case TRANSITION_TO_STABLE: // ignore. break; case SM_QUIT_CMD: mContext.unregisterReceiver(mBroadcastReceiver); mBroadcastReceiver = null; mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadsetService); mBluetoothProfileServiceListener = null; mOutgoingHandsfree = null; mPbap = null; mPbapService.close(); mPbapService = null; mIncomingHid = null; mOutgoingHid = null; mIncomingHandsfree = null; mOutgoingHandsfree = null; mIncomingA2dp = null; mOutgoingA2dp = null; mBondedDevice = null; // There is a problem in the State Machine code // where things are not cleaned up properly, when quit message // is handled so return NOT_HANDLED as a workaround. return NOT_HANDLED; default: return NOT_HANDLED; } Loading Loading @@ -1341,6 +1340,15 @@ public final class BluetoothDeviceProfileState extends StateMachine { return mDevice; } /** * Quit the state machine, only to be called by BluetoothService. * * @hide */ public void doQuit() { this.quit(); } private void log(String message) { if (DBG) { Log.i(TAG, "Device:" + mDevice + " Message:" + message); Loading
core/java/android/net/DhcpStateMachine.java +13 −4 Original line number Diff line number Diff line Loading @@ -163,7 +163,20 @@ public class DhcpStateMachine extends StateMachine { mRegisteredForPreDhcpNotification = true; } /** * Quit the DhcpStateMachine. * * @hide */ public void doQuit() { quit(); } class DefaultState extends State { @Override public void exit() { mContext.unregisterReceiver(mBroadcastReceiver); } @Override public boolean processMessage(Message message) { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); Loading @@ -172,10 +185,6 @@ public class DhcpStateMachine extends StateMachine { Log.e(TAG, "Error! Failed to handle a DHCP renewal on " + mInterfaceName); mDhcpRenewWakeLock.release(); break; case SM_QUIT_CMD: mContext.unregisterReceiver(mBroadcastReceiver); //let parent kill the state machine return NOT_HANDLED; default: Log.e(TAG, "Error! unhandled message " + message); break; Loading
core/java/android/server/BluetoothService.java +1 −1 Original line number Diff line number Diff line Loading @@ -2448,7 +2448,7 @@ public class BluetoothService extends IBluetooth.Stub { BluetoothDeviceProfileState state = mDeviceProfileState.get(address); if (state == null) return; state.quit(); state.doQuit(); mDeviceProfileState.remove(address); } Loading
core/java/com/android/internal/util/StateMachine.java +164 −147 Original line number Diff line number Diff line Loading @@ -80,9 +80,9 @@ import java.util.Vector; * and invoke <code>halting</code>. Any message subsequently received by the state * machine will cause <code>haltedProcessMessage</code> to be invoked.</p> * * <p>If it is desirable to completely stop the state machine call <code>quit</code>. This * will exit the current state and its parent and then exit from the controlling thread * and no further messages will be processed.</p> * <p>If it is desirable to completely stop the state machine call <code>quit</code> or * <code>abort</code>. These will call <code>exit</code> of the current state and its parents, call * <code>onQuiting</code> and then exit Thread/Loopers.</p> * * <p>In addition to <code>processMessage</code> each <code>State</code> has * an <code>enter</code> method and <code>exit</exit> method which may be overridden.</p> Loading Loading @@ -362,7 +362,7 @@ class Hsm1 extends StateMachine { } @Override void halting() { void onHalting() { Log.d(TAG, "halting"); synchronized (this) { this.notifyAll(); Loading Loading @@ -423,10 +423,10 @@ public class StateMachine { private String mName; /** Message.what value when quitting */ public static final int SM_QUIT_CMD = -1; private static final int SM_QUIT_CMD = -1; /** Message.what value when initializing */ public static final int SM_INIT_CMD = -2; private static final int SM_INIT_CMD = -2; /** * Convenience constant that maybe returned by processMessage Loading @@ -443,11 +443,10 @@ public class StateMachine { public static final boolean NOT_HANDLED = false; /** * StateMachine logging record. * {@hide} * * The information maintained for a processed message. */ public static class ProcessedMessageInfo { public static class LogRec { private long mTime; private int mWhat; private String mInfo; Loading @@ -456,12 +455,13 @@ public class StateMachine { /** * Constructor * @param message * * @param msg * @param state that handled the message * @param orgState is the first state the received the message but * did not processes the message. */ ProcessedMessageInfo(Message msg, String info, State state, State orgState) { LogRec(Message msg, String info, State state, State orgState) { update(msg, info, state, orgState); } Loading @@ -473,7 +473,7 @@ public class StateMachine { */ public void update(Message msg, String info, State state, State orgState) { mTime = System.currentTimeMillis(); mWhat = msg.what; mWhat = (msg != null) ? msg.what : 0; mInfo = info; mState = state; mOrgState = orgState; Loading Loading @@ -517,8 +517,7 @@ public class StateMachine { /** * @return as string */ @Override public String toString() { public String toString(StateMachine sm) { StringBuilder sb = new StringBuilder(); sb.append("time="); Calendar c = Calendar.getInstance(); Loading @@ -529,10 +528,15 @@ public class StateMachine { sb.append(" orgState="); sb.append(mOrgState == null ? "<null>" : mOrgState.getName()); sb.append(" what="); String what = sm.getWhatToString(mWhat); if (TextUtils.isEmpty(what)) { sb.append(mWhat); sb.append("(0x"); sb.append(Integer.toHexString(mWhat)); sb.append(")"); } else { sb.append(what); } if ( ! TextUtils.isEmpty(mInfo)) { sb.append(" "); sb.append(mInfo); Loading @@ -542,21 +546,21 @@ public class StateMachine { } /** * A list of messages recently processed by the state machine. * A list of log records including messages recently processed by the state machine. * * The class maintains a list of messages that have been most * The class maintains a list of log records including messages * 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. * includes size which returns the number of recent records, * count which is the number of records processed since the * the last setSize, get which returns a record and * add which adds a record. */ private static class ProcessedMessages { private static class LogRecords { private static final int DEFAULT_SIZE = 20; private Vector<ProcessedMessageInfo> mMessages = new Vector<ProcessedMessageInfo>(); private Vector<LogRec> mLogRecords = new Vector<LogRec>(); private int mMaxSize = DEFAULT_SIZE; private int mOldestIndex = 0; private int mCount = 0; Loading @@ -564,39 +568,39 @@ public class StateMachine { /** * private constructor use add */ private ProcessedMessages() { private LogRecords() { } /** * Set size of messages to maintain and clears all current messages. * Set size of messages to maintain and clears all current records. * * @param maxSize number of messages to maintain at anyone time. * @param maxSize number of records to maintain at anyone time. */ void setSize(int maxSize) { synchronized void setSize(int maxSize) { mMaxSize = maxSize; mCount = 0; mMessages.clear(); mLogRecords.clear(); } /** * @return the number of recent messages. * @return the number of recent records. */ int size() { return mMessages.size(); synchronized int size() { return mLogRecords.size(); } /** * @return the total number of messages processed since size was set. * @return the total number of records processed since size was set. */ int count() { synchronized int count() { return mCount; } /** * Clear the list of Processed Message Info. * Clear the list of records. */ void cleanup() { mMessages.clear(); synchronized void cleanup() { mLogRecords.clear(); } /** Loading @@ -604,7 +608,7 @@ public class StateMachine { * record and size()-1 is the newest record. If the index is to * large null is returned. */ ProcessedMessageInfo get(int index) { synchronized LogRec get(int index) { int nextIndex = mOldestIndex + index; if (nextIndex >= mMaxSize) { nextIndex -= mMaxSize; Loading @@ -612,7 +616,7 @@ public class StateMachine { if (nextIndex >= size()) { return null; } else { return mMessages.get(nextIndex); return mLogRecords.get(nextIndex); } } Loading @@ -625,12 +629,12 @@ public class StateMachine { * @param orgState is the first state the received the message but * did not processes the message. */ void add(Message msg, String messageInfo, State state, State orgState) { synchronized void add(Message msg, String messageInfo, State state, State orgState) { mCount += 1; if (mMessages.size() < mMaxSize) { mMessages.add(new ProcessedMessageInfo(msg, messageInfo, state, orgState)); if (mLogRecords.size() < mMaxSize) { mLogRecords.add(new LogRec(msg, messageInfo, state, orgState)); } else { ProcessedMessageInfo pmi = mMessages.get(mOldestIndex); LogRec pmi = mLogRecords.get(mOldestIndex); mOldestIndex += 1; if (mOldestIndex >= mMaxSize) { mOldestIndex = 0; Loading @@ -652,8 +656,8 @@ public class StateMachine { /** The current message */ private Message mMsg; /** A list of messages that this state machine has processed */ private ProcessedMessages mProcessedMessages = new ProcessedMessages(); /** A list of log records including messages this state machine has processed */ private LogRecords mLogRecords = new LogRecords(); /** true if construction of the state machine has not been completed */ private boolean mIsConstructionCompleted; Loading Loading @@ -814,15 +818,18 @@ public class StateMachine { */ if (destState != null) { if (destState == mQuittingState) { /** * Call onQuitting to let subclasses cleanup. */ mSm.onQuitting(); cleanupAfterQuitting(); } else if (destState == mHaltingState) { /** * Call halting() if we've transitioned to the halting * Call onHalting() if we've transitioned to the halting * state. All subsequent messages will be processed in * in the halting state which invokes haltedProcessMessage(msg); */ mSm.halting(); mSm.onHalting(); } } } Loading @@ -831,7 +838,6 @@ public class StateMachine { * Cleanup all the static variables and the looper after the SM has been quit. */ private final void cleanupAfterQuitting() { mSm.quitting(); if (mSm.mSmThread != null) { // If we made the thread then quit looper which stops the thread. getLooper().quit(); Loading @@ -841,7 +847,7 @@ public class StateMachine { mSm.mSmHandler = null; mSm = null; mMsg = null; mProcessedMessages.cleanup(); mLogRecords.cleanup(); mStateStack = null; mTempStateStack = null; mStateInfo.clear(); Loading Loading @@ -892,6 +898,10 @@ public class StateMachine { if (mDbg) { Log.d(TAG, "processMsg: " + curStateInfo.state.getName()); } if (isQuit(msg)) { transitionTo(mQuittingState); } else { while (!curStateInfo.state.processMessage(msg)) { /** * Not processed Loading @@ -902,9 +912,6 @@ public class StateMachine { * No parents left so it's not handled */ mSm.unhandledMessage(msg); if (isQuit(msg)) { transitionTo(mQuittingState); } break; } if (mDbg) { Loading @@ -915,13 +922,14 @@ public class StateMachine { /** * Record that we processed the message */ if (mSm.recordProcessedMessage(msg)) { if (mSm.recordLogRec(msg)) { if (curStateInfo != null) { State orgState = mStateStack[mStateStackTopIndex].state; mProcessedMessages.add(msg, mSm.getMessageInfo(msg), curStateInfo.state, mLogRecords.add(msg, mSm.getLogRecString(msg), curStateInfo.state, orgState); } else { mProcessedMessages.add(msg, mSm.getMessageInfo(msg), null, null); mLogRecords.add(msg, mSm.getLogRecString(msg), null, null); } } } } Loading Loading @@ -1141,13 +1149,19 @@ public class StateMachine { mDeferredMessages.add(newMsg); } /** @see StateMachine#deferMessage(Message) */ /** @see StateMachine#quit() */ private final void quit() { if (mDbg) Log.d(TAG, "quit:"); sendMessage(obtainMessage(SM_QUIT_CMD, mSmHandlerObj)); } /** @see StateMachine#isQuit(Message) */ /** @see StateMachine#quitNow() */ private final void quitNow() { if (mDbg) Log.d(TAG, "abort:"); sendMessageAtFrontOfQueue(obtainMessage(SM_QUIT_CMD, mSmHandlerObj)); } /** Validate that the message was sent by quit or abort. */ private final boolean isQuit(Message msg) { return (msg.what == SM_QUIT_CMD) && (msg.obj == mSmHandlerObj); } Loading @@ -1162,26 +1176,6 @@ public class StateMachine { mDbg = dbg; } /** @see StateMachine#setProcessedMessagesSize(int) */ private final void setProcessedMessagesSize(int maxSize) { mProcessedMessages.setSize(maxSize); } /** @see StateMachine#getProcessedMessagesSize() */ private final int getProcessedMessagesSize() { return mProcessedMessages.size(); } /** @see StateMachine#getProcessedMessagesCount() */ private final int getProcessedMessagesCount() { return mProcessedMessages.count(); } /** @see StateMachine#getProcessedMessageInfo(int) */ private final ProcessedMessageInfo getProcessedMessageInfo(int index) { return mProcessedMessages.get(index); } } private SmHandler mSmHandler; Loading Loading @@ -1282,8 +1276,8 @@ public class StateMachine { /** * transition to halt state. Upon returning * from processMessage we will exit all current * states, execute the halting() method and then * all subsequent messages haltedProcessMesage * states, execute the onHalting() method and then * for all subsequent messages haltedProcessMessage * will be called. */ protected final void transitionToHaltingState() { Loading @@ -1303,7 +1297,6 @@ public class StateMachine { mSmHandler.deferMessage(msg); } /** * Called when message wasn't handled * Loading @@ -1325,7 +1318,7 @@ public class StateMachine { * transitionToHalting. All subsequent messages will invoke * {@link StateMachine#haltedProcessMessage(Message)} */ protected void halting() { protected void onHalting() { } /** Loading @@ -1334,7 +1327,7 @@ public class StateMachine { * ignored. In addition, if this StateMachine created the thread, the thread will * be stopped after this method returns. */ protected void quitting() { protected void onQuitting() { } /** Loading @@ -1345,33 +1338,77 @@ public class StateMachine { } /** * Set size of messages to maintain and clears all current messages. * Set number of log records to maintain and clears all current records. * * @param maxSize number of messages to maintain at anyone time. */ public final void setProcessedMessagesSize(int maxSize) { mSmHandler.setProcessedMessagesSize(maxSize); public final void setLogRecSize(int maxSize) { mSmHandler.mLogRecords.setSize(maxSize); } /** * @return number of log records */ public final int getLogRecSize() { return mSmHandler.mLogRecords.size(); } /** * @return the total number of records processed */ public final int getLogRecCount() { return mSmHandler.mLogRecords.count(); } /** * @return a log record */ public final LogRec getLogRec(int index) { return mSmHandler.mLogRecords.get(index); } /** * @return number of messages processed * Add the string to LogRecords. * * @param string */ public final int getProcessedMessagesSize() { return mSmHandler.getProcessedMessagesSize(); protected void addLogRec(String string) { mSmHandler.mLogRecords.add(null, string, null, null); } /** * @return the total number of messages processed * Add the string and state to LogRecords * * @param string * @param state current state */ protected void addLogRec(String string, State state) { mSmHandler.mLogRecords.add(null, string, state, null); } /** * @return true if msg should be saved in the log, default is true. */ protected boolean recordLogRec(Message msg) { return true; } /** * Return a string to be logged by LogRec, default * is an empty string. Override if additional information is desired. * * @param msg that was processed * @return information to be logged as a String */ public final int getProcessedMessagesCount() { return mSmHandler.getProcessedMessagesCount(); protected String getLogRecString(Message msg) { return ""; } /** * @return a processed message information * @return the string for msg.what */ public final ProcessedMessageInfo getProcessedMessageInfo(int index) { return mSmHandler.getProcessedMessageInfo(index); protected String getWhatToString(int what) { return null; } /** Loading Loading @@ -1548,43 +1585,23 @@ public class StateMachine { } /** * Conditionally quit the looper and stop execution. * * This sends the SM_QUIT_MSG to the state machine and * if not handled by any state's processMessage then the * state machine will be stopped and no further messages * will be processed. * Quit the state machine after all currently queued up messages are processed. */ public final void quit() { // mSmHandler can be null if the state machine has quit. protected final void quit() { // mSmHandler can be null if the state machine is already stopped. if (mSmHandler == null) return; mSmHandler.quit(); } /** * @return ture if msg is quit * Quit the state machine immediately all currently queued messages will be discarded. */ protected final boolean isQuit(Message msg) { return mSmHandler.isQuit(msg); } /** * @return true if msg should be saved in ProcessedMessage, default is true. */ protected boolean recordProcessedMessage(Message msg) { return true; } protected final void quitNow() { // mSmHandler can be null if the state machine is already stopped. if (mSmHandler == null) return; /** * Return message info to be logged by ProcessedMessageInfo, default * is an empty string. Override if additional information is desired. * * @param msg that was processed * @return information to be logged as a String */ protected String getMessageInfo(Message msg) { return ""; mSmHandler.quitNow(); } /** Loading Loading @@ -1629,9 +1646,9 @@ public class StateMachine { */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(getName() + ":"); pw.println(" total messages=" + getProcessedMessagesCount()); for (int i=0; i < getProcessedMessagesSize(); i++) { pw.printf(" msg[%d]: %s\n", i, getProcessedMessageInfo(i)); pw.println(" total records=" + getLogRecCount()); for (int i=0; i < getLogRecSize(); i++) { pw.printf(" rec[%d]: %s\n", i, getLogRec(i).toString(this)); pw.flush(); } pw.println("curState=" + getCurrentState().getName()); Loading
core/tests/coretests/src/com/android/internal/util/StateMachineTest.java +366 −236 File changed.Preview size limit exceeded, changes collapsed. Show changes