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

Commit 08bc4ed3 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Do not force seamless rotation with animating rotated recents

The animating recents activity (e.g. home) is set as fixed-rotation-
launching-app to reduce extra enable/disable transform because it may
be the real top activity later (e.g. swipe to home or enter overview).
The actual state is only known when finishing the recents animation.
So during animating, it is not really the top activity that will change
the rotation of display.

If auto-rotate is disabled, there will have a rotation button when
device is rotated. And if the device is using gesture navigation, the
touch region of button may overlap with the navigation bar. Then when
pressing the button while device is in landscape, the recents activity
may also be triggered with fixed rotation in portrait, that causes
the rotation type is forced to be seamless. But the actual foreground
app is not rotated and does not declare to use seamless, therefore
the screen looks flickering by updating configuration directly.

Fixes: 157208761
Test: DisplayContentTests#testRotateSeamlesslyWithFixedRotation

Change-Id: If512ad14420ed7956fe888a0ce9f5d5006eb43a8
parent 148fb0e8
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -1485,8 +1485,16 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        return true;
    }

    @Nullable ActivityRecord getFixedRotationLaunchingApp() {
        return mFixedRotationLaunchingApp;
    /** Returns {@code true} if the top activity is transformed with the new rotation of display. */
    boolean hasTopFixedRotationLaunchingApp() {
        return mFixedRotationLaunchingApp != null
                // Ignore animating recents because it hasn't really become the top.
                && mFixedRotationLaunchingApp != mFixedRotationTransitionListener.mAnimatingRecents;
    }

    @VisibleForTesting
    boolean isFixedRotationLaunchingApp(ActivityRecord r) {
        return mFixedRotationLaunchingApp == r;
    }

    @VisibleForTesting
+1 −1
Original line number Diff line number Diff line
@@ -582,7 +582,7 @@ public class DisplayRotation {
    boolean shouldRotateSeamlessly(int oldRotation, int newRotation, boolean forceUpdate) {
        // Display doesn't need to be frozen because application has been started in correct
        // rotation already, so the rest of the windows can use seamless rotation.
        if (mDisplayContent.getFixedRotationLaunchingApp() != null) {
        if (mDisplayContent.hasTopFixedRotationLaunchingApp()) {
            return true;
        }

+3 −3
Original line number Diff line number Diff line
@@ -1412,7 +1412,7 @@ public class ActivityRecordTests extends ActivityTestsBase {

        // The launching rotated app should not be cleared when waiting for remote rotation.
        display.continueUpdateOrientationForDiffOrienLaunchingApp();
        assertNotNull(display.getFixedRotationLaunchingApp());
        assertTrue(display.isFixedRotationLaunchingApp(mActivity));

        // Simulate the rotation has been updated to previous one, e.g. sensor updates before the
        // remote rotation is completed.
@@ -1441,7 +1441,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
        display.setFixedRotationLaunchingAppUnchecked(mActivity);
        display.sendNewConfiguration();

        assertNull(display.getFixedRotationLaunchingApp());
        assertFalse(display.hasTopFixedRotationLaunchingApp());
        assertFalse(mActivity.hasFixedRotationTransform());
    }

@@ -1497,7 +1497,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
        // rotation should be applied when creating snapshot surface if the display rotation may be
        // changed according to the activity orientation.
        assertTrue(mActivity.hasFixedRotationTransform());
        assertEquals(mActivity, mActivity.mDisplayContent.getFixedRotationLaunchingApp());
        assertTrue(mActivity.mDisplayContent.isFixedRotationLaunchingApp(mActivity));
    }

    /**
+18 −0
Original line number Diff line number Diff line
@@ -1147,6 +1147,24 @@ public class DisplayContentTests extends WindowTestsBase {
        assertNull(mDisplayContent.getFixedRotationAnimationController());
    }

    @Test
    public void testRotateSeamlesslyWithFixedRotation() {
        final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
        final ActivityRecord app = mAppWindow.mActivityRecord;
        mDisplayContent.setFixedRotationLaunchingAppUnchecked(app);
        mAppWindow.mAttrs.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;

        // Use seamless rotation if the top app is rotated.
        assertTrue(displayRotation.shouldRotateSeamlessly(ROTATION_0 /* oldRotation */,
                ROTATION_90 /* newRotation */, false /* forceUpdate */));

        mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(app);

        // Use normal rotation because animating recents is an intermediate state.
        assertFalse(displayRotation.shouldRotateSeamlessly(ROTATION_0 /* oldRotation */,
                ROTATION_90 /* newRotation */, false /* forceUpdate */));
    }

    @Test
    public void testRemoteRotation() {
        DisplayContent dc = createNewDisplay();
+5 −5
Original line number Diff line number Diff line
@@ -343,7 +343,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {

        initializeRecentsAnimationController(mController, homeActivity);

        assertEquals(homeActivity, mDefaultDisplay.getFixedRotationLaunchingApp());
        assertTrue(mDefaultDisplay.isFixedRotationLaunchingApp(homeActivity));

        // Check that the home app is in portrait
        assertEquals(Configuration.ORIENTATION_PORTRAIT,
@@ -353,7 +353,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
        // top rotated record should be cleared.
        mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
        assertFalse(homeActivity.hasFixedRotationTransform());
        assertNull(mDefaultDisplay.getFixedRotationLaunchingApp());
        assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp());
    }

    @Test
@@ -367,7 +367,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
                (mDefaultDisplay.getRotation() + 1) % 4);

        assertTrue(activity.hasFixedRotationTransform());
        assertEquals(activity, mDefaultDisplay.getFixedRotationLaunchingApp());
        assertTrue(mDefaultDisplay.isFixedRotationLaunchingApp(activity));

        // Before the transition is done, the recents animation is triggered.
        initializeRecentsAnimationController(mController, homeActivity);
@@ -377,7 +377,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
        mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
        // The rotation transform should be cleared after updating orientation with display.
        assertFalse(activity.hasFixedRotationTransform());
        assertNull(mDefaultDisplay.getFixedRotationLaunchingApp());
        assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp());
    }

    @Test
@@ -436,7 +436,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
        // The transform state should keep because we expect to listen the signal from the
        // transition executed by moving the task to front.
        assertTrue(homeActivity.hasFixedRotationTransform());
        assertEquals(homeActivity, mDefaultDisplay.getFixedRotationLaunchingApp());
        assertTrue(mDefaultDisplay.isFixedRotationLaunchingApp(homeActivity));

        mDefaultDisplay.mFixedRotationTransitionListener.onAppTransitionFinishedLocked(
                homeActivity.token);