Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a428c2b0 authored by Automerger Merge Worker's avatar Automerger Merge Worker Committed by Android (Google) Code Review
Browse files

Merge "Merge "Prevent orientation request loop in override" into tm-qpr-dev...

Merge "Merge "Prevent orientation request loop in override" into tm-qpr-dev am: 84903feb am: 28d7f6a5" into udc-dev
parents 09cc79cf 9e70cef7
Loading
Loading
Loading
Loading
+14 −0
Original line number Original line Diff line number Diff line
@@ -1086,6 +1086,20 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
    public static final long OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION =
    public static final long OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION =
            254631730L; // buganizer id
            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
     * 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
     * applied for a letterbox or SCM activity. The Display APIs will continue to provide
+84 −14
Original line number Original line Diff line number Diff line
@@ -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_DISABLE_REFRESH;
import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
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_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_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA;
import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA;
@@ -130,6 +131,14 @@ final class LetterboxUiController {


    private static final float UNDEFINED_ASPECT_RATIO = 0f;
    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 Point mTmpPoint = new Point();


    private final LetterboxConfiguration mLetterboxConfiguration;
    private final LetterboxConfiguration mLetterboxConfiguration;
@@ -162,6 +171,8 @@ final class LetterboxUiController {


    // Corresponds to OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION
    // Corresponds to OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION
    private final boolean mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled;
    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
    // Corresponds to OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS
    private final boolean mIsOverrideEnableCompatFakeFocusEnabled;
    private final boolean mIsOverrideEnableCompatFakeFocusEnabled;
@@ -186,12 +197,18 @@ final class LetterboxUiController {
    private float mInheritedMinAspectRatio = UNDEFINED_ASPECT_RATIO;
    private float mInheritedMinAspectRatio = UNDEFINED_ASPECT_RATIO;
    private float mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO;
    private float mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO;


    // Updated when ActivityRecord#setRequestedOrientation is called
    private long mTimeMsLastSetOrientationRequest = 0;

    @Configuration.Orientation
    @Configuration.Orientation
    private int mInheritedOrientation = ORIENTATION_UNDEFINED;
    private int mInheritedOrientation = ORIENTATION_UNDEFINED;


    // The app compat state for the opaque activity if any
    // The app compat state for the opaque activity if any
    private int mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN;
    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.
    // The CompatDisplayInsets of the opaque activity beneath the translucent one.
    private ActivityRecord.CompatDisplayInsets mInheritedCompatDisplayInsets;
    private ActivityRecord.CompatDisplayInsets mInheritedCompatDisplayInsets;


@@ -284,6 +301,9 @@ final class LetterboxUiController {


        mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled =
        mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled =
                isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION);
                isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION);
        mIsOverrideEnableCompatIgnoreOrientationRequestWhenLoopDetectedEnabled =
                isCompatChangeEnabled(
                        OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED);


        mIsOverrideEnableCompatFakeFocusEnabled =
        mIsOverrideEnableCompatFakeFocusEnabled =
                isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS);
                isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS);
@@ -354,20 +374,20 @@ final class LetterboxUiController {
     *     <li>Opt-in component property or per-app override are enabled
     *     <li>Opt-in component property or per-app override are enabled
     *     <li>Activity is relaunched after {@link android.app.Activity#setRequestedOrientation}
     *     <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.
     *     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>
     * </ul>
     */
     */
    boolean shouldIgnoreRequestedOrientation(@ScreenOrientation int requestedOrientation) {
    boolean shouldIgnoreRequestedOrientation(@ScreenOrientation int requestedOrientation) {
        if (!shouldEnableWithOverrideAndProperty(
        if (shouldEnableWithOverrideAndProperty(
                /* gatingCondition */ mLetterboxConfiguration
                /* gatingCondition */ mLetterboxConfiguration
                        ::isPolicyForIgnoringRequestedOrientationEnabled,
                        ::isPolicyForIgnoringRequestedOrientationEnabled,
                mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled,
                mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled,
                mBooleanPropertyIgnoreRequestedOrientation)) {
                mBooleanPropertyIgnoreRequestedOrientation)) {
            return false;
        }
            if (mIsRelauchingAfterRequestedOrientationChanged) {
            if (mIsRelauchingAfterRequestedOrientationChanged) {
                Slog.w(TAG, "Ignoring orientation update to "
                Slog.w(TAG, "Ignoring orientation update to "
                        + screenOrientationToString(requestedOrientation)
                        + screenOrientationToString(requestedOrientation)
                    + " due to relaunching after setRequestedOrientation for " + mActivityRecord);
                        + " due to relaunching after setRequestedOrientation for "
                        + mActivityRecord);
                return true;
                return true;
            }
            }
            DisplayContent displayContent = mActivityRecord.mDisplayContent;
            DisplayContent displayContent = mActivityRecord.mDisplayContent;
@@ -382,9 +402,59 @@ final class LetterboxUiController {
                        + " due to camera compat treatment for " + mActivityRecord);
                        + " due to camera compat treatment for " + mActivityRecord);
                return true;
                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;
            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
     * 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
     * because some game engines wait to get focus before drawing the content of the app which isn't
+66 −0
Original line number Original line Diff line number Diff line
@@ -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_DISABLE_REFRESH;
import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
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_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_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA;
import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA;
@@ -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.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
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.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertFalse;
@@ -185,6 +188,69 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
        assertFalse(mController.shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED));
        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
    @Test
    @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH})
    @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH})
    public void testShouldIgnoreRequestedOrientation_flagIsDisabled_returnsFalse() {
    public void testShouldIgnoreRequestedOrientation_flagIsDisabled_returnsFalse() {