Loading services/core/java/com/android/server/wm/DisplayRotation.java +3 −0 Original line number Diff line number Diff line Loading @@ -485,6 +485,9 @@ public class DisplayRotation { if (isDefaultDisplay) { updateOrientationListenerLw(); } } else if (mCompatPolicyForImmersiveApps != null && mCompatPolicyForImmersiveApps.deferOrientationUpdate()) { return false; } return updateRotationUnchecked(forceUpdate); } Loading services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java +34 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -65,6 +68,37 @@ final class DisplayRotationImmersiveAppCompatPolicy { mDisplayContent = displayContent; } /** * 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. Loading services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java +23 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -54,6 +57,7 @@ public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBas private DisplayRotationImmersiveAppCompatPolicy mPolicy; private DisplayRotation mMockDisplayRotation; private AppCompatConfiguration mMockAppCompatConfiguration; private ActivityRecord mMockActivityRecord; private Task mMockTask; Loading Loading @@ -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; } Loading Loading @@ -195,6 +200,24 @@ public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBas assertIsRotationLockEnforcedReturnsFalseForAllRotations(); } @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); Loading Loading
services/core/java/com/android/server/wm/DisplayRotation.java +3 −0 Original line number Diff line number Diff line Loading @@ -485,6 +485,9 @@ public class DisplayRotation { if (isDefaultDisplay) { updateOrientationListenerLw(); } } else if (mCompatPolicyForImmersiveApps != null && mCompatPolicyForImmersiveApps.deferOrientationUpdate()) { return false; } return updateRotationUnchecked(forceUpdate); } Loading
services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java +34 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -65,6 +68,37 @@ final class DisplayRotationImmersiveAppCompatPolicy { mDisplayContent = displayContent; } /** * 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. Loading
services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java +23 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -54,6 +57,7 @@ public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBas private DisplayRotationImmersiveAppCompatPolicy mPolicy; private DisplayRotation mMockDisplayRotation; private AppCompatConfiguration mMockAppCompatConfiguration; private ActivityRecord mMockActivityRecord; private Task mMockTask; Loading Loading @@ -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; } Loading Loading @@ -195,6 +200,24 @@ public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBas assertIsRotationLockEnforcedReturnsFalseForAllRotations(); } @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); Loading