diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 5ad0a516ed636..fc4c0f7660917 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4027,7 +4027,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } void finishRelaunching() { - mLetterboxUiController.setRelauchingAfterRequestedOrientationChanged(false); + mLetterboxUiController.setRelaunchingAfterRequestedOrientationChanged(false); mTaskSupervisor.getActivityMetricsLogger().notifyActivityRelaunched(this); if (mPendingRelaunchCount > 0) { @@ -9422,7 +9422,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mRelaunchReason = RELAUNCH_REASON_NONE; } if (isRequestedOrientationChanged) { - mLetterboxUiController.setRelauchingAfterRequestedOrientationChanged(true); + mLetterboxUiController.setRelaunchingAfterRequestedOrientationChanged(true); } if (mState == PAUSING) { // A little annoying: we are waiting for this activity to finish pausing. Let's not diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index 6572f56abe041..0a52c576a5110 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -242,7 +242,9 @@ final class LetterboxUiController { @Nullable private final Boolean mBooleanPropertyFakeFocus; - private boolean mIsRelauchingAfterRequestedOrientationChanged; + private boolean mIsRelaunchingAfterRequestedOrientationChanged; + + private boolean mLastShouldShowLetterboxUi; private boolean mDoubleTapEvent; @@ -395,7 +397,7 @@ final class LetterboxUiController { ::isPolicyForIgnoringRequestedOrientationEnabled, mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled, mBooleanPropertyIgnoreRequestedOrientation)) { - if (mIsRelauchingAfterRequestedOrientationChanged) { + if (mIsRelaunchingAfterRequestedOrientationChanged) { Slog.w(TAG, "Ignoring orientation update to " + screenOrientationToString(requestedOrientation) + " due to relaunching after setRequestedOrientation for " @@ -484,8 +486,8 @@ final class LetterboxUiController { * Sets whether an activity is relaunching after the app has called {@link * android.app.Activity#setRequestedOrientation}. */ - void setRelauchingAfterRequestedOrientationChanged(boolean isRelaunching) { - mIsRelauchingAfterRequestedOrientationChanged = isRelaunching; + void setRelaunchingAfterRequestedOrientationChanged(boolean isRelaunching) { + mIsRelaunchingAfterRequestedOrientationChanged = isRelaunching; } /** @@ -1162,12 +1164,28 @@ final class LetterboxUiController { @VisibleForTesting boolean shouldShowLetterboxUi(WindowState mainWindow) { - return (mActivityRecord.isInLetterboxAnimation() || isSurfaceVisible(mainWindow)) + if (mIsRelaunchingAfterRequestedOrientationChanged || !isSurfaceReadyToShow(mainWindow)) { + return mLastShouldShowLetterboxUi; + } + + final boolean shouldShowLetterboxUi = + (mActivityRecord.isInLetterboxAnimation() || isSurfaceVisible(mainWindow)) && mainWindow.areAppWindowBoundsLetterboxed() // Check for FLAG_SHOW_WALLPAPER explicitly instead of using // WindowContainer#showWallpaper because the later will return true when this // activity is using blurred wallpaper for letterbox background. && (mainWindow.getAttrs().flags & FLAG_SHOW_WALLPAPER) == 0; + + mLastShouldShowLetterboxUi = shouldShowLetterboxUi; + + return shouldShowLetterboxUi; + } + + @VisibleForTesting + boolean isSurfaceReadyToShow(WindowState mainWindow) { + return mainWindow.isDrawn() // Regular case + // Waiting for relayoutWindow to call preserveSurface + || mainWindow.isDragResizeChanged(); } @VisibleForTesting @@ -1303,6 +1321,10 @@ final class LetterboxUiController { return null; } + boolean getIsRelaunchingAfterRequestedOrientationChanged() { + return mIsRelaunchingAfterRequestedOrientationChanged; + } + private void adjustBoundsForTaskbar(final WindowState mainWindow, final Rect bounds) { // Rounded corners should be displayed above the taskbar. When taskbar is hidden, // an insets frame is equal to a navigation bar which shouldn't affect position of diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 4f3ac48d2ca33..2d21e710bca8e 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -5596,8 +5596,17 @@ class WindowState extends WindowContainer implements WindowManagerP if (surfaceInsetsChanged) { mLastSurfaceInsets.set(mAttrs.surfaceInsets); } - if (surfaceSizeChanged && mWinAnimator.getShown() && !canPlayMoveAnimation() - && okToDisplay() && mSyncState == SYNC_STATE_NONE) { + final boolean surfaceResizedWithoutMoveAnimation = surfaceSizeChanged + && mWinAnimator.getShown() && !canPlayMoveAnimation() && okToDisplay() + && mSyncState == SYNC_STATE_NONE; + final ActivityRecord activityRecord = getActivityRecord(); + // If this window belongs to an activity that is relaunching due to an orientation + // change then delay the position update until it has redrawn to avoid any flickers. + final boolean isLetterboxedAndRelaunching = activityRecord != null + && activityRecord.areBoundsLetterboxed() + && activityRecord.mLetterboxUiController + .getIsRelaunchingAfterRequestedOrientationChanged(); + if (surfaceResizedWithoutMoveAnimation || isLetterboxedAndRelaunching) { applyWithNextDraw(mSetSurfacePositionConsumer); } else { mSetSurfacePositionConsumer.accept(t); diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java index 8f31641c66f41..3dd7b73fe6f55 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java @@ -145,7 +145,7 @@ public class LetterboxUiControllerTest extends WindowTestsBase { mActivity = setUpActivityWithComponent(); mController = new LetterboxUiController(mWm, mActivity); prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch(); - mController.setRelauchingAfterRequestedOrientationChanged(false); + mController.setRelaunchingAfterRequestedOrientationChanged(false); spyOn(mDisplayContent.mDisplayRotationCompatPolicy); doReturn(true).when(mDisplayContent.mDisplayRotationCompatPolicy) @@ -864,7 +864,7 @@ public class LetterboxUiControllerTest extends WindowTestsBase { private void prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch() { doReturn(true).when(mLetterboxConfiguration) .isPolicyForIgnoringRequestedOrientationEnabled(); - mController.setRelauchingAfterRequestedOrientationChanged(true); + mController.setRelaunchingAfterRequestedOrientationChanged(true); } private ActivityRecord setUpActivityWithComponent() { diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index b5993e237db80..d93871e59b37f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -782,6 +782,8 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(window, mActivity.findMainWindow()); spyOn(mActivity.mLetterboxUiController); + doReturn(true).when(mActivity.mLetterboxUiController) + .isSurfaceReadyToShow(any()); doReturn(true).when(mActivity.mLetterboxUiController) .isSurfaceVisible(any());