diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 802683a67f80c..39eda044a5b34 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -2322,7 +2322,9 @@ final class ActivityRecord extends ConfigurationContainer { return; } - if (configChanges == 0 && mAppWindowToken.okToDisplay()) { + // Window configuration changes only effect windows, so don't require a screen freeze. + int freezableConfigChanges = configChanges & ~(CONFIG_WINDOW_CONFIGURATION); + if (freezableConfigChanges == 0 && mAppWindowToken.okToDisplay()) { if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + appToken); return; } diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 6499497014192..fd90f0339e632 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -509,6 +509,10 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree final DisplayContent displayContent = getDisplayContent(); displayContent.mOpeningApps.remove(this); displayContent.mClosingApps.remove(this); + if (isInChangeTransition()) { + clearChangeLeash(getPendingTransaction(), true /* cancel */); + } + displayContent.mChangingApps.remove(this); waitingToShow = false; hiddenRequested = !visible; mDeferHidingClient = deferHidingClient; @@ -1310,7 +1314,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree void onDisplayChanged(DisplayContent dc) { DisplayContent prevDc = mDisplayContent; super.onDisplayChanged(dc); - if (prevDc == null) { + if (prevDc == null || prevDc == mDisplayContent) { return; } if (prevDc.mChangingApps.contains(this)) { @@ -1333,7 +1337,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } } - if (prevDc != mDisplayContent && mLetterbox != null) { + if (mLetterbox != null) { mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId()); } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index eac7716396887..0fbf956fcfa19 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -6828,9 +6828,26 @@ public class WindowManagerService extends IWindowManager.Stub return; } + int lastWindowingMode = displayContent.getWindowingMode(); mDisplayWindowSettings.setWindowingModeLocked(displayContent, mode); reconfigureDisplayLocked(displayContent); + + if (lastWindowingMode != displayContent.getWindowingMode()) { + // reconfigure won't detect this change in isolation because the windowing mode is + // already set on the display, so fire off a new config now. + mH.removeMessages(H.SEND_NEW_CONFIGURATION); + + final long origId = Binder.clearCallingIdentity(); + try { + // direct call since lock is shared. + sendNewConfiguration(displayId); + } finally { + Binder.restoreCallingIdentity(origId); + } + // Now that all configurations are updated, execute pending transitions + displayContent.executeAppTransition(); + } } } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java index 777e4f4915b80..035568f489bee 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java @@ -158,4 +158,22 @@ public class AppChangeTransitionTests extends WindowTestsBase { waitUntilHandlersIdle(); mToken.removeImmediately(); } + + @Test + public void testCancelPendingChangeOnHide() { + // setup currently defaults to no snapshot. + setUpOnDisplay(mDisplayContent); + + mTask.setWindowingMode(WINDOWING_MODE_FREEFORM); + assertEquals(1, mDisplayContent.mChangingApps.size()); + assertTrue(mToken.isInChangeTransition()); + + // Changing visibility should cancel the change transition and become closing + mToken.setVisibility(false, false); + assertEquals(0, mDisplayContent.mChangingApps.size()); + assertFalse(mToken.isInChangeTransition()); + + waitUntilHandlersIdle(); + mToken.removeImmediately(); + } }