diff options
7 files changed, 48 insertions, 13 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index d249f8c3ab40..1e42f16e13c5 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -5263,13 +5263,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Before setting mVisibleRequested so we can track changes. boolean isCollecting = false; + boolean inFinishingTransition = false; if (mTransitionController.isShellTransitionsEnabled()) { isCollecting = mTransitionController.isCollecting(); if (isCollecting) { mTransitionController.collect(this); } else { - Slog.e(TAG, "setVisibility=" + visible + " while transition is not collecting " - + this + " caller=" + Debug.getCallers(8)); + inFinishingTransition = mTransitionController.inFinishingTransition(this); + if (!inFinishingTransition) { + Slog.e(TAG, "setVisibility=" + visible + + " while transition is not collecting or finishing " + + this + " caller=" + Debug.getCallers(8)); + } } } @@ -5346,6 +5351,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } return; } + if (inFinishingTransition) { + // Let the finishing transition commit the visibility. + return; + } // If we are preparing an app transition, then delay changing // the visibility of this token until we execute that transition. if (deferCommitVisibilityChange(visible)) { diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 4e0f120759d9..89feb0cc5e4a 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -814,6 +814,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { if (mState < STATE_PLAYING) { throw new IllegalStateException("Can't finish a non-playing transition " + mSyncId); } + mController.mFinishingTransition = this; boolean hasParticipatedDisplay = false; boolean hasVisibleTransientLaunch = false; @@ -995,6 +996,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { // Handle back animation if it's already started. mController.mAtm.mBackNavigationController.handleDeferredBackAnimation(mTargets); + mController.mFinishingTransition = null; } void abort() { @@ -1274,7 +1276,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { if (mFinishTransaction != null) { mFinishTransaction.apply(); } - mController.finishTransition(mToken); + mController.finishTransition(this); } private void cleanUpInternal() { diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index bacc6e615ed1..59264e9b6ea0 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -107,6 +107,9 @@ class TransitionController { */ private final ArrayList<Transition> mPlayingTransitions = new ArrayList<>(); + /** The currently finishing transition. */ + Transition mFinishingTransition; + /** * The windows that request to be invisible while it is in transition. After the transition * is finished and the windows are no longer animating, their surfaces will be destroyed. @@ -313,6 +316,11 @@ class TransitionController { return false; } + /** Returns {@code true} if the `wc` is a participant of the finishing transition. */ + boolean inFinishingTransition(WindowContainer<?> wc) { + return mFinishingTransition != null && mFinishingTransition.mParticipants.contains(wc); + } + /** @return {@code true} if a transition is running */ boolean inTransition() { // TODO(shell-transitions): eventually properly support multiple @@ -672,14 +680,13 @@ class TransitionController { } /** @see Transition#finishTransition */ - void finishTransition(@NonNull IBinder token) { + void finishTransition(Transition record) { // It is usually a no-op but make sure that the metric consumer is removed. - mTransitionMetricsReporter.reportAnimationStart(token, 0 /* startTime */); + mTransitionMetricsReporter.reportAnimationStart(record.getToken(), 0 /* startTime */); // It is a no-op if the transition did not change the display. mAtm.endLaunchPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY); - final Transition record = Transition.fromBinder(token); - if (record == null || !mPlayingTransitions.contains(record)) { - Slog.e(TAG, "Trying to finish a non-playing transition " + token); + if (!mPlayingTransitions.contains(record)) { + Slog.e(TAG, "Trying to finish a non-playing transition " + record); return; } ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Finish Transition: %s", record); diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index c3c87af51b15..95606d049ed7 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -391,9 +391,14 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub // apply the incoming transaction before finish in case it alters the visibility // of the participants. if (t != null) { + // Set the finishing transition before applyTransaction so the visibility + // changes of the transition participants will only set visible-requested + // and still let finishTransition handle the participants. + mTransitionController.mFinishingTransition = transition; applyTransaction(t, syncId, null /*transition*/, caller, transition); } - getTransitionController().finishTransition(transitionToken); + mTransitionController.finishTransition(transition); + mTransitionController.mFinishingTransition = null; if (syncId >= 0) { setSyncReady(syncId); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java index 304581297932..3cbe2de13702 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -1391,7 +1391,7 @@ public class TransitionTests extends WindowTestsBase { verify(snapshotController, times(1)).recordSnapshot(eq(task2), eq(false)); - openTransition.finishTransition(); + controller.finishTransition(openTransition); // We are now going to simulate closing task1 to return back to (open) task2. final Transition closeTransition = controller.createTransition(TRANSIT_CLOSE); @@ -1416,7 +1416,19 @@ public class TransitionTests extends WindowTestsBase { verify(snapshotController, times(0)).recordSnapshot(eq(task1), eq(false)); enteringAnimReports.clear(); - closeTransition.finishTransition(); + final boolean[] wasInFinishingTransition = { false }; + controller.registerLegacyListener(new WindowManagerInternal.AppTransitionListener() { + @Override + public void onAppTransitionFinishedLocked(IBinder token) { + final ActivityRecord r = ActivityRecord.forToken(token); + if (r != null) { + wasInFinishingTransition[0] = controller.inFinishingTransition(r); + } + } + }); + controller.finishTransition(closeTransition); + assertTrue(wasInFinishingTransition[0]); + assertNull(controller.mFinishingTransition); assertEquals(ActivityTaskManagerService.APP_SWITCH_DISALLOW, mAtm.getBalAppSwitchesState()); assertFalse(activity1.app.hasActivityInVisibleTask()); diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java index 65631ea11e81..984b868ab67f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java @@ -396,7 +396,7 @@ public class WallpaperControllerTests extends WindowTestsBase { final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class); token.finishSync(t, false /* cancel */); transit.onTransactionReady(transit.getSyncId(), t); - dc.mTransitionController.finishTransition(transit.getToken()); + dc.mTransitionController.finishTransition(transit); assertFalse(wallpaperWindow.isVisible()); assertFalse(token.isVisible()); } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index ce6cd9023e5c..b80500ad6417 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -1799,7 +1799,7 @@ class WindowTestsBase extends SystemServiceTestsBase { } public void finish() { - mController.finishTransition(mLastTransit.getToken()); + mController.finishTransition(mLastTransit); } } } |