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

Commit cbc5d272 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Polish fixed rotated recents animation

For the cases that move recents or home to top, the transformed
state is kept until the transition of task-to-front is done.

This fixes the flickering when switching between recents and the
activity that supported PiP. Also eliminated an additional toggle
of fixed rotation transform from finishing recents animation.

Fixes: 154588225
Test: atest RecentsAnimationControllerTest

Change-Id: I92c6dfac1d030f76f62a10bd0596f935adffb63c
parent d4957437
Loading
Loading
Loading
Loading
+56 −4
Original line number Diff line number Diff line
@@ -494,6 +494,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
     * The launching activity which is using fixed rotation transformation.
     *
     * @see #handleTopActivityLaunchingInDifferentOrientation
     * @see #setFixedRotationLaunchingApp
     * @see DisplayRotation#shouldRotateSeamlessly
     */
    ActivityRecord mFixedRotationLaunchingApp;
@@ -1451,6 +1452,15 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            return false;
        }

        setFixedRotationLaunchingApp(r, rotation);
        return true;
    }

    /**
     * Sets the provided record to {@link mFixedRotationLaunchingApp} if possible to apply fixed
     * rotation transform to it and indicate that the display may be rotated after it is launched.
     */
    void setFixedRotationLaunchingApp(@NonNull ActivityRecord r, @Surface.Rotation int rotation) {
        final WindowToken prevRotatedLaunchingApp = mFixedRotationLaunchingApp;
        if (prevRotatedLaunchingApp != null
                && prevRotatedLaunchingApp.getWindowConfiguration().getRotation() == rotation
@@ -1461,15 +1471,16 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            // the heavy operations. This also benefits that the states of multiple activities
            // are handled together.
            r.linkFixedRotationTransform(prevRotatedLaunchingApp);
            return true;
            return;
        }

        if (!r.hasFixedRotationTransform()) {
            startFixedRotationTransform(r, rotation);
        }
        mFixedRotationLaunchingApp = r;
        if (prevRotatedLaunchingApp != null) {
            prevRotatedLaunchingApp.finishFixedRotationTransform();
        }
        return true;
    }

    /**
@@ -5497,10 +5508,51 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    /** The entry for proceeding to handle {@link #mFixedRotationLaunchingApp}. */
    class FixedRotationTransitionListener extends WindowManagerInternal.AppTransitionListener {

        /**
         * The animating activity which shows the recents task list. It is set between
         * {@link RecentsAnimationController#initialize} and
         * {@link RecentsAnimationController#cancelAnimation}.
         */
        private ActivityRecord mAnimatingRecents;

        /**
         * If the recents activity has a fixed orientation which is different from the current top
         * activity, it will be rotated before being shown so we avoid a screen rotation animation
         * when showing the Recents view.
         */
        void onStartRecentsAnimation(@NonNull ActivityRecord r) {
            mAnimatingRecents = r;
            rotateInDifferentOrientationIfNeeded(r);
            if (r.hasFixedRotationTransform()) {
                // Set the record so we can recognize it to continue to update display orientation
                // if the recents activity becomes the top later.
                setFixedRotationLaunchingApp(r, r.getWindowConfiguration().getRotation());
            }
        }

        /**
         * If {@link #mAnimatingRecents} still has fixed rotation, it should be moved to top so we
         * don't clear {@link #mFixedRotationLaunchingApp} that will be handled by transition.
         */
        void onFinishRecentsAnimation() {
            final ActivityRecord animatingRecents = mAnimatingRecents;
            mAnimatingRecents = null;
            if (animatingRecents != null && animatingRecents == mFixedRotationLaunchingApp
                    && !animatingRecents.hasFixedRotationTransform()) {
                // The recents activity won't be the top, such as giving up the swipe up gesture
                // and return to the original top.
                mFixedRotationLaunchingApp = null;
            }
        }

        @Override
        public void onAppTransitionFinishedLocked(IBinder token) {
            final ActivityRecord r = getActivityRecord(token);
            if (r == null) {
            // Ignore the animating recents so the fixed rotation transform won't be switched twice
            // by finishing the recents animation and moving it to top. That also avoids flickering
            // due to wait for previous activity to be paused if it supports PiP that ignores the
            // effect of resume-while-pausing.
            if (r == null || r == mAnimatingRecents) {
                return;
            }
            if (mFixedRotationLaunchingApp != null
+5 −6
Original line number Diff line number Diff line
@@ -411,10 +411,7 @@ public class RecentsAnimationController implements DeathRecipient {

        mService.mWindowPlacerLocked.performSurfacePlacement();

        // If the target activity has a fixed orientation which is different from the current top
        // activity, it will be rotated before being shown so we avoid a screen rotation
        // animation when showing the Recents view.
        mDisplayContent.rotateInDifferentOrientationIfNeeded(mTargetActivityRecord);
        mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(targetActivity);

        // Notify that the animation has started
        if (mStatusBar != null) {
@@ -736,11 +733,13 @@ public class RecentsAnimationController implements DeathRecipient {
            if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) {
                mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(
                        mTargetActivityRecord.token);
            }
            if (mTargetActivityRecord.hasFixedRotationTransform()) {
            } else {
                // The target activity will be moved to original position (non-top). Since it won't
                // affect display orientation, just finish the transform.
                mTargetActivityRecord.finishFixedRotationTransform();
            }
        }
        mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation();

        // Notify that the animation has ended
        if (mStatusBar != null) {
+17 −1
Original line number Diff line number Diff line
@@ -344,9 +344,17 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {

        mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeActivity);

        assertEquals(homeActivity, mDefaultDisplay.mFixedRotationLaunchingApp);

        // Check that the home app is in portrait
        assertEquals(Configuration.ORIENTATION_PORTRAIT,
                homeActivity.getConfiguration().orientation);

        // Home activity won't become top (return to landActivity), so its fixed rotation and the
        // top rotated record should be cleared.
        mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
        assertFalse(homeActivity.hasFixedRotationTransform());
        assertNull(mDefaultDisplay.mFixedRotationLaunchingApp);
    }

    @Test
@@ -401,8 +409,16 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
        assertEquals(Configuration.ORIENTATION_PORTRAIT,
                wallpapers.get(0).getConfiguration().orientation);

        mController.cleanupAnimation(REORDER_MOVE_TO_TOP);
        // 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.mFixedRotationLaunchingApp);

        mDefaultDisplay.mFixedRotationTransitionListener.onAppTransitionFinishedLocked(
                homeActivity.token);
        // Wallpaper's transform state should be cleared with home.
        homeActivity.finishFixedRotationTransform();
        assertFalse(homeActivity.hasFixedRotationTransform());
        assertFalse(wallpaperWindowToken.hasFixedRotationTransform());
    }