diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 3d91921e3ab7b..8dd58506ef0b9 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -399,9 +399,8 @@ public class DisplayRotation { return false; } - final ScreenRotationAnimation screenRotationAnimation = - mDisplayContent.getRotationAnimation(); - if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { + if (mDisplayContent.inTransition() + && !mDisplayContent.mTransitionController.useShellTransitionsRotation()) { // Rotation updates cannot be performed while the previous rotation change animation // is still in progress. Skip this update. We will try updating again after the // animation is finished and the display is unfrozen. diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index bbc95a1dd70f6..584a40e047005 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -622,9 +622,11 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe throw new IllegalStateException("Can't finish a non-playing transition " + mSyncId); } + boolean hasParticipatedDisplay = false; // Commit all going-invisible containers for (int i = 0; i < mParticipants.size(); ++i) { - final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord(); + final WindowContainer participant = mParticipants.valueAt(i); + final ActivityRecord ar = participant.asActivityRecord(); if (ar != null) { boolean visibleAtTransitionEnd = mVisibleAtTransitionEndTokens.contains(ar); // We need both the expected visibility AND current requested-visibility to be @@ -656,8 +658,13 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // Legacy dispatch relies on this (for now). ar.mEnteringAnimation = visibleAtTransitionEnd; } + continue; } - final WallpaperWindowToken wt = mParticipants.valueAt(i).asWallpaperToken(); + if (participant.asDisplayContent() != null) { + hasParticipatedDisplay = true; + continue; + } + final WallpaperWindowToken wt = participant.asWallpaperToken(); if (wt != null) { final boolean visibleAtTransitionEnd = mVisibleAtTransitionEndTokens.contains(wt); if (!visibleAtTransitionEnd && !wt.isVisibleRequested()) { @@ -737,6 +744,12 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe mState = STATE_FINISHED; mController.mTransitionTracer.logState(this); + // Rotation change may be deferred while there is a display change transition, so check + // again in case there is a new pending change. + if (hasParticipatedDisplay && !mController.useShellTransitionsRotation()) { + mController.mAtm.mWindowManager.updateRotation(false /* alwaysSendConfiguration */, + false /* forceRelayout */); + } } void abort() { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index cbb68865587d6..1e79b0385d451 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -4290,7 +4290,9 @@ public class WindowManagerService extends IWindowManager.Stub // Even if alwaysSend, we are waiting for a transition or remote to provide // updated configuration, so we can't update configuration yet. if (!pendingRemoteDisplayChange) { - if (!rotationChanged || forceRelayout) { + // The layout-needed flag will be set if there is a rotation change, so + // only set it if the caller requests to force relayout. + if (forceRelayout) { displayContent.setLayoutNeeded(); layoutNeeded = true; } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 9fedfcef6e337..8b350f4d0ac79 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -2466,6 +2466,7 @@ public class ActivityRecordTests extends WindowTestsBase { activity.addWindow(appWindow); spyOn(appWindow); doNothing().when(appWindow).onStartFreezingScreen(); + doNothing().when(mWm).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt()); // Set initial orientation and update. performRotation(displayRotation, Surface.ROTATION_90); @@ -2474,8 +2475,6 @@ public class ActivityRecordTests extends WindowTestsBase { // Update the rotation to perform 180 degree rotation and check that resize was reported. performRotation(displayRotation, Surface.ROTATION_270); assertTrue(appWindow.mResizeReported); - - appWindow.removeImmediately(); } private void performRotation(DisplayRotation spiedRotation, int rotationToReport) { 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 d6b807fc223e3..600881ea955cd 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1820,19 +1820,18 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testRemoteRotation() { - DisplayContent dc = createNewDisplay(); - + final DisplayContent dc = mDisplayContent; final DisplayRotation dr = dc.getDisplayRotation(); - doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean()); + spyOn(dr); // Rotate 180 degree so the display doesn't have configuration change. This condition is // used for the later verification of stop-freezing (without setting mWaitingForConfig). doReturn((dr.getRotation() + 2) % 4).when(dr).rotationForOrientation(anyInt(), anyInt()); final boolean[] continued = new boolean[1]; - doAnswer( - invocation -> { - continued[0] = true; - return true; - }).when(dc).updateDisplayOverrideConfigurationLocked(); + doAnswer(invocation -> { + continued[0] = true; + mAtm.addWindowLayoutReasons(ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED); + return true; + }).when(dc).updateDisplayOverrideConfigurationLocked(); final boolean[] called = new boolean[1]; mWm.mDisplayChangeController = new IDisplayChangeWindowController.Stub() {