diff options
author | Riddle Hsu <riddlehsu@google.com> | 2023-10-06 12:15:01 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-12-15 07:19:34 +0000 |
commit | 7f17bb5c5a6e33e3891ae3ba38a0aa21f889b550 (patch) | |
tree | 33c1a7b02efbfe47fc99a422088370c818540594 | |
parent | 1de674b401c71305fe8bbcf60191d64bc822e8b9 (diff) | |
download | base-7f17bb5c5a6e33e3891ae3ba38a0aa21f889b550.tar.gz |
Improve surface visibility recovering with transition
For example:
1. A transition contains an incorrect info which will set X
to be invisible.
2. When the transition is playing, set the surface of X to
visible directly if there is no collecting transition.
3. The transition of step 1 finishes, which applies invisible
to X, then the recovering of step 2 doesn't help.
So it will be more robust to recover until the playing transitions
are finished. Then it can also cover some cases of other visibility
validators.
Bug: 303613521
Test: Finish several activities when switching display.
The surface of foreground activity and its parent should
keep visible.
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3fc49ae16be0c421a9afa6fcfaa5d771747f059d)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b81e181cc5581e2acb174bcf1687c61efd741786)
Merged-In: I2ecb714ef0eaf94f8950bd4cd3857abfb1c46fbc
Change-Id: I2ecb714ef0eaf94f8950bd4cd3857abfb1c46fbc
3 files changed, 34 insertions, 35 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index cd0a4efad77e..d570c9e1acab 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -5346,18 +5346,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // rather than just direct membership. inFinishingTransition = mTransitionController.inFinishingTransition(this); if (!inFinishingTransition && (visible || !mDisplayContent.isSleeping())) { - Slog.e(TAG, "setVisibility=" + visible - + " while transition is not collecting or finishing " - + this + " caller=" + Debug.getCallers(8)); - // Force showing the parents because they may be hidden by previous transition. if (visible) { - final Transaction t = getSyncTransaction(); - for (WindowContainer<?> p = getParent(); p != null && p != mDisplayContent; - p = p.getParent()) { - if (p.mSurfaceControl != null) { - t.show(p.mSurfaceControl); - } - } + mTransitionController.onVisibleWithoutCollectingTransition(this, + Debug.getCallers(1, 1)); + } else { + Slog.w(TAG, "Set invisible without transition " + this); } } } diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index e7c6ff4d887f..7ef90fe12824 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -1374,7 +1374,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { dc.handleCompleteDeferredRemoval(); } validateKeyguardOcclusion(); - validateVisibility(); mState = STATE_FINISHED; // Rotation change may be deferred while there is a display change transition, so check @@ -2734,29 +2733,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } } - private void validateVisibility() { - for (int i = mTargets.size() - 1; i >= 0; --i) { - if (reduceMode(mTargets.get(i).mReadyMode) != TRANSIT_CLOSE) { - return; - } - } - // All modes are CLOSE. The surfaces may be hidden by the animation unexpectedly. - // If the window container should be visible, then recover it. - mController.mStateValidators.add(() -> { - for (int i = mTargets.size() - 1; i >= 0; --i) { - final ChangeInfo change = mTargets.get(i); - if (!change.mContainer.isVisibleRequested() - || change.mContainer.mSurfaceControl == null) { - continue; - } - Slog.e(TAG, "Force show for visible " + change.mContainer - + " which may be hidden by transition unexpectedly"); - change.mContainer.getSyncTransaction().show(change.mContainer.mSurfaceControl); - change.mContainer.scheduleAnimation(); - } - }); - } - /** * Returns {@code true} if the transition and the corresponding transaction should be applied * on display thread. Currently, this only checks for display rotation change because the order diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index a43a6f6292ae..577e755c310c 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -951,6 +951,36 @@ class TransitionController { mValidateDisplayVis.clear(); } + void onVisibleWithoutCollectingTransition(WindowContainer<?> wc, String caller) { + final boolean isPlaying = !mPlayingTransitions.isEmpty(); + Slog.e(TAG, "Set visible without transition " + wc + " playing=" + isPlaying + + " caller=" + caller); + if (!isPlaying) { + enforceSurfaceVisible(wc); + return; + } + // Update surface visibility after the playing transitions are finished, so the last + // visibility won't be replaced by the finish transaction of transition. + mStateValidators.add(() -> { + if (wc.isVisibleRequested()) { + enforceSurfaceVisible(wc); + } + }); + } + + private void enforceSurfaceVisible(WindowContainer<?> wc) { + if (wc.mSurfaceControl == null) return; + wc.getSyncTransaction().show(wc.mSurfaceControl); + // Force showing the parents because they may be hidden by previous transition. + for (WindowContainer<?> p = wc.getParent(); p != null && p != wc.mDisplayContent; + p = p.getParent()) { + if (p.mSurfaceControl != null) { + p.getSyncTransaction().show(p.mSurfaceControl); + } + } + wc.scheduleAnimation(); + } + /** * Called when the transition has a complete set of participants for its operation. In other * words, it is when the transition is "ready" but is still waiting for participants to draw. |