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

Commit 4b8c659f authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Defer window removal including app transition

The mWinAnimator.applyAnimationLocked in removeIfPossible may
not apply window level animation, but the activity may be
running closing transition. So the window shouldn't be removed
immediately, otherwise the animation is disappeared.

Bug: 176471456
Test: WindowStateTests#testDeferredRemovalByAnimating
Test: Launch a translucent activity and finish it, check the
      slide-down style exit animation can play with the
      declared duration.

Change-Id: I4227a89108d16fc25f912b96ae83cf125fec4b16
parent 8c828565
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -131,6 +131,7 @@ import static com.android.server.wm.MoveAnimationSpecProto.DURATION_MS;
import static com.android.server.wm.MoveAnimationSpecProto.FROM;
import static com.android.server.wm.MoveAnimationSpecProto.TO;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -2281,7 +2282,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
                        mWmService.mAccessibilityController.onWindowTransitionLocked(this, transit);
                    }
                }
                final boolean isAnimating = isAnimating(TRANSITION | PARENTS)
                final boolean isAnimating = mAnimatingExit || isAnimating(TRANSITION | PARENTS,
                        ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_WINDOW_ANIMATION)
                        && (mActivityRecord == null || !mActivityRecord.isWaitingForTransitionStart());
                final boolean lastWindowIsStartingWindow = startingWindow && mActivityRecord != null
                        && mActivityRecord.isLastWindow(this);
@@ -2290,8 +2292,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
                // Also, If isn't the an animating starting window that is the last window in the app.
                // We allow the removal of the non-animating starting window now as there is no
                // additional window or animation that will trigger its removal.
                if (mWinAnimator.getShown() && mAnimatingExit
                        && (!lastWindowIsStartingWindow || isAnimating)) {
                if (mWinAnimator.getShown() && !lastWindowIsStartingWindow && isAnimating) {
                    // Make isSelfOrAncestorWindowAnimatingExit return true so onExitAnimationDone
                    // can proceed to remove this window.
                    mAnimatingExit = true;
                    // The exit animation is running or should run... wait for it!
                    ProtoLog.v(WM_DEBUG_ADD_REMOVE,
                            "Not removing %s due to exit animation", this);
+20 −0
Original line number Diff line number Diff line
@@ -447,6 +447,26 @@ public class WindowStateTests extends WindowTestsBase {
        assertTrue(child2.isSelfOrAncestorWindowAnimatingExit());
    }

    @Test
    public void testDeferredRemovalByAnimating() {
        final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
        makeWindowVisible(appWindow);
        spyOn(appWindow.mWinAnimator);
        doReturn(true).when(appWindow.mWinAnimator).getShown();
        final AnimationAdapter animation = mock(AnimationAdapter.class);
        final ActivityRecord activity = appWindow.mActivityRecord;
        activity.startAnimation(appWindow.getPendingTransaction(),
                animation, false /* hidden */, SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION);

        appWindow.removeIfPossible();
        assertTrue(appWindow.mAnimatingExit);
        assertFalse(appWindow.mRemoved);

        activity.cancelAnimation();
        assertFalse(appWindow.mAnimatingExit);
        assertTrue(appWindow.mRemoved);
    }

    @Test
    public void testLayoutSeqResetOnReparent() {
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");