diff options
| author | 2024-11-21 03:19:26 +0000 | |
|---|---|---|
| committer | 2024-11-21 03:19:26 +0000 | |
| commit | c79f21db074e0f4b20c6fa00db54dabcf09acd34 (patch) | |
| tree | 683795026ec4154cbd38f66925a7cba6ab94d5e5 | |
| parent | 5c9a7aec4dc4c7458fa02453f7664e59fc437fe9 (diff) | |
| parent | 4a44565881b174f094d37b7879e24efe79820a95 (diff) | |
Merge "Defer orientation for transient launch with immersive app policy" into main
3 files changed, 60 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 4cf1fb400fe7..df209ff4cf50 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -485,6 +485,9 @@ public class DisplayRotation { if (isDefaultDisplay) { updateOrientationListenerLw(); } + } else if (mCompatPolicyForImmersiveApps != null + && mCompatPolicyForImmersiveApps.deferOrientationUpdate()) { + return false; } return updateRotationUnchecked(forceUpdate); } diff --git a/services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java index 094434d07cfe..046ed614dc19 100644 --- a/services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java @@ -17,10 +17,13 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.content.res.Configuration.ORIENTATION_UNDEFINED; +import static com.android.server.policy.WindowManagerPolicy.USER_ROTATION_FREE; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.res.Configuration.Orientation; @@ -66,6 +69,37 @@ final class DisplayRotationImmersiveAppCompatPolicy { } /** + * Returns {@code true} if the orientation update should be skipped and it will update when + * transition is done. This is to keep the orientation which was preserved by + * {@link #isRotationLockEnforced} from being changed by a transient launch (i.e. recents). + */ + boolean deferOrientationUpdate() { + if (mDisplayRotation.getUserRotation() != USER_ROTATION_FREE + || mDisplayRotation.getLastOrientation() != SCREEN_ORIENTATION_UNSPECIFIED) { + return false; + } + final WindowOrientationListener orientationListener = + mDisplayRotation.getOrientationListener(); + if (orientationListener == null + || orientationListener.getProposedRotation() == mDisplayRotation.getRotation()) { + return false; + } + // The above conditions mean that isRotationLockEnforced might have taken effect: + // Auto-rotation is enabled and the proposed rotation is not applied. + // Then the update should defer until the transition idle to avoid disturbing animation. + if (!mDisplayContent.mTransitionController.hasTransientLaunch(mDisplayContent)) { + return false; + } + mDisplayContent.mTransitionController.mStateValidators.add(() -> { + if (!isRotationLockEnforcedLocked(orientationListener.getProposedRotation())) { + mDisplayContent.mWmService.updateRotation(false /* alwaysSendConfiguration */, + false /* forceRelayout */); + } + }); + return true; + } + + /** * Decides whether it is necessary to lock screen rotation, preventing auto rotation, based on * the top activity configuration and proposed screen rotation. * diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java index c8fc4822259e..63973345b5fb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java @@ -20,16 +20,19 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.content.res.Configuration.ORIENTATION_UNDEFINED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.verify; import android.platform.test.annotations.Presubmit; import android.view.Surface; @@ -54,6 +57,7 @@ public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBas private DisplayRotationImmersiveAppCompatPolicy mPolicy; + private DisplayRotation mMockDisplayRotation; private AppCompatConfiguration mMockAppCompatConfiguration; private ActivityRecord mMockActivityRecord; private Task mMockTask; @@ -98,6 +102,7 @@ public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBas when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_90)).thenReturn(true); when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_180)).thenReturn(false); when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_270)).thenReturn(true); + mMockDisplayRotation = mockDisplayRotation; return mockDisplayRotation; } @@ -196,6 +201,24 @@ public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBas } @Test + public void testDeferOrientationUpdate() { + assertFalse(mPolicy.deferOrientationUpdate()); + + doReturn(SCREEN_ORIENTATION_UNSPECIFIED).when(mMockDisplayRotation).getLastOrientation(); + final WindowOrientationListener orientationListener = mock(WindowOrientationListener.class); + doReturn(Surface.ROTATION_90).when(orientationListener).getProposedRotation(); + doReturn(orientationListener).when(mMockDisplayRotation).getOrientationListener(); + spyOn(mDisplayContent.mTransitionController); + doReturn(true).when(mDisplayContent.mTransitionController) + .hasTransientLaunch(mDisplayContent); + + assertTrue(mPolicy.deferOrientationUpdate()); + mDisplayContent.mTransitionController.mStateValidators.getFirst().run(); + + verify(mWm).updateRotation(false, false); + } + + @Test public void testRotationChoiceEnforcedOnly_nullTopRunningActivity_lockNotEnforced() { when(mDisplayContent.topRunningActivity()).thenReturn(null); |