am 8fb0faf3: Merge change I0a56959e into eclair-mr2
Merge commit '8fb0faf3cc2f792db8cf38fe5ab67c5eab7baa5c' into eclair-mr2-plus-aosp * commit '8fb0faf3cc2f792db8cf38fe5ab67c5eab7baa5c': Implement a HierarchicalStateMachine
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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 android.os;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public abstract class HandlerState {
|
||||
public HandlerState() {
|
||||
}
|
||||
|
||||
public void enter(Message message) {
|
||||
}
|
||||
|
||||
public abstract void processMessage(Message message);
|
||||
|
||||
public void exit(Message message) {
|
||||
}
|
||||
}
|
||||
@@ -1,290 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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 android.os;
|
||||
|
||||
import android.util.Log;
|
||||
import android.util.LogPrinter;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*
|
||||
* Implement a state machine where each state is an object,
|
||||
* HandlerState. Each HandlerState must implement processMessage
|
||||
* and optionally enter/exit. When a state machine is created
|
||||
* the initial state must be set. When messages are sent to
|
||||
* a state machine the current state's processMessage method is
|
||||
* invoked. If this is the first message for this state the
|
||||
* enter method is called prior to processMessage and when
|
||||
* transtionTo is invoked the state's exit method will be
|
||||
* called after returning from processMessage.
|
||||
*
|
||||
* If a message should be handled in a different state the
|
||||
* processMessage method may call deferMessage. This causes
|
||||
* the message to be saved on a list until transitioning
|
||||
* to a new state, at which time all of the deferred messages
|
||||
* will be put on the front of the state machines queue and
|
||||
* processed by the new current state's processMessage
|
||||
* method.
|
||||
*
|
||||
* Below is an example state machine with two state's, S1 and S2.
|
||||
* The initial state is S1 which defers all messages and only
|
||||
* transition to S2 when message.what == TEST_WHAT_2. State S2
|
||||
* will process each messages until it receives TEST_WHAT_2
|
||||
* where it will transition back to S1:
|
||||
<code>
|
||||
class StateMachine1 extends HandlerStateMachine {
|
||||
private static final int TEST_WHAT_1 = 1;
|
||||
private static final int TEST_WHAT_2 = 2;
|
||||
|
||||
StateMachine1(String name) {
|
||||
super(name);
|
||||
setInitialState(mS1);
|
||||
}
|
||||
|
||||
class S1 extends HandlerState {
|
||||
&#064;Override public void enter(Message message) {
|
||||
}
|
||||
|
||||
&#064;Override public void processMessage(Message message) {
|
||||
deferMessage(message);
|
||||
if (message.what == TEST_WHAT_2) {
|
||||
transitionTo(mS2);
|
||||
}
|
||||
}
|
||||
|
||||
&#064;Override public void exit(Message message) {
|
||||
}
|
||||
}
|
||||
|
||||
class S2 extends HandlerState {
|
||||
&#064;Override public void processMessage(Message message) {
|
||||
// Do some processing
|
||||
if (message.what == TEST_WHAT_2) {
|
||||
transtionTo(mS1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private S1 mS1 = new S1();
|
||||
private S2 mS2 = new S2();
|
||||
}
|
||||
</code>
|
||||
*/
|
||||
public class HandlerStateMachine {
|
||||
|
||||
private boolean mDbg = false;
|
||||
private static final String TAG = "HandlerStateMachine";
|
||||
private String mName;
|
||||
private SmHandler mHandler;
|
||||
private HandlerThread mHandlerThread;
|
||||
|
||||
/**
|
||||
* Handle messages sent to the state machine by calling
|
||||
* the current state's processMessage. It also handles
|
||||
* the enter/exit calls and placing any deferred messages
|
||||
* back onto the queue when transitioning to a new state.
|
||||
*/
|
||||
class SmHandler extends Handler {
|
||||
|
||||
SmHandler(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will dispatch the message to the
|
||||
* current state's processMessage.
|
||||
*/
|
||||
@Override
|
||||
final public void handleMessage(Message msg) {
|
||||
if (mDbg) Log.d(TAG, "SmHandler.handleMessage E");
|
||||
if (mDestState != null) {
|
||||
if (mDbg) Log.d(TAG, "SmHandler.handleMessage; new destation call enter");
|
||||
mCurrentState = mDestState;
|
||||
mDestState = null;
|
||||
mCurrentState.enter(msg);
|
||||
}
|
||||
if (mCurrentState != null) {
|
||||
if (mDbg) Log.d(TAG, "SmHandler.handleMessage; call processMessage");
|
||||
mCurrentState.processMessage(msg);
|
||||
} else {
|
||||
/* Strange no state to execute */
|
||||
Log.e(TAG, "handleMessage: no current state, did you call setInitialState");
|
||||
}
|
||||
|
||||
if (mDestState != null) {
|
||||
if (mDbg) Log.d(TAG, "SmHandler.handleMessage; new destination call exit");
|
||||
mCurrentState.exit(msg);
|
||||
|
||||
/**
|
||||
* Place the messages from the deferred queue:t
|
||||
* on to the Handler's message queue in the
|
||||
* same order that they originally arrived.
|
||||
*
|
||||
* We set cur.when = 0 to circumvent the check
|
||||
* that this message has already been sent.
|
||||
*/
|
||||
while (mDeferredMessages != null) {
|
||||
Message cur = mDeferredMessages;
|
||||
mDeferredMessages = mDeferredMessages.next;
|
||||
cur.when = 0;
|
||||
if (mDbg) Log.d(TAG, "SmHandler.handleMessage; queue deferred message what="
|
||||
+ cur.what + " target=" + cur.target);
|
||||
sendMessageAtFrontOfQueue(cur);
|
||||
}
|
||||
if (mDbg) Log.d(TAG, "SmHandler.handleMessage X");
|
||||
}
|
||||
}
|
||||
|
||||
public HandlerState mCurrentState;
|
||||
public HandlerState mDestState;
|
||||
public Message mDeferredMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an active StateMachine, one that has a
|
||||
* dedicated thread/looper/queue.
|
||||
*/
|
||||
public HandlerStateMachine(String name) {
|
||||
mName = name;
|
||||
mHandlerThread = new HandlerThread(name);
|
||||
mHandlerThread.start();
|
||||
mHandler = new SmHandler(mHandlerThread.getLooper());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a message and set Message.target = this.
|
||||
*/
|
||||
public final Message obtainMessage()
|
||||
{
|
||||
Message msg = Message.obtain(mHandler);
|
||||
if (mDbg) Log.d(TAG, "StateMachine.obtainMessage() EX target=" + msg.target);
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a message and set Message.target = this and
|
||||
* Message.what = what.
|
||||
*/
|
||||
public final Message obtainMessage(int what) {
|
||||
Message msg = Message.obtain(mHandler, what);
|
||||
if (mDbg) {
|
||||
Log.d(TAG, "StateMachine.obtainMessage(what) EX what=" + msg.what +
|
||||
" target=" + msg.target);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue a message to this state machine.
|
||||
*/
|
||||
public final void sendMessage(Message msg) {
|
||||
if (mDbg) Log.d(TAG, "StateMachine.sendMessage EX msg.what=" + msg.what);
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue a message to this state machine after a delay.
|
||||
*/
|
||||
public final void sendMessageDelayed(Message msg, long delayMillis) {
|
||||
if (mDbg) {
|
||||
Log.d(TAG, "StateMachine.sendMessageDelayed EX msg.what="
|
||||
+ msg.what + " delay=" + delayMillis);
|
||||
}
|
||||
mHandler.sendMessageDelayed(msg, delayMillis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the initial state. This must be invoked before
|
||||
* and messages are sent to the state machine.
|
||||
*/
|
||||
public void setInitialState(HandlerState initialState) {
|
||||
if (mDbg) {
|
||||
Log.d(TAG, "StateMachine.setInitialState EX initialState"
|
||||
+ initialState.getClass().getName());
|
||||
}
|
||||
mHandler.mDestState = initialState;
|
||||
}
|
||||
|
||||
/**
|
||||
* transition to destination state. Upon returning
|
||||
* from processMessage the current state's exit will
|
||||
* be executed and upon the next message arriving
|
||||
* destState.enter will be invoked.
|
||||
*/
|
||||
final public void transitionTo(HandlerState destState) {
|
||||
if (mDbg) {
|
||||
Log.d(TAG, "StateMachine.transitionTo EX destState"
|
||||
+ destState.getClass().getName());
|
||||
}
|
||||
mHandler.mDestState = destState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defer this message until next state transition.
|
||||
* Upon transitioning all deferred messages will be
|
||||
* placed on the queue and reprocessed in the original
|
||||
* order. (i.e. The next state the oldest messages will
|
||||
* be processed first)
|
||||
*/
|
||||
final public void deferMessage(Message msg) {
|
||||
if (mDbg) {
|
||||
Log.d(TAG, "StateMachine.deferMessage EX mDeferredMessages="
|
||||
+ mHandler.mDeferredMessages);
|
||||
}
|
||||
|
||||
/* Copy the "msg" to "newMsg" as "msg" will be recycled */
|
||||
Message newMsg = obtainMessage();
|
||||
newMsg.copyFrom(msg);
|
||||
|
||||
/* Place on front of queue */
|
||||
newMsg.next = mHandler.mDeferredMessages;
|
||||
mHandler.mDeferredMessages = newMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Handler
|
||||
*/
|
||||
public Handler getHandler() {
|
||||
return mHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if debugging is enabled
|
||||
*/
|
||||
public boolean isDbg() {
|
||||
return mDbg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set debug enable/disabled.
|
||||
*/
|
||||
public void setDbg(boolean dbg) {
|
||||
mDbg = dbg;
|
||||
if (mDbg) {
|
||||
mHandlerThread.getLooper().setMessageLogging(new LogPrinter(Log.VERBOSE, TAG));
|
||||
} else {
|
||||
mHandlerThread.getLooper().setMessageLogging(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
75
core/java/com/android/internal/util/HierarchicalState.java
Normal file
75
core/java/com/android/internal/util/HierarchicalState.java
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*
|
||||
* The abstract class for implementing states in a
|
||||
* HierarchicalStateMachine and HandlerStateMachine.
|
||||
*/
|
||||
public abstract class HierarchicalState {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
protected HierarchicalState() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a state is entered.
|
||||
*/
|
||||
protected void enter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a message is to be processed by the
|
||||
* state machine.
|
||||
*
|
||||
* This routine is never reentered thus no synchronization
|
||||
* is needed as only one processMessage method will ever be
|
||||
* executing within a state machine at any given time. This
|
||||
* does mean that processing by this routine must be completed
|
||||
* as expeditiously as possible as no subsequent messages will
|
||||
* be processed until this routine returns.
|
||||
*
|
||||
* @param msg to process
|
||||
* @return true if processing has completed and false
|
||||
* if the parent state's processMessage should
|
||||
* be invoked.
|
||||
*/
|
||||
abstract protected boolean processMessage(Message msg);
|
||||
|
||||
/**
|
||||
* Called when a state is exited.
|
||||
*/
|
||||
protected void exit() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return name of state, but default returns the states
|
||||
* class name. An instance name would be better but requiring
|
||||
* it seems unnecessary.
|
||||
*/
|
||||
public String getName() {
|
||||
String name = getClass().getName();
|
||||
int lastDollar = name.lastIndexOf('$');
|
||||
return name.substring(lastDollar + 1);
|
||||
}
|
||||
}
|
||||
1164
core/java/com/android/internal/util/HierarchicalStateMachine.java
Normal file
1164
core/java/com/android/internal/util/HierarchicalStateMachine.java
Normal file
File diff suppressed because it is too large
Load Diff
198
core/java/com/android/internal/util/ProcessedMessages.java
Normal file
198
core/java/com/android/internal/util/ProcessedMessages.java
Normal file
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,7 +203,7 @@ class CommandParamsFactory extends Handler {
|
||||
}
|
||||
|
||||
private void sendCmdParams(ResultCode resCode) {
|
||||
mCaller.sendMessageParamsDecoded(resCode, mCmdParams);
|
||||
mCaller.sendMsgParamsDecoded(resCode, mCmdParams);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,18 +20,18 @@ import com.android.internal.telephony.gsm.SIMFileHandler;
|
||||
import com.android.internal.telephony.IccUtils;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerState;
|
||||
import android.os.HandlerStateMachine;
|
||||
import com.android.internal.util.HierarchicalState;
|
||||
import com.android.internal.util.HierarchicalStateMachine;
|
||||
import android.os.Message;
|
||||
|
||||
/**
|
||||
* Class used for queuing raw ril messages, decoding them into CommanParams
|
||||
* objects and sending the result back to the STK Service.
|
||||
*/
|
||||
class RilMessageDecoder extends HandlerStateMachine {
|
||||
class RilMessageDecoder extends HierarchicalStateMachine {
|
||||
|
||||
// constants
|
||||
private static final int START = 1;
|
||||
private static final int CMD_START = 1;
|
||||
private static final int CMD_PARAMS_READY = 2;
|
||||
|
||||
// members
|
||||
@@ -54,6 +54,7 @@ class RilMessageDecoder extends HandlerStateMachine {
|
||||
public static synchronized RilMessageDecoder getInstance(Handler caller, SIMFileHandler fh) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new RilMessageDecoder(caller, fh);
|
||||
sInstance.start();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
@@ -65,7 +66,7 @@ class RilMessageDecoder extends HandlerStateMachine {
|
||||
* @param rilMsg
|
||||
*/
|
||||
public void sendStartDecodingMessageParams(RilMessage rilMsg) {
|
||||
Message msg = obtainMessage(START);
|
||||
Message msg = obtainMessage(CMD_START);
|
||||
msg.obj = rilMsg;
|
||||
sendMessage(msg);
|
||||
}
|
||||
@@ -76,7 +77,7 @@ class RilMessageDecoder extends HandlerStateMachine {
|
||||
* @param resCode
|
||||
* @param cmdParams
|
||||
*/
|
||||
public void sendMessageParamsDecoded(ResultCode resCode, CommandParams cmdParams) {
|
||||
public void sendMsgParamsDecoded(ResultCode resCode, CommandParams cmdParams) {
|
||||
Message msg = obtainMessage(RilMessageDecoder.CMD_PARAMS_READY);
|
||||
msg.arg1 = resCode.value();
|
||||
msg.obj = cmdParams;
|
||||
@@ -91,28 +92,31 @@ class RilMessageDecoder extends HandlerStateMachine {
|
||||
|
||||
private RilMessageDecoder(Handler caller, SIMFileHandler fh) {
|
||||
super("RilMessageDecoder");
|
||||
setDbg(false);
|
||||
|
||||
addState(mStateStart);
|
||||
addState(mStateCmdParamsReady);
|
||||
setInitialState(mStateStart);
|
||||
|
||||
mCaller = caller;
|
||||
mCmdParamsFactory = CommandParamsFactory.getInstance(this, fh);
|
||||
}
|
||||
|
||||
private class StateStart extends HandlerState {
|
||||
@Override public void processMessage(Message msg) {
|
||||
if (msg.what == START) {
|
||||
private class StateStart extends HierarchicalState {
|
||||
@Override protected boolean processMessage(Message msg) {
|
||||
if (msg.what == CMD_START) {
|
||||
if (decodeMessageParams((RilMessage)msg.obj)) {
|
||||
transitionTo(mStateCmdParamsReady);
|
||||
}
|
||||
} else {
|
||||
StkLog.d(this, "StateStart unexpected expecting START=" +
|
||||
START + " got " + msg.what);
|
||||
CMD_START + " got " + msg.what);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class StateCmdParamsReady extends HandlerState {
|
||||
@Override public void processMessage(Message msg) {
|
||||
private class StateCmdParamsReady extends HierarchicalState {
|
||||
@Override protected boolean processMessage(Message msg) {
|
||||
if (msg.what == CMD_PARAMS_READY) {
|
||||
mCurrentRilMessage.mResCode = ResultCode.fromInt(msg.arg1);
|
||||
mCurrentRilMessage.mData = msg.obj;
|
||||
@@ -123,6 +127,7 @@ class RilMessageDecoder extends HandlerStateMachine {
|
||||
+ CMD_PARAMS_READY + " got " + msg.what);
|
||||
deferMessage(msg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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.unit_tests.os;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import java.util.Vector;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerState;
|
||||
import android.os.HandlerStateMachine;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Process;
|
||||
import android.os.Message;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class HandlerStateMachineTest extends TestCase {
|
||||
private static final int TEST_WHAT_1 = 1;
|
||||
private static final int TEST_WHAT_2 = 2;
|
||||
|
||||
private static final boolean DBG = false;
|
||||
private static final String TAG = "HandlerStateMachineTest";
|
||||
|
||||
private boolean mDidEnter = false;
|
||||
private boolean mDidExit = false;
|
||||
private Vector<Integer> mGotMessagesWhat = new Vector<Integer>();
|
||||
|
||||
/**
|
||||
* This test statemachine has two states, it receives
|
||||
* two messages in state mS1 deferring them until what == TEST_WHAT_2
|
||||
* and then transitions to state mS2. State mS2 should then receive
|
||||
* both of the deferred messages first TEST_WHAT_1 and then TEST_WHAT_2.
|
||||
* When TEST_WHAT_2 is received it invokes notifyAll so the test can
|
||||
* conclude.
|
||||
*/
|
||||
class StateMachine1 extends HandlerStateMachine {
|
||||
StateMachine1(String name) {
|
||||
super(name);
|
||||
mThisSm = this;
|
||||
setDbg(DBG);
|
||||
setInitialState(mS1);
|
||||
}
|
||||
|
||||
class S1 extends HandlerState {
|
||||
@Override public void enter(Message message) {
|
||||
mDidEnter = true;
|
||||
}
|
||||
|
||||
@Override public void processMessage(Message message) {
|
||||
deferMessage(message);
|
||||
if (message.what == TEST_WHAT_2) {
|
||||
transitionTo(mS2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void exit(Message message) {
|
||||
mDidExit = true;
|
||||
}
|
||||
}
|
||||
|
||||
class S2 extends HandlerState {
|
||||
@Override public void processMessage(Message message) {
|
||||
mGotMessagesWhat.add(message.what);
|
||||
if (message.what == TEST_WHAT_2) {
|
||||
synchronized (mThisSm) {
|
||||
mThisSm.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private StateMachine1 mThisSm;
|
||||
private S1 mS1 = new S1();
|
||||
private S2 mS2 = new S2();
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testStateMachine1() throws Exception {
|
||||
StateMachine1 sm1 = new StateMachine1("sm1");
|
||||
if (sm1.isDbg()) Log.d(TAG, "testStateMachine1 E");
|
||||
|
||||
synchronized (sm1) {
|
||||
// Send two messages
|
||||
sm1.sendMessage(sm1.obtainMessage(TEST_WHAT_1));
|
||||
sm1.sendMessage(sm1.obtainMessage(TEST_WHAT_2));
|
||||
|
||||
try {
|
||||
// wait for the messages to be handled
|
||||
sm1.wait();
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, "testStateMachine1: exception while waiting " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(mDidEnter);
|
||||
assertTrue(mDidExit);
|
||||
assertTrue(mGotMessagesWhat.size() == 2);
|
||||
assertTrue(mGotMessagesWhat.get(0) == TEST_WHAT_1);
|
||||
assertTrue(mGotMessagesWhat.get(1) == TEST_WHAT_2);
|
||||
if (sm1.isDbg()) Log.d(TAG, "testStateMachine1 X");
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user