summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Riddle Hsu <riddlehsu@google.com> 2024-11-21 03:19:26 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-11-21 03:19:26 +0000
commitc79f21db074e0f4b20c6fa00db54dabcf09acd34 (patch)
tree683795026ec4154cbd38f66925a7cba6ab94d5e5
parent5c9a7aec4dc4c7458fa02453f7664e59fc437fe9 (diff)
parent4a44565881b174f094d37b7879e24efe79820a95 (diff)
Merge "Defer orientation for transient launch with immersive app policy" into main
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java3
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java34
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java23
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);