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

Commit bdc4e842 authored by Issei Suzuki's avatar Issei Suzuki
Browse files

Clean up windows which stuck in animatingExit state.

WM delays to destroy window surface if the window is running an exit
animation, and clean it up after the animation finishes. In case the
clean up process was not triggered, we do it before starting an app
transition.

Note that this is a safe guard for potential bugs. The surface shall
be destroyed as soon as an animation finishes, so the clean up should
have been done before an app transition starts.

Bug: 205335975
Test: atest AppTransitionControllerTest
Change-Id: I9c37ab9ebc57ef48827df25ecc52bf09101ad419
parent 35185d54
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -889,6 +889,12 @@
      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
      "at": "com\/android\/server\/wm\/NonAppWindowAnimationAdapter.java"
    },
    "-1145384901": {
      "message": "shouldWaitAnimatingExit: isTransition: %s",
      "level": "DEBUG",
      "group": "WM_DEBUG_APP_TRANSITIONS",
      "at": "com\/android\/server\/wm\/WindowState.java"
    },
    "-1142279614": {
      "message": "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s",
      "level": "VERBOSE",
@@ -1273,6 +1279,12 @@
      "group": "WM_DEBUG_SCREEN_ON",
      "at": "com\/android\/server\/wm\/WindowManagerService.java"
    },
    "-743856570": {
      "message": "shouldWaitAnimatingExit: isAnimating: %s",
      "level": "DEBUG",
      "group": "WM_DEBUG_APP_TRANSITIONS",
      "at": "com\/android\/server\/wm\/WindowState.java"
    },
    "-743431900": {
      "message": "Configuration no differences in %s",
      "level": "VERBOSE",
@@ -1777,6 +1789,12 @@
      "group": "WM_DEBUG_SYNC_ENGINE",
      "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
    },
    "-208825711": {
      "message": "shouldWaitAnimatingExit: isWallpaperTarget: %s",
      "level": "DEBUG",
      "group": "WM_DEBUG_APP_TRANSITIONS",
      "at": "com\/android\/server\/wm\/WindowState.java"
    },
    "-198463978": {
      "message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b",
      "level": "VERBOSE",
@@ -2989,6 +3007,12 @@
      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
      "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java"
    },
    "1087494661": {
      "message": "Clear window stuck on animatingExit status: %s",
      "level": "WARN",
      "group": "WM_DEBUG_APP_TRANSITIONS",
      "at": "com\/android\/server\/wm\/WindowState.java"
    },
    "1088929964": {
      "message": "onLockTaskPackagesUpdated: starting new locktask task=%s",
      "level": "DEBUG",
+3 −0
Original line number Diff line number Diff line
@@ -176,6 +176,9 @@ public class AppTransitionController {
        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "AppTransitionReady");

        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "**** GOOD TO GO");
        // TODO(b/205335975): Remove window which stuck in animatingExit status. Find actual cause.
        mDisplayContent.forAllWindows(WindowState::cleanupAnimatingExitWindow,
                true /* traverseTopToBottom */);
        // TODO(new-app-transition): Remove code using appTransition.getAppTransition()
        final AppTransition appTransition = mDisplayContent.mAppTransition;

+42 −0
Original line number Diff line number Diff line
@@ -5069,6 +5069,48 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        return false;
    }

    private boolean shouldFinishAnimatingExit() {
        // Exit animation might be applied soon.
        if (inTransition()) {
            ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "shouldWaitAnimatingExit: isTransition: %s",
                    this);
            return false;
        }
        if (!mDisplayContent.okToAnimate()) {
            return true;
        }
        // Exit animation is running.
        if (isAnimating(TRANSITION | PARENTS, EXIT_ANIMATING_TYPES)) {
            ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "shouldWaitAnimatingExit: isAnimating: %s",
                    this);
            return false;
        }
        // If the wallpaper is currently behind this app window, we need to change both of
        // them inside of a transaction to avoid artifacts.
        if (mDisplayContent.mWallpaperController.isWallpaperTarget(this)) {
            ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
                    "shouldWaitAnimatingExit: isWallpaperTarget: %s", this);
            return false;
        }
        return true;
    }

    /**
     * If this is window is stuck in the animatingExit status, resume clean up procedure blocked
     * by the exit animation.
     */
    void cleanupAnimatingExitWindow() {
        // TODO(b/205335975): WindowManagerService#tryStartExitingAnimation starts an exit animation
        // and set #mAnimationExit. After the exit animation finishes, #onExitAnimationDone shall
        // be called, but there seems to be a case that #onExitAnimationDone is not triggered, so
        // a windows stuck in the animatingExit status.
        if (mAnimatingExit && shouldFinishAnimatingExit()) {
            ProtoLog.w(WM_DEBUG_APP_TRANSITIONS, "Clear window stuck on animatingExit status: %s",
                    this);
            onExitAnimationDone();
        }
    }

    void onExitAnimationDone() {
        if (DEBUG_ANIM) Slog.v(TAG, "onExitAnimationDone in " + this
                + ": exiting=" + mAnimatingExit + " remove=" + mRemoveOnExit
+12 −0
Original line number Diff line number Diff line
@@ -333,6 +333,18 @@ public class AppTransitionControllerTest extends WindowTestsBase {
                        new ArraySet<>(), closing, false /* visible */));
    }

    @Test
    public void testExitAnimationDone_beforeAppTransition() {
        final Task task = createTask(mDisplayContent);
        final WindowState win = createAppWindow(task, ACTIVITY_TYPE_STANDARD, "Win");
        spyOn(win);
        win.mAnimatingExit = true;
        mDisplayContent.mAppTransition.setTimeout();
        mDisplayContent.mAppTransitionController.handleAppTransitionReady();

        verify(win).onExitAnimationDone();
    }

    @Test
    public void testGetAnimationTargets_windowsAreBeingReplaced() {
        // [DisplayContent] -+- [Task1] - [ActivityRecord1] (opening, visible)