From 4cb5549a508856adad4e51ab777ca17ad242cfff Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Wed, 10 Aug 2022 23:49:53 +0800 Subject: [PATCH] Collect changes for transition right before updating config Otherwise if display configuration is updated first, the later collect() may not detect change. Such as if an activity with ROTATION_ANIMATION_SEAMLESS is not included in TransitionInfo, the animation will still be screenshot based style. Bug: 240238575 Test: SeamlessAppRotationTest Change-Id: I53f4212dad210cacdc4c243475ab1ab6355fe53b --- .../com/android/server/wm/DisplayArea.java | 1 + .../com/android/server/wm/DisplayContent.java | 6 ++--- .../android/server/wm/DisplayRotation.java | 18 --------------- ...ysicalDisplaySwitchTransitionLauncher.java | 1 - .../com/android/server/wm/Transition.java | 13 +++++++++++ .../server/wm/TransitionController.java | 11 +++++----- .../server/wm/WindowOrganizerController.java | 22 ++----------------- .../server/wm/DisplayContentTests.java | 2 +- 8 files changed, 25 insertions(+), 49 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index 04229063732f0..b033dca465f4c 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -504,6 +504,7 @@ public class DisplayArea extends WindowContainer { @Override public void onConfigurationChanged(Configuration newParentConfig) { + mTransitionController.collectForDisplayAreaChange(this); mTmpConfiguration.setTo(getConfiguration()); super.onConfigurationChanged(newParentConfig); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index ecb9fe3a00ccf..17f43b1955e8a 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -5935,6 +5935,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (changes != 0) { Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " " + mTempConfig + " for displayId=" + mDisplayId); + if (isReady() && mTransitionController.isShellTransitionsEnabled()) { + requestChangeTransitionIfNeeded(changes, null /* displayChange */); + } onRequestedOverrideConfigurationChanged(mTempConfig); final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0; @@ -5951,9 +5954,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } mWmService.mDisplayNotificationController.dispatchDisplayChanged( this, getConfiguration()); - if (isReady() && mTransitionController.isShellTransitionsEnabled()) { - requestChangeTransitionIfNeeded(changes, null /* displayChange */); - } } return changes; } diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 8dd58506ef0b9..97609a7dd8ba3 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -513,19 +513,6 @@ public class DisplayRotation { return true; } - /** - * Utility to get a rotating displaycontent from a Transition. - * @return null if the transition doesn't contain a rotating display. - */ - static DisplayContent getDisplayFromTransition(Transition transition) { - for (int i = transition.mParticipants.size() - 1; i >= 0; --i) { - final WindowContainer wc = transition.mParticipants.valueAt(i); - if (!(wc instanceof DisplayContent)) continue; - return (DisplayContent) wc; - } - return null; - } - private void startRemoteRotation(int fromRotation, int toRotation) { mDisplayContent.mRemoteDisplayChangeController.performRemoteDisplayChange( fromRotation, toRotation, null /* newDisplayAreaInfo */, @@ -545,11 +532,6 @@ public class DisplayRotation { throw new IllegalStateException("Trying to rotate outside a transition"); } mDisplayContent.mTransitionController.collect(mDisplayContent); - // Go through all tasks and collect them before the rotation - // TODO(shell-transitions): move collect() to onConfigurationChange once wallpaper - // handling is synchronized. - mDisplayContent.mTransitionController.collectForDisplayAreaChange(mDisplayContent, - null /* use collecting transition */); } mService.mAtmService.deferWindowLayout(); try { diff --git a/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java b/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java index 64749cf94ddfc..a89894db4b4b4 100644 --- a/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java +++ b/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java @@ -101,7 +101,6 @@ public class PhysicalDisplaySwitchTransitionLauncher { if (t != null) { mDisplayContent.mAtmService.startLaunchPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY); - mTransitionController.collectForDisplayAreaChange(mDisplayContent, t); mTransition = t; } } diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 584a40e047005..99ed3434f72b6 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -1634,6 +1634,19 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe return mainWin.getAttrs().rotationAnimation; } + /** Applies the new configuration and returns {@code true} if there is a display change. */ + boolean applyDisplayChangeIfNeeded() { + boolean changed = false; + for (int i = mParticipants.size() - 1; i >= 0; --i) { + final WindowContainer wc = mParticipants.valueAt(i); + final DisplayContent dc = wc.asDisplayContent(); + if (dc == null || !mChanges.get(dc).hasChanged(dc)) continue; + dc.sendNewConfiguration(); + changed = true; + } + return changed; + } + boolean getLegacyIsReady() { return isCollecting() && mSyncId >= 0; } diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index 4f324f22aa5ea..846aa3e3739a1 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -463,13 +463,12 @@ class TransitionController { } /** - * Collects the window containers which need to be synced with the changing display (e.g. - * rotating) to the given transition or the current collecting transition. + * Collects the window containers which need to be synced with the changing display area into + * the current collecting transition. */ - void collectForDisplayAreaChange(@NonNull DisplayArea wc, @Nullable Transition incoming) { - if (incoming == null) incoming = mCollectingTransition; - if (incoming == null) return; - final Transition transition = incoming; + void collectForDisplayAreaChange(@NonNull DisplayArea wc) { + final Transition transition = mCollectingTransition; + if (transition == null || !transition.mParticipants.contains(wc)) return; // Collect all visible tasks. wc.forAllLeafTasks(task -> { if (task.isVisible()) { diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 3b9cd368a93bb..4f03264b15565 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -397,17 +397,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub mService.deferWindowLayout(); mService.mTaskSupervisor.setDeferRootVisibilityUpdate(true /* deferUpdate */); try { - if (transition != null) { - // First check if we have a display rotation transition and if so, update it. - final DisplayContent dc = DisplayRotation.getDisplayFromTransition(transition); - if (dc != null && transition.mChanges.get(dc).hasChanged(dc)) { - // Go through all tasks and collect them before the rotation - // TODO(shell-transitions): move collect() to onConfigurationChange once - // wallpaper handling is synchronized. - dc.mTransitionController.collectForDisplayAreaChange(dc, transition); - dc.sendNewConfiguration(); - effects |= TRANSACT_EFFECTS_LIFECYCLE; - } + if (transition != null && transition.applyDisplayChangeIfNeeded()) { + effects |= TRANSACT_EFFECTS_LIFECYCLE; } final List hops = t.getHierarchyOps(); final int hopSize = hops.size(); @@ -428,15 +419,6 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub addToSyncSet(syncId, wc); } if (transition != null) transition.collect(wc); - final DisplayArea da = wc.asDisplayArea(); - // Only check DisplayArea here as a similar thing is done for DisplayContent above. - if (da != null && wc.asDisplayContent() == null - && entry.getValue().getWindowingMode() != da.getWindowingMode()) { - // Go through all tasks and collect them before changing the windowing mode of a - // display-level container. - // TODO(shell-transitions): handle this more elegantly. - da.mTransitionController.collectForDisplayAreaChange(da, transition); - } if ((entry.getValue().getChangeMask() & WindowContainerTransaction.Change.CHANGE_FORCE_NO_PIP) != 0) { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 600881ea955cd..be266c9f991e4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1904,10 +1904,10 @@ public class DisplayContentTests extends WindowTestsBase { testPlayer.start(); assertNotEquals(origRot, dc.getConfiguration().windowConfiguration.getRotation()); assertNotNull(testPlayer.mLastReady); - assertEquals(dc, DisplayRotation.getDisplayFromTransition(testPlayer.mLastTransit)); WindowContainerToken dcToken = dc.mRemoteToken.toWindowContainerToken(); assertNotEquals(testPlayer.mLastReady.getChange(dcToken).getEndRotation(), testPlayer.mLastReady.getChange(dcToken).getStartRotation()); + assertTrue(testPlayer.mLastTransit.applyDisplayChangeIfNeeded()); testPlayer.finish(); }