diff options
3 files changed, 225 insertions, 11 deletions
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 65677cd7c3fd..c57628624007 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -913,7 +913,6 @@ public interface WindowManager extends ViewManager { * </application> * </pre> */ - // TODO(b/263984287): Add CTS tests. String PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION = "android.window.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION"; @@ -983,7 +982,6 @@ public interface WindowManager extends ViewManager { * </application> * </pre> */ - // TODO(b/263984287): Make this public API. String PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS = "android.window.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS"; @@ -1018,7 +1016,6 @@ public interface WindowManager extends ViewManager { * </application> * </pre> */ - // TODO(b/263984287): Add CTS tests. String PROPERTY_COMPAT_ENABLE_FAKE_FOCUS = "android.window.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS"; /** @@ -1056,7 +1053,6 @@ public interface WindowManager extends ViewManager { * </application> * </pre> */ - // TODO(b/263984287): Add CTS tests. String PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION = "android.window.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION"; @@ -1102,7 +1098,6 @@ public interface WindowManager extends ViewManager { * </application> * </pre> */ - // TODO(b/263984287): Add CTS tests. String PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH = "android.window.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH"; @@ -1151,7 +1146,6 @@ public interface WindowManager extends ViewManager { * </application> * </pre> */ - // TODO(b/263984287): Add CTS tests. String PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE = "android.window.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE"; @@ -1189,7 +1183,6 @@ public interface WindowManager extends ViewManager { * </application> * </pre> */ - // TODO(b/263984287): Add CTS tests. String PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE = "android.window.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE"; @@ -1233,7 +1226,6 @@ public interface WindowManager extends ViewManager { * </application> * </pre> */ - // TODO(b/263984287): Add CTS tests. String PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE = "android.window.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE"; @@ -1300,6 +1292,102 @@ public interface WindowManager extends ViewManager { "android.window.PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES"; /** + * Application level + * {@link android.content.pm.PackageManager.Property PackageManager.Property} + * tag that (when set to false) informs the system the app has opted out of the + * user-facing aspect ratio compatibility override. + * + * <p>The compatibility override enables device users to set the app's aspect + * ratio or force the app to fill the display regardless of the aspect + * ratio or orientation specified in the app manifest. + * + * <p>The aspect ratio compatibility override is exposed to users in device + * settings. A menu in device settings lists all apps that don't opt out of + * the compatibility override. Users select apps from the menu and set the + * app aspect ratio on a per-app basis. Typically, the menu is available + * only on large screen devices. + * + * <p>When users apply the aspect ratio override, the minimum aspect ratio + * specified in the app manifest is overridden. If users choose a + * full-screen aspect ratio, the orientation of the activity is forced to + * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_USER}; + * see {@link #PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE} to + * disable the full-screen option only. + * + * <p>The user override is intended to improve the app experience on devices + * that have the ignore orientation request display setting enabled by OEMs + * (enables compatibility mode for fixed orientation on Android 12 (API + * level 31) or higher; see + * <a href="https://developer.android.com/guide/topics/large-screens/large-screen-app-compatibility"> + * Large screen app compatibility</a> + * for more details). + * + * <p>To opt out of the user aspect ratio compatibility override, add this property + * to your app manifest and set the value to {@code false}. Your app will be excluded + * from the list of apps in device settings, and users will not be able to override + * the app's aspect ratio. + * + * <p>Not setting this property at all, or setting this property to {@code true} has no effect. + * + * <p><b>Syntax:</b> + * <pre> + * <application> + * <property + * android:name="android.window.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE" + * android:value="false"/> + * </application> + * </pre> + * @hide + */ + // TODO(b/294227289): Make this public API + String PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE = + "android.window.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"; + + /** + * Application level + * {@link android.content.pm.PackageManager.Property PackageManager.Property} + * tag that (when set to false) informs the system the app has opted out of the + * full-screen option of the aspect ratio compatibility override. (For + * background information about the aspect ratio compatibility override, see + * {@link #PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE}.) + * + * <p>When users apply the aspect ratio compatibility override, the orientation + * of the activity is forced to {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_USER}. + * + * <p>The user override is intended to improve the app experience on devices + * that have the ignore orientation request display setting enabled by OEMs + * (enables compatibility mode for fixed orientation on Android 12 (API + * level 31) or higher; see + * <a href="https://developer.android.com/guide/topics/large-screens/large-screen-app-compatibility"> + * Large screen app compatibility</a> + * for more details). + * + * <p>To opt out of the full-screen option of the user aspect ratio compatibility + * override, add this property to your app manifest and set the value to {@code false}. + * Your app will have full-screen option removed from the list of user aspect ratio + * override options in device settings, and users will not be able to apply + * full-screen override to your app. + * + * <p><b>Note:</b> If {@link #PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE} is + * {@code false}, this property has no effect. + * + * <p>Not setting this property at all, or setting this property to {@code true} has no effect. + * + * <p><b>Syntax:</b> + * <pre> + * <application> + * <property + * android:name="android.window.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE" + * android:value="false"/> + * </application> + * </pre> + * @hide + */ + // TODO(b/294227289): Make this public API + String PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE = + "android.window.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE"; + + /** * @hide */ public static final String PARCEL_KEY_SHORTCUTS_ARRAY = "shortcuts_array"; diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index 7d3c87a7556b..ba242ecd0ec3 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -63,6 +63,8 @@ import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTAT 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_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES; +import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE; +import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS; import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION; @@ -215,6 +217,11 @@ final class LetterboxUiController { @Nullable private final Boolean mBooleanPropertyAllowForceResizeOverride; + @Nullable + private final Boolean mBooleanPropertyAllowUserAspectRatioOverride; + @Nullable + private final Boolean mBooleanPropertyAllowUserAspectRatioFullscreenOverride; + /* * WindowContainerListener responsible to make translucent activities inherit * constraints from the first opaque activity beneath them. It's null for not @@ -335,6 +342,15 @@ final class LetterboxUiController { /* gatingCondition */ null, PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES); + mBooleanPropertyAllowUserAspectRatioOverride = + readComponentProperty(packageManager, mActivityRecord.packageName, + () -> mLetterboxConfiguration.isUserAppAspectRatioSettingsEnabled(), + PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE); + mBooleanPropertyAllowUserAspectRatioFullscreenOverride = + readComponentProperty(packageManager, mActivityRecord.packageName, + () -> mLetterboxConfiguration.isUserAppAspectRatioFullscreenEnabled(), + PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE); + mIsOverrideAnyOrientationEnabled = isCompatChangeEnabled(OVERRIDE_ANY_ORIENTATION); mIsOverrideToPortraitOrientationEnabled = isCompatChangeEnabled(OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT); @@ -1109,7 +1125,8 @@ final class LetterboxUiController { } boolean shouldApplyUserMinAspectRatioOverride() { - if (!mLetterboxConfiguration.isUserAppAspectRatioSettingsEnabled() + if (FALSE.equals(mBooleanPropertyAllowUserAspectRatioOverride) + || !mLetterboxConfiguration.isUserAppAspectRatioSettingsEnabled() || mActivityRecord.mDisplayContent == null || !mActivityRecord.mDisplayContent.getIgnoreOrientationRequest()) { return false; @@ -1122,7 +1139,9 @@ final class LetterboxUiController { } boolean shouldApplyUserFullscreenOverride() { - if (!mLetterboxConfiguration.isUserAppAspectRatioFullscreenEnabled() + if (FALSE.equals(mBooleanPropertyAllowUserAspectRatioOverride) + || FALSE.equals(mBooleanPropertyAllowUserAspectRatioFullscreenOverride) + || !mLetterboxConfiguration.isUserAppAspectRatioFullscreenEnabled() || mActivityRecord.mDisplayContent == null || !mActivityRecord.mDisplayContent.getIgnoreOrientationRequest()) { return false; @@ -1151,7 +1170,8 @@ final class LetterboxUiController { } } - private int getUserMinAspectRatioOverrideCode() { + @VisibleForTesting + int getUserMinAspectRatioOverrideCode() { try { return mActivityRecord.mAtmService.getPackageManager() .getUserMinAspectRatio(mActivityRecord.packageName, mActivityRecord.mUserId); 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 72ab18dca02f..2ad9fa0e5b13 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java @@ -37,6 +37,8 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_3_2; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER; @@ -48,6 +50,8 @@ import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTAT 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_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES; +import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE; +import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS; import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION; @@ -807,6 +811,108 @@ public class LetterboxUiControllerTest extends WindowTestsBase { /* candidate */ SCREEN_ORIENTATION_PORTRAIT), SCREEN_ORIENTATION_PORTRAIT); } + // shouldApplyUser...Override + @Test + public void testShouldApplyUserFullscreenOverride_trueProperty_returnsFalse() throws Exception { + mockThatProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE, + /* value */ true); + + mController = new LetterboxUiController(mWm, mActivity); + doReturn(false).when(mLetterboxConfiguration).isUserAppAspectRatioFullscreenEnabled(); + + assertFalse(mController.shouldApplyUserFullscreenOverride()); + } + + @Test + public void testShouldApplyUserFullscreenOverride_falseFullscreenProperty_returnsFalse() + throws Exception { + prepareActivityThatShouldApplyUserFullscreenOverride(); + mockThatProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE, + /* value */ false); + + mController = new LetterboxUiController(mWm, mActivity); + + assertFalse(mController.shouldApplyUserFullscreenOverride()); + } + + @Test + public void testShouldApplyUserFullscreenOverride_falseSettingsProperty_returnsFalse() + throws Exception { + prepareActivityThatShouldApplyUserFullscreenOverride(); + mockThatProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, /* value */ false); + + mController = new LetterboxUiController(mWm, mActivity); + + assertFalse(mController.shouldApplyUserFullscreenOverride()); + } + + @Test + public void testShouldApplyUserFullscreenOverride_disabledIgnoreOrientationRequest() { + prepareActivityThatShouldApplyUserFullscreenOverride(); + mDisplayContent.setIgnoreOrientationRequest(false); + + assertFalse(mController.shouldApplyUserFullscreenOverride()); + } + + @Test + public void testShouldApplyUserFullscreenOverride_returnsTrue() { + prepareActivityThatShouldApplyUserFullscreenOverride(); + + assertTrue(mController.shouldApplyUserFullscreenOverride()); + } + + @Test + public void testShouldApplyUserMinAspectRatioOverride_falseProperty_returnsFalse() + throws Exception { + prepareActivityThatShouldApplyUserMinAspectRatioOverride(); + mockThatProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, /* value */ false); + + mController = new LetterboxUiController(mWm, mActivity); + + assertFalse(mController.shouldApplyUserMinAspectRatioOverride()); + } + + @Test + public void testShouldApplyUserMinAspectRatioOverride_trueProperty_returnsFalse() + throws Exception { + doReturn(false).when(mLetterboxConfiguration).isUserAppAspectRatioSettingsEnabled(); + mockThatProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, /* value */ true); + + mController = new LetterboxUiController(mWm, mActivity); + + assertFalse(mController.shouldApplyUserMinAspectRatioOverride()); + } + + @Test + public void testShouldApplyUserMinAspectRatioOverride_disabledIgnoreOrientationRequest() { + prepareActivityThatShouldApplyUserMinAspectRatioOverride(); + mDisplayContent.setIgnoreOrientationRequest(false); + + assertFalse(mController.shouldApplyUserMinAspectRatioOverride()); + } + + @Test + public void testShouldApplyUserMinAspectRatioOverride_returnsTrue() { + prepareActivityThatShouldApplyUserMinAspectRatioOverride(); + + assertTrue(mController.shouldApplyUserMinAspectRatioOverride()); + } + + private void prepareActivityThatShouldApplyUserMinAspectRatioOverride() { + spyOn(mController); + doReturn(true).when(mLetterboxConfiguration).isUserAppAspectRatioSettingsEnabled(); + mDisplayContent.setIgnoreOrientationRequest(true); + doReturn(USER_MIN_ASPECT_RATIO_3_2).when(mController).getUserMinAspectRatioOverrideCode(); + } + + private void prepareActivityThatShouldApplyUserFullscreenOverride() { + spyOn(mController); + doReturn(true).when(mLetterboxConfiguration).isUserAppAspectRatioFullscreenEnabled(); + mDisplayContent.setIgnoreOrientationRequest(true); + doReturn(USER_MIN_ASPECT_RATIO_FULLSCREEN).when(mController) + .getUserMinAspectRatioOverrideCode(); + } + // shouldUseDisplayLandscapeNaturalOrientation @Test |