From 1db71c40f379e0496abd2f215f9003f639be52fd Mon Sep 17 00:00:00 2001 From: Vali Calinescu Date: Mon, 20 Feb 2023 12:45:05 +0000 Subject: Skip Size Compat mode when orientation change comes from app Avoid going into size compat mode and showing a restart button when the orientation change request comes from the app Bug: 259651516 Fix: 256509413 Test: atest WmTests:SizeCompatTests#testAppRequestsOrientationChange_notInSizeCompat Test: atest WmTests:SizeCompatTests#testDisplayIgnoreOrientationRequest_orientationChangedToUnspecified Change-Id: Ide316f05d0ba1286ed2583bf8919d0ae94a2899f --- data/etc/services.core.protolog.json | 6 ++ .../java/com/android/server/wm/ActivityRecord.java | 65 ++++++++++++++++++---- .../android/server/wm/LetterboxConfiguration.java | 15 +++++ .../wm/LetterboxConfigurationDeviceConfig.java | 20 ++++++- .../com/android/server/wm/WindowContainer.java | 27 +++++++-- .../com/android/server/wm/ActivityRecordTests.java | 2 +- .../src/com/android/server/wm/SizeCompatTests.java | 29 ++++++++-- 7 files changed, 141 insertions(+), 23 deletions(-) diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 1cf819af7a24..3d7fb16bb846 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -1051,6 +1051,12 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/WindowContainer.java" }, + "-1104347731": { + "message": "Setting requested orientation %s for %s", + "level": "VERBOSE", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/ActivityRecord.java" + }, "-1103716954": { "message": "Not removing %s due to exit animation", "level": "VERBOSE", diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index c8f9db7f7e34..7df01a49a102 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -7727,27 +7727,38 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A /** * Returns the requested {@link Configuration.Orientation} for the current activity. + */ + @Configuration.Orientation + @Override + int getRequestedConfigurationOrientation(boolean forDisplay) { + return getRequestedConfigurationOrientation(forDisplay, getOverrideOrientation()); + } + + /** + * Returns the requested {@link Configuration.Orientation} for the requested + * {@link ActivityInfo.ScreenOrientation}. * - *

When The current orientation is set to {@link SCREEN_ORIENTATION_BEHIND} it returns the - * requested orientation for the activity below which is the first activity with an explicit + *

When the current screen orientation is set to {@link SCREEN_ORIENTATION_BEHIND} it returns + * the requested orientation for the activity below which is the first activity with an explicit * (different from {@link SCREEN_ORIENTATION_UNSET}) orientation which is not {@link * SCREEN_ORIENTATION_BEHIND}. */ @Configuration.Orientation - @Override - int getRequestedConfigurationOrientation(boolean forDisplay) { + int getRequestedConfigurationOrientation(boolean forDisplay, + @ActivityInfo.ScreenOrientation int requestedOrientation) { if (mLetterboxUiController.hasInheritedOrientation()) { final RootDisplayArea root = getRootDisplayArea(); if (forDisplay && root != null && root.isOrientationDifferentFromDisplay()) { - return ActivityInfo.reverseOrientation( + return reverseConfigurationOrientation( mLetterboxUiController.getInheritedOrientation()); } else { return mLetterboxUiController.getInheritedOrientation(); } } - if (task != null && getOverrideOrientation() == SCREEN_ORIENTATION_BEHIND) { + if (task != null && requestedOrientation == SCREEN_ORIENTATION_BEHIND) { // We use Task here because we want to be consistent with what happens in // multi-window mode where other tasks orientations are ignored. + android.util.Log.d("orientation", "We are here"); final ActivityRecord belowCandidate = task.getActivity( a -> a.canDefineOrientationForActivitiesAbove() /* callback */, this /* boundary */, false /* includeBoundary */, @@ -7756,7 +7767,23 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return belowCandidate.getRequestedConfigurationOrientation(forDisplay); } } - return super.getRequestedConfigurationOrientation(forDisplay); + return super.getRequestedConfigurationOrientation(forDisplay, requestedOrientation); + } + + /** + * Returns the reversed configuration orientation. + * @hide + */ + @Configuration.Orientation + public static int reverseConfigurationOrientation(@Configuration.Orientation int orientation) { + switch (orientation) { + case ORIENTATION_LANDSCAPE: + return ORIENTATION_PORTRAIT; + case ORIENTATION_PORTRAIT: + return ORIENTATION_LANDSCAPE; + default: + return orientation; + } } /** @@ -7802,6 +7829,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (mLetterboxUiController.shouldIgnoreRequestedOrientation(requestedOrientation)) { return; } + // This is necessary in order to avoid going into size compat mode when the orientation + // change request comes from the app + if (mWmService.mLetterboxConfiguration + .isSizeCompatModeDisabledAfterOrientationChangeFromApp() + && getRequestedConfigurationOrientation(false, requestedOrientation) + != getRequestedConfigurationOrientation(false /*forDisplay */)) { + // Do not change the requested configuration now, because this will be done when setting + // the orientation below with the new mCompatDisplayInsets + clearSizeCompatModeAttributes(); + } + ProtoLog.v(WM_DEBUG_ORIENTATION, + "Setting requested orientation %s for %s", + ActivityInfo.screenOrientationToString(requestedOrientation), this); setOrientation(requestedOrientation, this); // Push the new configuration to the requested app in case where it's not pushed, e.g. when @@ -8023,17 +8063,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mDisplayContent, this, mLetterboxBoundsForFixedOrientationAndAspectRatio); } - @VisibleForTesting - void clearSizeCompatMode() { - final float lastSizeCompatScale = mSizeCompatScale; + private void clearSizeCompatModeAttributes() { mInSizeCompatModeForBounds = false; mSizeCompatScale = 1f; mSizeCompatBounds = null; mCompatDisplayInsets = null; + } + + @VisibleForTesting + void clearSizeCompatMode() { + final float lastSizeCompatScale = mSizeCompatScale; + clearSizeCompatModeAttributes(); if (mSizeCompatScale != lastSizeCompatScale) { forAllWindows(WindowState::updateGlobalScale, false /* traverseTopToBottom */); } - // Clear config override in #updateCompatDisplayInsets(). final int activityType = getActivityType(); final Configuration overrideConfig = getRequestedOverrideConfiguration(); diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java index fa49a6ba6c2b..37cf5bc95a23 100644 --- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java +++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ALLOW_IGNORE_ORIENTATION_REQUEST; +import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP; import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_CAMERA_COMPAT_TREATMENT; import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_COMPAT_FAKE_FOCUS; import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY; @@ -314,6 +315,10 @@ final class LetterboxConfiguration { mDeviceConfig.updateFlagActiveStatus( /* isActive */ mTranslucentLetterboxingEnabled, /* key */ KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY); + mDeviceConfig.updateFlagActiveStatus( + /* isActive */ true, + /* key */ KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP); + mLetterboxConfigurationPersister = letterboxConfigurationPersister; mLetterboxConfigurationPersister.start(); } @@ -326,6 +331,16 @@ final class LetterboxConfiguration { return mDeviceConfig.getFlag(KEY_ALLOW_IGNORE_ORIENTATION_REQUEST); } + /** + * Whether size compat mode is disabled after an orientation change request comes from the app. + * This value is controlled via {@link android.provider.DeviceConfig}. + */ + // TODO(b/270356567) Clean up this flag + boolean isSizeCompatModeDisabledAfterOrientationChangeFromApp() { + return mDeviceConfig.getFlag( + KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP); + } + /** * Overrides the aspect ratio of letterbox for fixed orientation. If given value is <= {@link * #MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO}, both it and a value of {@link diff --git a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java index df3c8f0fdccc..1651af328b1f 100644 --- a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java +++ b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java @@ -20,7 +20,6 @@ import android.annotation.NonNull; import android.provider.DeviceConfig; import android.util.ArraySet; - import com.android.internal.annotations.VisibleForTesting; import java.util.Map; @@ -53,6 +52,11 @@ final class LetterboxConfigurationDeviceConfig private static final boolean DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY = true; + static final String KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP = + "disable_size_compat_mode_after_orientation_change_from_app"; + private static final boolean + DEFAULT_VALUE_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP = true; + @VisibleForTesting static final Map sKeyToDefaultValueMap = Map.of( KEY_ENABLE_CAMERA_COMPAT_TREATMENT, @@ -64,7 +68,9 @@ final class LetterboxConfigurationDeviceConfig KEY_ENABLE_COMPAT_FAKE_FOCUS, DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS, KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY, - DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY + DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY, + KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP, + DEFAULT_VALUE_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP ); // Whether camera compatibility treatment is enabled. @@ -93,6 +99,10 @@ final class LetterboxConfigurationDeviceConfig private boolean mIsTranslucentLetterboxingAllowed = DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY; + // Whether size compat mode is disabled after an orientation change request comes from the app + private boolean mIsSizeCompatModeDisabledAfterOrientationChangeFromApp = + DEFAULT_VALUE_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP; + // Set of active device configs that need to be updated in // DeviceConfig.OnPropertiesChangedListener#onPropertiesChanged. private final ArraySet mActiveDeviceConfigsSet = new ArraySet<>(); @@ -142,6 +152,8 @@ final class LetterboxConfigurationDeviceConfig return mIsCompatFakeFocusAllowed; case KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY: return mIsTranslucentLetterboxingAllowed; + case KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP: + return mIsSizeCompatModeDisabledAfterOrientationChangeFromApp; default: throw new AssertionError("Unexpected flag name: " + key); } @@ -169,6 +181,10 @@ final class LetterboxConfigurationDeviceConfig case KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY: mIsTranslucentLetterboxingAllowed = getDeviceConfig(key, defaultValue); break; + case KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP: + mIsSizeCompatModeDisabledAfterOrientationChangeFromApp = + getDeviceConfig(key, defaultValue); + break; default: throw new AssertionError("Unexpected flag name: " + key); } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index ce032442e4af..7ff92afc9d29 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -1436,7 +1436,7 @@ class WindowContainer extends ConfigurationContainer< * {@link Configuration#ORIENTATION_PORTRAIT}, * {@link Configuration#ORIENTATION_UNDEFINED}). */ - @ScreenOrientation + @Configuration.Orientation int getRequestedConfigurationOrientation() { return getRequestedConfigurationOrientation(false /* forDisplay */); } @@ -1454,9 +1454,28 @@ class WindowContainer extends ConfigurationContainer< * {@link Configuration#ORIENTATION_PORTRAIT}, * {@link Configuration#ORIENTATION_UNDEFINED}). */ - @ScreenOrientation + @Configuration.Orientation int getRequestedConfigurationOrientation(boolean forDisplay) { - int requestedOrientation = getOverrideOrientation(); + return getRequestedConfigurationOrientation(forDisplay, getOverrideOrientation()); + } + + /** + * Gets the configuration orientation by the requested screen orientation + * + * @param forDisplay whether it is the requested config orientation for display. + * If {@code true}, we may reverse the requested orientation if the root is + * different from the display, so that when the display rotates to the + * reversed orientation, the requested app will be in the requested + * orientation. + * @param requestedOrientation the screen orientation({@link ScreenOrientation}) that is + * requested + * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE}, + * {@link Configuration#ORIENTATION_PORTRAIT}, + * {@link Configuration#ORIENTATION_UNDEFINED}). + */ + @Configuration.Orientation + int getRequestedConfigurationOrientation(boolean forDisplay, + @ScreenOrientation int requestedOrientation) { final RootDisplayArea root = getRootDisplayArea(); if (forDisplay && root != null && root.isOrientationDifferentFromDisplay()) { // Reverse the requested orientation if the orientation of its root is different from @@ -1466,7 +1485,7 @@ class WindowContainer extends ConfigurationContainer< // (portrait). // When an app below the DAG is requesting landscape, it should actually request the // display to be portrait, so that the DAG and the app will be in landscape. - requestedOrientation = reverseOrientation(getOverrideOrientation()); + requestedOrientation = reverseOrientation(requestedOrientation); } if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index ea50179746d8..0300eb06c220 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -2377,7 +2377,7 @@ public class ActivityRecordTests extends WindowTestsBase { .setScreenOrientation(SCREEN_ORIENTATION_BEHIND) .build(); final int topOrientation = activityTop.getRequestedConfigurationOrientation(); - assertEquals(SCREEN_ORIENTATION_PORTRAIT, topOrientation); + assertEquals(ORIENTATION_PORTRAIT, topOrientation); } private void verifyProcessInfoUpdate(ActivityRecord activity, State state, 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 117805bf344d..d77b6ada268e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -381,7 +381,7 @@ public class SizeCompatTests extends WindowTestsBase { } @Test - public void testTranslucentActivitiesDontGoInSizeCompactMode() { + public void testTranslucentActivitiesDontGoInSizeCompatMode() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); setUpDisplaySizeWithApp(2800, 1400); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); @@ -2454,11 +2454,11 @@ public class SizeCompatTests extends WindowTestsBase { assertFalse(mActivity.inSizeCompatMode()); mActivity.setRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED); - - assertTrue(mActivity.inSizeCompatMode()); - // We should remember the original orientation. + // Activity is not in size compat mode because the orientation change request came from the + // app itself + assertFalse(mActivity.inSizeCompatMode()); assertEquals(mActivity.getResolvedOverrideConfiguration().orientation, - Configuration.ORIENTATION_PORTRAIT); + Configuration.ORIENTATION_UNDEFINED); } @Test @@ -3032,6 +3032,25 @@ public class SizeCompatTests extends WindowTestsBase { assertTrue(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled()); } + @Test + public void testAppRequestsOrientationChange_notInSizeCompat() { + setUpDisplaySizeWithApp(2200, 1800); + mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + + prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE); + + mActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT); + + // Activity is not in size compat mode because the orientation change request came from the + // app itself + assertFalse(mActivity.inSizeCompatMode()); + + rotateDisplay(mActivity.mDisplayContent, ROTATION_270); + // Activity should go into size compat mode now because the orientation change came from the + // system (device rotation) + assertTrue(mActivity.inSizeCompatMode()); + } + @Test public void testLetterboxDetailsForStatusBar_noLetterbox() { setUpDisplaySizeWithApp(2800, 1000); -- cgit v1.2.3-59-g8ed1b