Merge "SyncSM02: implement addState function" into main
This commit is contained in:
@@ -18,11 +18,15 @@ package com.android.networkstack.tethering.util;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.util.State;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* An implementation of a state machine, meant to be called synchronously.
|
||||
@@ -35,6 +39,7 @@ public class SyncStateMachine {
|
||||
@NonNull private final String mName;
|
||||
@NonNull private final Thread mMyThread;
|
||||
private final boolean mDbg;
|
||||
private final ArrayMap<State, StateInfo> mStateInfo = new ArrayMap<>();
|
||||
|
||||
// mCurrentState is the current state. mDestState is the target state that mCurrentState will
|
||||
// transition to. The value of mDestState can be changed when a state processes a message and
|
||||
@@ -91,9 +96,9 @@ public class SyncStateMachine {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all of states to the state machine. Different StateInfos which have same state but have
|
||||
* different parents are not allowed. A state can not have multiple parent states.
|
||||
* This can only be called once either from mMyThread or before mMyThread started.
|
||||
* Add all of states to the state machine. Different StateInfos which have same state are not
|
||||
* allowed. In other words, a state can not have multiple parent states. #addAllStates can
|
||||
* only be called once either from mMyThread or before mMyThread started.
|
||||
*/
|
||||
public final void addAllStates(@NonNull final List<StateInfo> stateInfos) {
|
||||
ensureCorrectOrNotStartedThread();
|
||||
@@ -101,13 +106,39 @@ public class SyncStateMachine {
|
||||
if (mCurrentState != null) {
|
||||
throw new IllegalStateException("State only can be added before started");
|
||||
}
|
||||
|
||||
if (stateInfos.isEmpty()) throw new IllegalStateException("Empty state is not allowed");
|
||||
|
||||
if (!mStateInfo.isEmpty()) throw new IllegalStateException("States are already configured");
|
||||
|
||||
final Set<Class> usedClasses = new ArraySet<>();
|
||||
for (final StateInfo info : stateInfos) {
|
||||
Objects.requireNonNull(info.state);
|
||||
if (!usedClasses.add(info.state.getClass())) {
|
||||
throw new IllegalStateException("Adding the same state multiple times in a state "
|
||||
+ "machine is forbidden because it tends to be confusing; it can be done "
|
||||
+ "with anonymous subclasses but consider carefully whether you want to "
|
||||
+ "use a single state or other alternatives instead.");
|
||||
}
|
||||
|
||||
mStateInfo.put(info.state, info);
|
||||
}
|
||||
|
||||
// Check whether all of parent states indicated from StateInfo are added.
|
||||
for (final StateInfo info : stateInfos) {
|
||||
if (info.parent != null) ensureExistingState(info.parent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the state machine. The initial state can't be child state.
|
||||
*
|
||||
* @param initialState the first state of this machine. The state must be exact state object
|
||||
* setting up by {@link #addAllStates}, not a copy of it.
|
||||
*/
|
||||
public final void start(@NonNull final State initialState) {
|
||||
ensureCorrectThread();
|
||||
ensureExistingState(initialState);
|
||||
|
||||
mCurrentState = initialState;
|
||||
mDestState = initialState;
|
||||
@@ -127,11 +158,13 @@ public class SyncStateMachine {
|
||||
* This function can NOT be called inside the State enter and exit function. The transition
|
||||
* target is always defined and can never be changed mid-way of state transition.
|
||||
*
|
||||
* @param destState will be the state to transition to.
|
||||
* @param destState will be the state to transition to. The state must be the same instance set
|
||||
* up by {@link #addAllStates}, not a copy of it.
|
||||
*/
|
||||
public final void transitionTo(@NonNull final State destState) {
|
||||
if (mDbg) Log.d(mName, "transitionTo " + destState);
|
||||
ensureCorrectThread();
|
||||
ensureExistingState(destState);
|
||||
|
||||
if (mDestState == mCurrentState) {
|
||||
mDestState = destState;
|
||||
@@ -151,4 +184,8 @@ public class SyncStateMachine {
|
||||
|
||||
ensureCorrectThread();
|
||||
}
|
||||
|
||||
private void ensureExistingState(@NonNull final State state) {
|
||||
if (!mStateInfo.containsKey(state)) throw new IllegalStateException("Invalid state");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user