diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 5b6df1cb754e6..1850462221012 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1184,6 +1184,37 @@ public interface WindowManager extends ViewManager { String PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE = "android.window.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE"; + /** + * Application level {@link android.content.pm.PackageManager.Property PackageManager + * .Property} for an app to inform the system that the app should be opted-out from the + * compatibility override that changes the min aspect ratio. + * + *

When this compat override is enabled the min aspect ratio given in the app's manifest can + * be overridden by the device manufacturer using their discretion to improve display + * compatibility unless the app's manifest value is higher. This treatment will also apply if + * no min aspect ratio value is provided in the manifest. These treatments can apply only in + * specific cases (e.g. device is in portrait) or each time the app is displayed on screen. + * + *

Setting this property to {@code false} informs the system that the app must be + * opted-out from the compatibility treatment even if the device manufacturer has opted the app + * into the treatment. + * + *

Not setting this property at all, or setting this property to {@code true} has no effect. + * + *

Syntax: + *

+     * <application>
+     *   <property
+     *     android:name="android.window.PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE"
+     *     android:value="true|false"/>
+     * </application>
+     * 
+ * @hide + */ + // TODO(b/279428317): Make this public API. + String PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE = + "android.window.PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE"; + /** * @hide */ diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 1e50f3d2b67ec..d93778e18748b 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -78,7 +78,6 @@ import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS; import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT; import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED; import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER; -import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM; @@ -9323,8 +9322,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (info.applicationInfo == null) { return info.getMinAspectRatio(); } - - if (!info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO)) { + if (!mLetterboxUiController.shouldOverrideMinAspectRatio()) { return info.getMinAspectRatio(); } diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index 5b39790d5fdad..b557b2e1410fc 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -25,6 +25,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION; import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO; import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA; import static android.content.pm.ActivityInfo.OVERRIDE_RESPECT_REQUESTED_ORIENTATION; import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR; @@ -49,6 +50,7 @@ import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; +import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS; import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION; @@ -185,10 +187,15 @@ final class LetterboxUiController { // when dealing with translucent activities. private final List mDestroyListeners = new ArrayList<>(); + // Corresponds to OVERRIDE_MIN_ASPECT_RATIO + private final boolean mIsOverrideMinAspectRatio; + @Nullable private final Boolean mBooleanPropertyAllowOrientationOverride; @Nullable private final Boolean mBooleanPropertyAllowDisplayOrientationOverride; + @Nullable + private final Boolean mBooleanPropertyAllowMinAspectRatioOverride; /* * WindowContainerListener responsible to make translucent activities inherit @@ -300,6 +307,10 @@ final class LetterboxUiController { readComponentProperty(packageManager, mActivityRecord.packageName, /* gatingCondition */ null, PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE); + mBooleanPropertyAllowMinAspectRatioOverride = + readComponentProperty(packageManager, mActivityRecord.packageName, + /* gatingCondition */ null, + PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE); mIsOverrideAnyOrientationEnabled = isCompatChangeEnabled(OVERRIDE_ANY_ORIENTATION); mIsOverrideToPortraitOrientationEnabled = @@ -330,6 +341,7 @@ final class LetterboxUiController { mIsOverrideEnableCompatFakeFocusEnabled = isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS); + mIsOverrideMinAspectRatio = isCompatChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO); } /** @@ -501,6 +513,25 @@ final class LetterboxUiController { mBooleanPropertyFakeFocus); } + /** + * Whether we should apply the min aspect ratio per-app override. When this override is applied + * the min aspect ratio given in the app's manifest will be overridden to the largest enabled + * aspect ratio treatment unless the app's manifest value is higher. The treatment will also + * apply if no value is provided in the manifest. + * + *

This method returns {@code true} when the following conditions are met: + *

+ */ + boolean shouldOverrideMinAspectRatio() { + return shouldEnableWithOptInOverrideAndOptOutProperty( + /* gatingCondition */ () -> true, + mIsOverrideMinAspectRatio, + mBooleanPropertyAllowMinAspectRatioOverride); + } + /** * Sets whether an activity is relaunching after the app has called {@link * android.app.Activity#setRequestedOrientation}. diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java index 03c93e9760593..81e0fb3c79961 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java @@ -24,6 +24,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION; import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO; import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA; import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR; import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT; @@ -40,6 +41,7 @@ import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; +import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS; import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION; @@ -860,6 +862,62 @@ public class LetterboxUiControllerTest extends WindowTestsBase { assertTrue(mController.shouldSendFakeFocus()); } + @Test + @EnableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO}) + public void testshouldOverrideMinAspectRatio_overrideEnabled_returnsTrue() { + mController = new LetterboxUiController(mWm, mActivity); + + assertTrue(mController.shouldOverrideMinAspectRatio()); + } + + @Test + @EnableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO}) + public void testshouldOverrideMinAspectRatio_propertyTrue_overrideEnabled_returnsTrue() + throws Exception { + mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ true); + mController = new LetterboxUiController(mWm, mActivity); + + assertTrue(mController.shouldOverrideMinAspectRatio()); + } + + @Test + @DisableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO}) + public void testshouldOverrideMinAspectRatio_propertyTrue_overrideDisabled_returnsFalse() + throws Exception { + mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ true); + mController = new LetterboxUiController(mWm, mActivity); + + assertFalse(mController.shouldOverrideMinAspectRatio()); + } + + @Test + @DisableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO}) + public void testshouldOverrideMinAspectRatio_overrideDisabled_returnsFalse() { + mController = new LetterboxUiController(mWm, mActivity); + + assertFalse(mController.shouldOverrideMinAspectRatio()); + } + + @Test + @EnableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO}) + public void testshouldOverrideMinAspectRatio_propertyFalse_overrideEnabled_returnsFalse() + throws Exception { + mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ false); + mController = new LetterboxUiController(mWm, mActivity); + + assertFalse(mController.shouldOverrideMinAspectRatio()); + } + + @Test + @DisableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO}) + public void testshouldOverrideMinAspectRatio_propertyFalse_noOverride_returnsFalse() + throws Exception { + mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ false); + mController = new LetterboxUiController(mWm, mActivity); + + assertFalse(mController.shouldOverrideMinAspectRatio()); + } + @Test public void testgetFixedOrientationLetterboxAspectRatio_splitScreenAspectEnabled() { doReturn(true).when(mActivity.mWmService.mLetterboxConfiguration)