From 0047d16dd2972dc73059423dc3b245ca4a2d05a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6llner?= Date: Wed, 19 Jan 2022 14:11:20 +0100 Subject: [PATCH] Reset "allowAllRotations" when the physical display changed. Previously the config resource was read once and cached forever. There are different config resource values based on the screen dimensions, therefore we need to make sure that the value is reset when displays change. Test: DisplayRotationTests, DisplayWindowSettingsTest + Manually on device Bug: 203814571 Change-Id: I116d9922342ea4f1ca5858873a1d38c4c5d52161 --- .../android/server/wm/DisplayRotation.java | 15 ++++ .../server/wm/DisplayWindowSettings.java | 2 + .../server/wm/DisplayRotationTests.java | 75 +++++++++++++++++++ .../server/wm/DisplayWindowSettingsTests.java | 15 +++- 4 files changed, 105 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 8c8b33f344fd2..7e01e380eb553 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -1103,6 +1103,21 @@ public class DisplayRotation { return oldRotation != rotation; } + + /** + * Resets whether the screen can be rotated via the accelerometer in all 4 rotations as the + * default behavior. + * + * To be called if there is potential that the value changed. For example if the active display + * changed. + * + * At the moment it is called from + * {@link DisplayWindowSettings#applyRotationSettingsToDisplayLocked}. + */ + void resetAllowAllRotations() { + mAllowAllRotations = ALLOW_ALL_ROTATIONS_UNDEFINED; + } + /** * Given an orientation constant, returns the appropriate surface rotation, taking into account * sensors, docking mode, rotation lock, and other factors. diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java index 483c799c5afa6..70c769d608449 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java @@ -297,6 +297,8 @@ class DisplayWindowSettings { final boolean ignoreOrientationRequest = settings.mIgnoreOrientationRequest != null ? settings.mIgnoreOrientationRequest : false; dc.setIgnoreOrientationRequest(ignoreOrientationRequest); + + dc.getDisplayRotation().resetAllowAllRotations(); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java index 6342183ea28e0..25cff61c3b785 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT; import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_DISABLED; @@ -546,6 +547,80 @@ public class DisplayRotationTests { SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); } + @Test + public void testReturnsSensorRotation_180degrees_allRotationsAllowed() + throws Exception { + mBuilder.build(); + when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) + .thenReturn(true); + configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); + enableOrientationSensor(); + mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); + + assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation( + SCREEN_ORIENTATION_SENSOR, Surface.ROTATION_0)); + } + + @Test + public void testReturnLastRotation_sensor180_allRotationsNotAllowed() + throws Exception { + mBuilder.build(); + when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) + .thenReturn(false); + configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); + enableOrientationSensor(); + mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); + + assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation( + SCREEN_ORIENTATION_SENSOR, Surface.ROTATION_0)); + } + + @Test + public void testAllowRotationsIsCached() + throws Exception { + mBuilder.build(); + configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); + enableOrientationSensor(); + + // Rotate once to read the resource + when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) + .thenReturn(true); + mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); + mTarget.rotationForOrientation(SCREEN_ORIENTATION_SENSOR, Surface.ROTATION_0); + + // Change resource to disallow all rotations. + // Rotate again and 180 degrees rotation should still be returned even if "disallowed". + when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) + .thenReturn(false); + mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); + assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation( + SCREEN_ORIENTATION_SENSOR, Surface.ROTATION_0)); + } + + @Test + public void testResetAllowRotations() + throws Exception { + mBuilder.build(); + configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); + enableOrientationSensor(); + + // Rotate once to read the resource + when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) + .thenReturn(true); + mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); + mTarget.rotationForOrientation(SCREEN_ORIENTATION_SENSOR, Surface.ROTATION_0); + + // Change resource to disallow all rotations. + // Reset "allowAllRotations". + // Rotate again and 180 degrees rotation should not be allowed anymore. + when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) + .thenReturn(false); + mTarget.resetAllowAllRotations(); + mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); + assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation( + SCREEN_ORIENTATION_SENSOR, Surface.ROTATION_0)); + } + // ================================= // Tests for Policy based Rotation // ================================= diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java index 365e749df79fe..093be82c61284 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java @@ -20,10 +20,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT; import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_DISABLED; import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_ENABLED; +import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; +import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY; import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY; -import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; -import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; @@ -259,6 +259,17 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { assertFalse(mSecondaryDisplay.mDisplayScalingDisabled); } + @Test + public void testResetAllowAllRotations() { + final DisplayRotation displayRotation = mock(DisplayRotation.class); + spyOn(mPrimaryDisplay); + doReturn(displayRotation).when(mPrimaryDisplay).getDisplayRotation(); + + mDisplayWindowSettings.applyRotationSettingsToDisplayLocked(mPrimaryDisplay); + + verify(displayRotation).resetAllowAllRotations(); + } + @Test public void testDefaultToFreeUserRotation() { mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay);