diff options
| author | 2023-11-10 11:47:06 -0800 | |
|---|---|---|
| committer | 2023-11-16 14:39:44 -0800 | |
| commit | cbc82b9d8a5ddb3697f86a8868ba84b0f5a2461c (patch) | |
| tree | bac5358162aa29e0da8d403f59bb3d366c244bb8 | |
| parent | 66c0d06e0c57f00f57d846e17ab02ad3ced61820 (diff) | |
Try to recover when receiving unexpected transitionReady
Basically, since everywhere else in the system tends to
propagate bad states, we have to also do the same. This
basically tries to just handle a transition even if it
wasn't told about it beforehand.
Bug: 278781290
Test: This is replacing a crash, so N/A
Change-Id: Ib367976ae21b97fe726abd9edd399cc18da0742d
| -rw-r--r-- | libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java index ab5c0636f2b5..b12e3a109267 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java @@ -654,12 +654,27 @@ public class Transitions implements RemoteCallable<Transitions>, info.setUnreleasedWarningCallSiteForAllSurfaces("Transitions.onTransitionReady"); ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "onTransitionReady (#%d) %s: %s", info.getDebugId(), transitionToken, info); - final int activeIdx = findByToken(mPendingTransitions, transitionToken); + int activeIdx = findByToken(mPendingTransitions, transitionToken); if (activeIdx < 0) { - throw new IllegalStateException("Got transitionReady for non-pending transition " + final ActiveTransition existing = getKnownTransition(transitionToken); + if (existing != null) { + Log.e(TAG, "Got duplicate transitionReady for " + transitionToken); + // The transition is already somewhere else in the pipeline, so just return here. + t.apply(); + existing.mFinishT.merge(finishT); + return; + } + // This usually means the system is in a bad state and may not recover; however, + // there's an incentive to propagate bad states rather than crash, so we're kinda + // required to do the same thing I guess. + Log.wtf(TAG, "Got transitionReady for non-pending transition " + transitionToken + ". expecting one of " + Arrays.toString(mPendingTransitions.stream().map( activeTransition -> activeTransition.mToken).toArray())); + final ActiveTransition fallback = new ActiveTransition(); + fallback.mToken = transitionToken; + mPendingTransitions.add(fallback); + activeIdx = mPendingTransitions.size() - 1; } // Move from pending to ready final ActiveTransition active = mPendingTransitions.remove(activeIdx); @@ -1050,34 +1065,43 @@ public class Transitions implements RemoteCallable<Transitions>, processReadyQueue(track); } - private boolean isTransitionKnown(IBinder token) { + /** + * Checks to see if the transition specified by `token` is already known. If so, it will be + * returned. + */ + @Nullable + private ActiveTransition getKnownTransition(IBinder token) { for (int i = 0; i < mPendingTransitions.size(); ++i) { - if (mPendingTransitions.get(i).mToken == token) return true; + final ActiveTransition active = mPendingTransitions.get(i); + if (active.mToken == token) return active; } for (int i = 0; i < mReadyDuringSync.size(); ++i) { - if (mReadyDuringSync.get(i).mToken == token) return true; + final ActiveTransition active = mReadyDuringSync.get(i); + if (active.mToken == token) return active; } for (int t = 0; t < mTracks.size(); ++t) { final Track tr = mTracks.get(t); for (int i = 0; i < tr.mReadyTransitions.size(); ++i) { - if (tr.mReadyTransitions.get(i).mToken == token) return true; + final ActiveTransition active = tr.mReadyTransitions.get(i); + if (active.mToken == token) return active; } final ActiveTransition active = tr.mActiveTransition; if (active == null) continue; - if (active.mToken == token) return true; + if (active.mToken == token) return active; if (active.mMerged == null) continue; for (int m = 0; m < active.mMerged.size(); ++m) { - if (active.mMerged.get(m).mToken == token) return true; + final ActiveTransition merged = active.mMerged.get(m); + if (merged.mToken == token) return merged; } } - return false; + return null; } void requestStartTransition(@NonNull IBinder transitionToken, @Nullable TransitionRequestInfo request) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition requested (#%d): %s %s", request.getDebugId(), transitionToken, request); - if (isTransitionKnown(transitionToken)) { + if (getKnownTransition(transitionToken) != null) { throw new RuntimeException("Transition already started " + transitionToken); } final ActiveTransition active = new ActiveTransition(); @@ -1161,7 +1185,7 @@ public class Transitions implements RemoteCallable<Transitions>, */ private void finishForSync(ActiveTransition reason, int trackIdx, @Nullable ActiveTransition forceFinish) { - if (!isTransitionKnown(reason.mToken)) { + if (getKnownTransition(reason.mToken) == null) { Log.d(TAG, "finishForSleep: already played sync transition " + reason); return; } |