Loading core/java/android/view/WindowManager.java +36 −0 Original line number Diff line number Diff line Loading @@ -852,6 +852,42 @@ public interface WindowManager extends ViewManager { String PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION = "android.window.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION"; /** * Application level {@link android.content.pm.PackageManager.Property PackageManager.Property} * for an app to inform the system that the app can be opted-out from the compatibility * treatment that avoids {@link android.app.Activity#setRequestedOrientation} loops. The loop * can be trigerred by ignoreRequestedOrientation display setting enabled on the device or * by the landscape natural orientation of the device. * * <p>The system could ignore {@link android.app.Activity#setRequestedOrientation} * call from an app if both of the following conditions are true: * <ul> * <li>Activity has requested orientation more than 2 times within 1-second timer * <li>Activity is not letterboxed for fixed orientation * </ul> * * <p>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. * * <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_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED" * android:value="false"/> * </application> * </pre> * * @hide */ // TODO(b/274924641): Make this public API. String PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED = "android.window.PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED"; /** * Application level {@link android.content.pm.PackageManager.Property PackageManager * .Property} for an app to inform the system that it needs to be opted-out from the Loading services/core/java/com/android/server/wm/LetterboxUiController.java +15 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_V import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_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_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION; import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM; Loading Loading @@ -239,6 +240,9 @@ final class LetterboxUiController { @Nullable private final Boolean mBooleanPropertyIgnoreRequestedOrientation; @Nullable private final Boolean mBooleanPropertyIgnoreOrientationRequestWhenLoopDetected; @Nullable private final Boolean mBooleanPropertyFakeFocus; Loading @@ -260,6 +264,10 @@ final class LetterboxUiController { readComponentProperty(packageManager, mActivityRecord.packageName, mLetterboxConfiguration::isPolicyForIgnoringRequestedOrientationEnabled, PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION); mBooleanPropertyIgnoreOrientationRequestWhenLoopDetected = readComponentProperty(packageManager, mActivityRecord.packageName, mLetterboxConfiguration::isPolicyForIgnoringRequestedOrientationEnabled, PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED); mBooleanPropertyFakeFocus = readComponentProperty(packageManager, mActivityRecord.packageName, mLetterboxConfiguration::isCompatFakeFocusEnabled, Loading Loading @@ -432,6 +440,8 @@ final class LetterboxUiController { * * <p>This treatment is enabled when the following conditions are met: * <ul> * <li>Flag gating the treatment is enabled * <li>Opt-out component property isn't enabled * <li>Per-app override is enabled * <li>App has requested orientation more than 2 times within 1-second * timer and activity is not letterboxed for fixed orientation Loading @@ -439,7 +449,11 @@ final class LetterboxUiController { */ @VisibleForTesting boolean shouldIgnoreOrientationRequestLoop() { if (!mIsOverrideEnableCompatIgnoreOrientationRequestWhenLoopDetectedEnabled) { if (!shouldEnableWithOptInOverrideAndOptOutProperty( /* gatingCondition */ mLetterboxConfiguration ::isPolicyForIgnoringRequestedOrientationEnabled, mIsOverrideEnableCompatIgnoreOrientationRequestWhenLoopDetectedEnabled, mBooleanPropertyIgnoreOrientationRequestWhenLoopDetected)) { return false; } Loading services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java +34 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_V import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_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_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; Loading Loading @@ -189,7 +190,28 @@ public class LetterboxUiControllerTest extends WindowTestsBase { @Test public void testShouldIgnoreOrientationRequestLoop_overrideDisabled_returnsFalse() { doReturn(true).when(mLetterboxConfiguration) .isPolicyForIgnoringRequestedOrientationEnabled(); doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); // Request 3 times to simulate orientation request loop for (int i = 0; i <= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ 0); } } @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_propertyIsFalseAndOverride_returnsFalse() throws Exception { doReturn(true).when(mLetterboxConfiguration) .isPolicyForIgnoringRequestedOrientationEnabled(); mockThatProperty(PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED, /* value */ false); doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); mController = new LetterboxUiController(mWm, mActivity); // Request 3 times to simulate orientation request loop for (int i = 0; i <= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, Loading @@ -200,7 +222,10 @@ public class LetterboxUiControllerTest extends WindowTestsBase { @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_isLetterboxed_returnsFalse() { doReturn(true).when(mLetterboxConfiguration) .isPolicyForIgnoringRequestedOrientationEnabled(); doReturn(true).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); // Request 3 times to simulate orientation request loop for (int i = 0; i <= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, Loading @@ -211,7 +236,10 @@ public class LetterboxUiControllerTest extends WindowTestsBase { @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_noLoop_returnsFalse() { doReturn(true).when(mLetterboxConfiguration) .isPolicyForIgnoringRequestedOrientationEnabled(); doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); // No orientation request loop assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ 0); Loading @@ -221,7 +249,10 @@ public class LetterboxUiControllerTest extends WindowTestsBase { @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_timeout_returnsFalse() throws InterruptedException { doReturn(true).when(mLetterboxConfiguration) .isPolicyForIgnoringRequestedOrientationEnabled(); doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); for (int i = MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i > 0; i--) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ 0); Loading @@ -232,7 +263,10 @@ public class LetterboxUiControllerTest extends WindowTestsBase { @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_returnsTrue() { doReturn(true).when(mLetterboxConfiguration) .isPolicyForIgnoringRequestedOrientationEnabled(); doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); for (int i = 0; i < MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ i); Loading Loading
core/java/android/view/WindowManager.java +36 −0 Original line number Diff line number Diff line Loading @@ -852,6 +852,42 @@ public interface WindowManager extends ViewManager { String PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION = "android.window.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION"; /** * Application level {@link android.content.pm.PackageManager.Property PackageManager.Property} * for an app to inform the system that the app can be opted-out from the compatibility * treatment that avoids {@link android.app.Activity#setRequestedOrientation} loops. The loop * can be trigerred by ignoreRequestedOrientation display setting enabled on the device or * by the landscape natural orientation of the device. * * <p>The system could ignore {@link android.app.Activity#setRequestedOrientation} * call from an app if both of the following conditions are true: * <ul> * <li>Activity has requested orientation more than 2 times within 1-second timer * <li>Activity is not letterboxed for fixed orientation * </ul> * * <p>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. * * <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_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED" * android:value="false"/> * </application> * </pre> * * @hide */ // TODO(b/274924641): Make this public API. String PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED = "android.window.PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED"; /** * Application level {@link android.content.pm.PackageManager.Property PackageManager * .Property} for an app to inform the system that it needs to be opted-out from the Loading
services/core/java/com/android/server/wm/LetterboxUiController.java +15 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_V import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_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_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION; import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM; Loading Loading @@ -239,6 +240,9 @@ final class LetterboxUiController { @Nullable private final Boolean mBooleanPropertyIgnoreRequestedOrientation; @Nullable private final Boolean mBooleanPropertyIgnoreOrientationRequestWhenLoopDetected; @Nullable private final Boolean mBooleanPropertyFakeFocus; Loading @@ -260,6 +264,10 @@ final class LetterboxUiController { readComponentProperty(packageManager, mActivityRecord.packageName, mLetterboxConfiguration::isPolicyForIgnoringRequestedOrientationEnabled, PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION); mBooleanPropertyIgnoreOrientationRequestWhenLoopDetected = readComponentProperty(packageManager, mActivityRecord.packageName, mLetterboxConfiguration::isPolicyForIgnoringRequestedOrientationEnabled, PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED); mBooleanPropertyFakeFocus = readComponentProperty(packageManager, mActivityRecord.packageName, mLetterboxConfiguration::isCompatFakeFocusEnabled, Loading Loading @@ -432,6 +440,8 @@ final class LetterboxUiController { * * <p>This treatment is enabled when the following conditions are met: * <ul> * <li>Flag gating the treatment is enabled * <li>Opt-out component property isn't enabled * <li>Per-app override is enabled * <li>App has requested orientation more than 2 times within 1-second * timer and activity is not letterboxed for fixed orientation Loading @@ -439,7 +449,11 @@ final class LetterboxUiController { */ @VisibleForTesting boolean shouldIgnoreOrientationRequestLoop() { if (!mIsOverrideEnableCompatIgnoreOrientationRequestWhenLoopDetectedEnabled) { if (!shouldEnableWithOptInOverrideAndOptOutProperty( /* gatingCondition */ mLetterboxConfiguration ::isPolicyForIgnoringRequestedOrientationEnabled, mIsOverrideEnableCompatIgnoreOrientationRequestWhenLoopDetectedEnabled, mBooleanPropertyIgnoreOrientationRequestWhenLoopDetected)) { return false; } Loading
services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java +34 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_V import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_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_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; Loading Loading @@ -189,7 +190,28 @@ public class LetterboxUiControllerTest extends WindowTestsBase { @Test public void testShouldIgnoreOrientationRequestLoop_overrideDisabled_returnsFalse() { doReturn(true).when(mLetterboxConfiguration) .isPolicyForIgnoringRequestedOrientationEnabled(); doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); // Request 3 times to simulate orientation request loop for (int i = 0; i <= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ 0); } } @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_propertyIsFalseAndOverride_returnsFalse() throws Exception { doReturn(true).when(mLetterboxConfiguration) .isPolicyForIgnoringRequestedOrientationEnabled(); mockThatProperty(PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED, /* value */ false); doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); mController = new LetterboxUiController(mWm, mActivity); // Request 3 times to simulate orientation request loop for (int i = 0; i <= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, Loading @@ -200,7 +222,10 @@ public class LetterboxUiControllerTest extends WindowTestsBase { @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_isLetterboxed_returnsFalse() { doReturn(true).when(mLetterboxConfiguration) .isPolicyForIgnoringRequestedOrientationEnabled(); doReturn(true).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); // Request 3 times to simulate orientation request loop for (int i = 0; i <= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, Loading @@ -211,7 +236,10 @@ public class LetterboxUiControllerTest extends WindowTestsBase { @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_noLoop_returnsFalse() { doReturn(true).when(mLetterboxConfiguration) .isPolicyForIgnoringRequestedOrientationEnabled(); doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); // No orientation request loop assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ 0); Loading @@ -221,7 +249,10 @@ public class LetterboxUiControllerTest extends WindowTestsBase { @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_timeout_returnsFalse() throws InterruptedException { doReturn(true).when(mLetterboxConfiguration) .isPolicyForIgnoringRequestedOrientationEnabled(); doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); for (int i = MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i > 0; i--) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ 0); Loading @@ -232,7 +263,10 @@ public class LetterboxUiControllerTest extends WindowTestsBase { @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_returnsTrue() { doReturn(true).when(mLetterboxConfiguration) .isPolicyForIgnoringRequestedOrientationEnabled(); doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); for (int i = 0; i < MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ i); Loading