Loading core/java/android/content/pm/ActivityInfo.java +14 −0 Original line number Diff line number Diff line Loading @@ -1034,6 +1034,20 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { public static final long OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION = 254631730L; // buganizer id /** * This change id enables compat policy that ignores app requested orientation in * response to an app calling {@link android.app.Activity#setRequestedOrientation} more * than twice in one second if an activity is not letterboxed for fixed orientation. * See com.android.server.wm.LetterboxUiController#shouldIgnoreRequestedOrientation * for details. * @hide */ @ChangeId @Overridable @Disabled public static final long OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED = 273509367L; // buganizer id /** * This change id forces the packages it is applied to never have Display API sandboxing * applied for a letterbox or SCM activity. The Display APIs will continue to provide Loading services/core/java/com/android/server/wm/LetterboxUiController.java +84 −14 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FOR import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH; import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; 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_ORIENTATION_ONLY_FOR_CAMERA; Loading Loading @@ -129,6 +130,14 @@ final class LetterboxUiController { private static final float UNDEFINED_ASPECT_RATIO = 0f; // Minimum value of mSetOrientationRequestCounter before qualifying as orientation request loop @VisibleForTesting static final int MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP = 2; // Used to determine reset of mSetOrientationRequestCounter if next app requested // orientation is after timeout value @VisibleForTesting static final int SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS = 1000; private final Point mTmpPoint = new Point(); private final LetterboxConfiguration mLetterboxConfiguration; Loading Loading @@ -167,6 +176,8 @@ final class LetterboxUiController { // Corresponds to OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION private final boolean mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled; // Corresponds to OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED private final boolean mIsOverrideEnableCompatIgnoreOrientationRequestWhenLoopDetectedEnabled; // Corresponds to OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS private final boolean mIsOverrideEnableCompatFakeFocusEnabled; Loading @@ -191,12 +202,18 @@ final class LetterboxUiController { private float mInheritedMinAspectRatio = UNDEFINED_ASPECT_RATIO; private float mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO; // Updated when ActivityRecord#setRequestedOrientation is called private long mTimeMsLastSetOrientationRequest = 0; @Configuration.Orientation private int mInheritedOrientation = ORIENTATION_UNDEFINED; // The app compat state for the opaque activity if any private int mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN; // Counter for ActivityRecord#setRequestedOrientation private int mSetOrientationRequestCounter = 0; // The CompatDisplayInsets of the opaque activity beneath the translucent one. private ActivityRecord.CompatDisplayInsets mInheritedCompatDisplayInsets; Loading Loading @@ -292,6 +309,9 @@ final class LetterboxUiController { mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled = isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION); mIsOverrideEnableCompatIgnoreOrientationRequestWhenLoopDetectedEnabled = isCompatChangeEnabled( OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED); mIsOverrideEnableCompatFakeFocusEnabled = isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS); Loading Loading @@ -362,20 +382,20 @@ final class LetterboxUiController { * <li>Opt-in component property or per-app override are enabled * <li>Activity is relaunched after {@link android.app.Activity#setRequestedOrientation} * call from an app or camera compat force rotation treatment is active for the activity. * <li>Orientation request loop detected and is not letterboxed for fixed orientation * </ul> */ boolean shouldIgnoreRequestedOrientation(@ScreenOrientation int requestedOrientation) { if (!shouldEnableWithOverrideAndProperty( if (shouldEnableWithOverrideAndProperty( /* gatingCondition */ mLetterboxConfiguration ::isPolicyForIgnoringRequestedOrientationEnabled, mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled, mBooleanPropertyIgnoreRequestedOrientation)) { return false; } if (mIsRelauchingAfterRequestedOrientationChanged) { Slog.w(TAG, "Ignoring orientation update to " + screenOrientationToString(requestedOrientation) + " due to relaunching after setRequestedOrientation for " + mActivityRecord); + " due to relaunching after setRequestedOrientation for " + mActivityRecord); return true; } DisplayContent displayContent = mActivityRecord.mDisplayContent; Loading @@ -390,9 +410,59 @@ final class LetterboxUiController { + " due to camera compat treatment for " + mActivityRecord); return true; } } if (shouldIgnoreOrientationRequestLoop()) { Slog.w(TAG, "Ignoring orientation update to " + screenOrientationToString(requestedOrientation) + " as orientation request loop was detected for " + mActivityRecord); return true; } return false; } /** * Whether an app is calling {@link android.app.Activity#setRequestedOrientation} * in a loop and orientation request should be ignored. * * <p>This should only be called once in response to * {@link android.app.Activity#setRequestedOrientation}. See * {@link #shouldIgnoreRequestedOrientation} for more details. * * <p>This treatment is enabled when the following conditions are met: * <ul> * <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 * </ul> */ @VisibleForTesting boolean shouldIgnoreOrientationRequestLoop() { if (!mIsOverrideEnableCompatIgnoreOrientationRequestWhenLoopDetectedEnabled) { return false; } final long currTimeMs = System.currentTimeMillis(); if (currTimeMs - mTimeMsLastSetOrientationRequest < SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS) { mSetOrientationRequestCounter += 1; } else { // Resets app setOrientationRequest counter if timed out mSetOrientationRequestCounter = 0; } // Update time last called mTimeMsLastSetOrientationRequest = currTimeMs; return mSetOrientationRequestCounter >= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP && !mActivityRecord.isLetterboxedForFixedOrientationAndAspectRatio(); } @VisibleForTesting int getSetOrientationRequestCounter() { return mSetOrientationRequestCounter; } /** * Whether sending compat fake focus for split screen resumed activities is enabled. Needed * because some game engines wait to get focus before drawing the content of the app which isn't Loading services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java +66 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FOR import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH; import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; 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_ORIENTATION_ONLY_FOR_CAMERA; Loading @@ -46,6 +47,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.LetterboxUiController.MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; import static com.android.server.wm.LetterboxUiController.SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; Loading Loading @@ -184,6 +187,69 @@ public class LetterboxUiControllerTest extends WindowTestsBase { assertFalse(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED)); } @Test public void testShouldIgnoreOrientationRequestLoop_overrideDisabled_returnsFalse() { 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_isLetterboxed_returnsFalse() { 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, /* expectedCount */ i); } } @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_noLoop_returnsFalse() { doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); // No orientation request loop assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ 0); } @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_timeout_returnsFalse() throws InterruptedException { doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); for (int i = MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i > 0; i--) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ 0); Thread.sleep(SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS); } } @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_returnsTrue() { doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); for (int i = 0; i < MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ i); } assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ true, /* expectedCount */ MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP); } private void assertShouldIgnoreOrientationRequestLoop(boolean shouldIgnore, int expectedCount) { if (shouldIgnore) { assertTrue(mController.shouldIgnoreOrientationRequestLoop()); } else { assertFalse(mController.shouldIgnoreOrientationRequestLoop()); } assertEquals(expectedCount, mController.getSetOrientationRequestCounter()); } @Test @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH}) public void testShouldIgnoreRequestedOrientation_flagIsDisabled_returnsFalse() { Loading Loading
core/java/android/content/pm/ActivityInfo.java +14 −0 Original line number Diff line number Diff line Loading @@ -1034,6 +1034,20 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { public static final long OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION = 254631730L; // buganizer id /** * This change id enables compat policy that ignores app requested orientation in * response to an app calling {@link android.app.Activity#setRequestedOrientation} more * than twice in one second if an activity is not letterboxed for fixed orientation. * See com.android.server.wm.LetterboxUiController#shouldIgnoreRequestedOrientation * for details. * @hide */ @ChangeId @Overridable @Disabled public static final long OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED = 273509367L; // buganizer id /** * This change id forces the packages it is applied to never have Display API sandboxing * applied for a letterbox or SCM activity. The Display APIs will continue to provide Loading
services/core/java/com/android/server/wm/LetterboxUiController.java +84 −14 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FOR import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH; import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; 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_ORIENTATION_ONLY_FOR_CAMERA; Loading Loading @@ -129,6 +130,14 @@ final class LetterboxUiController { private static final float UNDEFINED_ASPECT_RATIO = 0f; // Minimum value of mSetOrientationRequestCounter before qualifying as orientation request loop @VisibleForTesting static final int MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP = 2; // Used to determine reset of mSetOrientationRequestCounter if next app requested // orientation is after timeout value @VisibleForTesting static final int SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS = 1000; private final Point mTmpPoint = new Point(); private final LetterboxConfiguration mLetterboxConfiguration; Loading Loading @@ -167,6 +176,8 @@ final class LetterboxUiController { // Corresponds to OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION private final boolean mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled; // Corresponds to OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED private final boolean mIsOverrideEnableCompatIgnoreOrientationRequestWhenLoopDetectedEnabled; // Corresponds to OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS private final boolean mIsOverrideEnableCompatFakeFocusEnabled; Loading @@ -191,12 +202,18 @@ final class LetterboxUiController { private float mInheritedMinAspectRatio = UNDEFINED_ASPECT_RATIO; private float mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO; // Updated when ActivityRecord#setRequestedOrientation is called private long mTimeMsLastSetOrientationRequest = 0; @Configuration.Orientation private int mInheritedOrientation = ORIENTATION_UNDEFINED; // The app compat state for the opaque activity if any private int mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN; // Counter for ActivityRecord#setRequestedOrientation private int mSetOrientationRequestCounter = 0; // The CompatDisplayInsets of the opaque activity beneath the translucent one. private ActivityRecord.CompatDisplayInsets mInheritedCompatDisplayInsets; Loading Loading @@ -292,6 +309,9 @@ final class LetterboxUiController { mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled = isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION); mIsOverrideEnableCompatIgnoreOrientationRequestWhenLoopDetectedEnabled = isCompatChangeEnabled( OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED); mIsOverrideEnableCompatFakeFocusEnabled = isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS); Loading Loading @@ -362,20 +382,20 @@ final class LetterboxUiController { * <li>Opt-in component property or per-app override are enabled * <li>Activity is relaunched after {@link android.app.Activity#setRequestedOrientation} * call from an app or camera compat force rotation treatment is active for the activity. * <li>Orientation request loop detected and is not letterboxed for fixed orientation * </ul> */ boolean shouldIgnoreRequestedOrientation(@ScreenOrientation int requestedOrientation) { if (!shouldEnableWithOverrideAndProperty( if (shouldEnableWithOverrideAndProperty( /* gatingCondition */ mLetterboxConfiguration ::isPolicyForIgnoringRequestedOrientationEnabled, mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled, mBooleanPropertyIgnoreRequestedOrientation)) { return false; } if (mIsRelauchingAfterRequestedOrientationChanged) { Slog.w(TAG, "Ignoring orientation update to " + screenOrientationToString(requestedOrientation) + " due to relaunching after setRequestedOrientation for " + mActivityRecord); + " due to relaunching after setRequestedOrientation for " + mActivityRecord); return true; } DisplayContent displayContent = mActivityRecord.mDisplayContent; Loading @@ -390,9 +410,59 @@ final class LetterboxUiController { + " due to camera compat treatment for " + mActivityRecord); return true; } } if (shouldIgnoreOrientationRequestLoop()) { Slog.w(TAG, "Ignoring orientation update to " + screenOrientationToString(requestedOrientation) + " as orientation request loop was detected for " + mActivityRecord); return true; } return false; } /** * Whether an app is calling {@link android.app.Activity#setRequestedOrientation} * in a loop and orientation request should be ignored. * * <p>This should only be called once in response to * {@link android.app.Activity#setRequestedOrientation}. See * {@link #shouldIgnoreRequestedOrientation} for more details. * * <p>This treatment is enabled when the following conditions are met: * <ul> * <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 * </ul> */ @VisibleForTesting boolean shouldIgnoreOrientationRequestLoop() { if (!mIsOverrideEnableCompatIgnoreOrientationRequestWhenLoopDetectedEnabled) { return false; } final long currTimeMs = System.currentTimeMillis(); if (currTimeMs - mTimeMsLastSetOrientationRequest < SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS) { mSetOrientationRequestCounter += 1; } else { // Resets app setOrientationRequest counter if timed out mSetOrientationRequestCounter = 0; } // Update time last called mTimeMsLastSetOrientationRequest = currTimeMs; return mSetOrientationRequestCounter >= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP && !mActivityRecord.isLetterboxedForFixedOrientationAndAspectRatio(); } @VisibleForTesting int getSetOrientationRequestCounter() { return mSetOrientationRequestCounter; } /** * Whether sending compat fake focus for split screen resumed activities is enabled. Needed * because some game engines wait to get focus before drawing the content of the app which isn't Loading
services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java +66 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FOR import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH; import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; 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_ORIENTATION_ONLY_FOR_CAMERA; Loading @@ -46,6 +47,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.LetterboxUiController.MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; import static com.android.server.wm.LetterboxUiController.SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; Loading Loading @@ -184,6 +187,69 @@ public class LetterboxUiControllerTest extends WindowTestsBase { assertFalse(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED)); } @Test public void testShouldIgnoreOrientationRequestLoop_overrideDisabled_returnsFalse() { 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_isLetterboxed_returnsFalse() { 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, /* expectedCount */ i); } } @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_noLoop_returnsFalse() { doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); // No orientation request loop assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ 0); } @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_timeout_returnsFalse() throws InterruptedException { doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); for (int i = MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i > 0; i--) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ 0); Thread.sleep(SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS); } } @Test @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) public void testShouldIgnoreOrientationRequestLoop_returnsTrue() { doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); for (int i = 0; i < MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, /* expectedCount */ i); } assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ true, /* expectedCount */ MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP); } private void assertShouldIgnoreOrientationRequestLoop(boolean shouldIgnore, int expectedCount) { if (shouldIgnore) { assertTrue(mController.shouldIgnoreOrientationRequestLoop()); } else { assertFalse(mController.shouldIgnoreOrientationRequestLoop()); } assertEquals(expectedCount, mController.getSetOrientationRequestCounter()); } @Test @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH}) public void testShouldIgnoreRequestedOrientation_flagIsDisabled_returnsFalse() { Loading