Skip to content
Snippets Groups Projects
Commit 6551cc56 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "SyncSM03: implement state transition logic" into main

parents 1bc9f5c6 9e572d10
No related branches found
No related tags found
No related merge requests found
......@@ -140,8 +140,8 @@ public class SyncStateMachine {
ensureCorrectThread();
ensureExistingState(initialState);
mCurrentState = initialState;
mDestState = initialState;
performTransitions();
}
/**
......@@ -149,6 +149,8 @@ public class SyncStateMachine {
*/
public final void processMessage(int what, int arg1, int arg2, @Nullable Object obj) {
ensureCorrectThread();
performTransitions();
}
/**
......@@ -173,6 +175,65 @@ public class SyncStateMachine {
}
}
private void performTransitions() {
// 1. Determine the common ancestor state of current/destination states
// 2. Invoke state exit list from current state to common ancestor state.
// 3. Invoke state enter list from common ancestor state to destState by going
// through mEnterStateStack.
if (mDestState == mCurrentState) return;
final StateInfo commonAncestor = getLastActiveAncestor(mStateInfo.get(mDestState));
executeExitMethods(commonAncestor, mStateInfo.get(mCurrentState));
executeEnterMethods(commonAncestor, mStateInfo.get(mDestState));
mCurrentState = mDestState;
}
// Null is the root of all states.
private StateInfo getLastActiveAncestor(@Nullable final StateInfo start) {
if (null == start || start.mActive) return start;
return getLastActiveAncestor(mStateInfo.get(start.parent));
}
// Call the exit method from current state to common ancestor state.
// Both the commonAncestor and exitingState StateInfo can be null because null is the ancestor
// of all states.
// For example: When transitioning from state1 to state2, the
// executeExitMethods(commonAncestor, exitingState) function will be called twice, once with
// null and state1 as the argument, and once with null and null as the argument.
// root
// | \
// current <- state1 state2 -> destination
private void executeExitMethods(@Nullable StateInfo commonAncestor,
@Nullable StateInfo exitingState) {
if (commonAncestor == exitingState) return;
if (mDbg) Log.d(mName, exitingState.state + " exit()");
exitingState.state.exit();
exitingState.mActive = false;
executeExitMethods(commonAncestor, mStateInfo.get(exitingState.parent));
}
// Call the enter method from common ancestor state to destination state.
// Both the commonAncestor and enteringState StateInfo can be null because null is the ancestor
// of all states.
// For example: When transitioning from state1 to state2, the
// executeEnterMethods(commonAncestor, enteringState) function will be called twice, once with
// null and state2 as the argument, and once with null and null as the argument.
// root
// | \
// current <- state1 state2 -> destination
private void executeEnterMethods(@Nullable StateInfo commonAncestor,
@Nullable StateInfo enteringState) {
if (enteringState == commonAncestor) return;
executeEnterMethods(commonAncestor, mStateInfo.get(enteringState.parent));
if (mDbg) Log.d(mName, enteringState.state + " enter()");
enteringState.state.enter();
enteringState.mActive = true;
}
private void ensureCorrectThread() {
if (!mMyThread.equals(Thread.currentThread())) {
throw new IllegalStateException("Called from wrong thread");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment