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

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

Cancel animation in previous rotation

The local animations are cancelled if fixed rotation transform is
going to be finished to perform seamless display rotation. That
avoids a case: a closing animation in landscape moved outside the
bottom of the screen, and it still has unfinished alpha animation
(e.g. wallpaper_open_exit is 250+167=417ms which is longer than
than wallpaper_open_enter 225ms). Then if the display is rotated
to portrait, the animation out of view becomes visible.

The reason not waiting for all animations to finish is that will
increase the latency to rotate display, and touching won't work
in the waiting state because the rotation of top activity (rotated
surface) is different than the display.

Bug: 151709552
Test: atest DisplayContentTests#testApplyTopFixedRotationTransform
Test: Enable fixed_rotation_transform, return from a task in
      different orientation to home with default animation.

Change-Id: I7c268de1f9061a7ac11fc42a70f02000faba7106
parent 884aa6af
Loading
Loading
Loading
Loading
+31 −8
Original line number Original line Diff line number Diff line
@@ -5176,14 +5176,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        final int currRotation = currOverrideConfig.windowConfiguration.getRotation();
        final int currRotation = currOverrideConfig.windowConfiguration.getRotation();
        final int overrideRotation = overrideConfiguration.windowConfiguration.getRotation();
        final int overrideRotation = overrideConfiguration.windowConfiguration.getRotation();
        if (currRotation != ROTATION_UNDEFINED && currRotation != overrideRotation) {
        if (currRotation != ROTATION_UNDEFINED && currRotation != overrideRotation) {
            if (mFixedRotationLaunchingApp != null) {
            applyRotationAndClearFixedRotation(currRotation, overrideRotation);
                mFixedRotationLaunchingApp.clearFixedRotationTransform(
                        () -> applyRotation(currRotation, overrideRotation));
                // Clear the record because the display will sync to current rotation.
                mFixedRotationLaunchingApp = null;
            } else {
                applyRotation(currRotation, overrideRotation);
            }
        }
        }
        mCurrentOverrideConfigurationChanges = currOverrideConfig.diff(overrideConfiguration);
        mCurrentOverrideConfigurationChanges = currOverrideConfig.diff(overrideConfiguration);
        super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
        super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
@@ -5193,6 +5186,36 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED);
                ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED);
    }
    }


    /**
     * If the launching rotated activity ({@link #mFixedRotationLaunchingApp}) is null, it simply
     * applies the rotation to display. Otherwise because the activity has shown as rotated, the
     * fixed rotation transform also needs to be cleared to make sure the rotated activity fits
     * the display naturally.
     */
    private void applyRotationAndClearFixedRotation(int oldRotation, int newRotation) {
        if (mFixedRotationLaunchingApp == null) {
            applyRotation(oldRotation, newRotation);
            return;
        }

        // The display may be about to rotate seamlessly, and the animation of closing apps may
        // still animate in old rotation. So make sure the outdated animation won't show on the
        // rotated display.
        mTaskContainers.forAllActivities(a -> {
            if (a.nowVisible && a != mFixedRotationLaunchingApp
                    && a.getWindowConfiguration().getRotation() != newRotation) {
                final WindowContainer<?> w = a.getAnimatingContainer();
                if (w != null) {
                    w.cancelAnimation();
                }
            }
        });

        mFixedRotationLaunchingApp.clearFixedRotationTransform(
                () -> applyRotation(oldRotation, newRotation));
        mFixedRotationLaunchingApp = null;
    }

    /** Checks whether the given activity is in size compatibility mode and notifies the change. */
    /** Checks whether the given activity is in size compatibility mode and notifies the change. */
    void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) {
    void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) {
        if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
        if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+10 −0
Original line number Original line Diff line number Diff line
@@ -56,6 +56,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;


@@ -1006,6 +1007,13 @@ public class DisplayContentTests extends WindowTestsBase {
        mDisplayContent.computeScreenConfiguration(config);
        mDisplayContent.computeScreenConfiguration(config);
        mDisplayContent.onRequestedOverrideConfigurationChanged(config);
        mDisplayContent.onRequestedOverrideConfigurationChanged(config);


        final ActivityRecord closingApp = new ActivityTestsBase.StackBuilder(mWm.mRoot)
                .setDisplay(mDisplayContent).setOnTop(false).build().getTopMostActivity();
        closingApp.nowVisible = true;
        closingApp.startAnimation(closingApp.getPendingTransaction(), mock(AnimationAdapter.class),
                false /* hidden */, ANIMATION_TYPE_APP_TRANSITION);
        assertTrue(closingApp.isAnimating());

        final ActivityRecord app = mAppWindow.mActivityRecord;
        final ActivityRecord app = mAppWindow.mActivityRecord;
        mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
        mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
                false /* alwaysKeepCurrent */);
                false /* alwaysKeepCurrent */);
@@ -1033,6 +1041,8 @@ public class DisplayContentTests extends WindowTestsBase {


        mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
        mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);


        // The animation in old rotation should be cancelled.
        assertFalse(closingApp.isAnimating());
        // The display should be rotated after the launch is finished.
        // The display should be rotated after the launch is finished.
        assertFalse(app.hasFixedRotationTransform());
        assertFalse(app.hasFixedRotationTransform());
        assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);
        assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);