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

Commit 65c5f99a authored by Winson Chung's avatar Winson Chung
Browse files

Don't call into AM finish-recents-animation while holding onto the WM lock

- By default, only call back to AM to finish the animation from callers
  outside of the system, when we are not holding the WM lock

Bug: 78258614
Test: Not really testable

Change-Id: I89966b1db165b39742a550f3e315bda7da7ce586
parent 3f8dd1ca
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -5306,7 +5306,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        final long origId = Binder.clearCallingIdentity();
        try {
            synchronized (this) {
                mWindowManager.cancelRecentsAnimation(restoreHomeStackPosition
                // Cancel the recents animation synchronously (do not hold the WM lock)
                mWindowManager.cancelRecentsAnimationSynchronously(restoreHomeStackPosition
                        ? REORDER_MOVE_TO_ORIGINAL_POSITION
                        : REORDER_KEEP_IN_PLACE, "cancelRecentsAnimation");
            }
+16 −6
Original line number Diff line number Diff line
@@ -179,8 +179,9 @@ class RecentsAnimation implements RecentsAnimationCallbacks {
            targetActivity.mLaunchTaskBehind = true;

            // Fetch all the surface controls and pass them to the client to get the animation
            // started
            mWindowManager.cancelRecentsAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION,
            // started. Cancel any existing recents animation running synchronously (do not hold the
            // WM lock)
            mWindowManager.cancelRecentsAnimationSynchronously(REORDER_MOVE_TO_ORIGINAL_POSITION,
                    "startRecentsActivity");
            mWindowManager.initializeRecentsAnimation(mTargetActivityType, recentsAnimationRunner,
                    this, display.mDisplayId, mStackSupervisor.mRecentTasks.getRecentTaskIds());
@@ -200,8 +201,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks {
        }
    }

    @Override
    public void onAnimationFinished(@RecentsAnimationController.ReorderMode int reorderMode) {
    private void finishAnimation(@RecentsAnimationController.ReorderMode int reorderMode) {
        synchronized (mService) {
            if (DEBUG) Slog.d(TAG, "onAnimationFinished(): controller="
                    + mWindowManager.getRecentsAnimationController()
@@ -298,6 +298,16 @@ class RecentsAnimation implements RecentsAnimationCallbacks {
        }
    }

    @Override
    public void onAnimationFinished(@RecentsAnimationController.ReorderMode int reorderMode,
            boolean runSychronously) {
        if (runSychronously) {
            finishAnimation(reorderMode);
        } else {
            mService.mHandler.post(() -> finishAnimation(reorderMode));
        }
    }

    /**
     * Called only when the animation should be canceled prior to starting.
     */
+17 −8
Original line number Diff line number Diff line
@@ -81,9 +81,8 @@ public class RecentsAnimationController implements DeathRecipient {
    private final RecentsAnimationCallbacks mCallbacks;
    private final ArrayList<TaskAnimationAdapter> mPendingAnimations = new ArrayList<>();
    private final int mDisplayId;
    private final Runnable mFailsafeRunnable = () -> {
    private final Runnable mFailsafeRunnable = () ->
            cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "failSafeRunnable");
    };

    // The recents component app token that is shown behind the visibile tasks
    private AppWindowToken mTargetAppToken;
@@ -110,7 +109,7 @@ public class RecentsAnimationController implements DeathRecipient {
    private boolean mLinkedToDeathOfRunner;

    public interface RecentsAnimationCallbacks {
        void onAnimationFinished(@ReorderMode int reorderMode);
        void onAnimationFinished(@ReorderMode int reorderMode, boolean runSychronously);
    }

    private final IRecentsAnimationController mController =
@@ -162,7 +161,8 @@ public class RecentsAnimationController implements DeathRecipient {
                // prior to calling the callback
                mCallbacks.onAnimationFinished(moveHomeToTop
                        ? REORDER_MOVE_TO_TOP
                        : REORDER_MOVE_TO_ORIGINAL_POSITION);
                        : REORDER_MOVE_TO_ORIGINAL_POSITION,
                        true /* runSynchronously */);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
@@ -369,7 +369,17 @@ public class RecentsAnimationController implements DeathRecipient {
    }

    void cancelAnimation(@ReorderMode int reorderMode, String reason) {
        if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "cancelAnimation(): reason=" + reason);
        cancelAnimation(reorderMode, false /* runSynchronously */, reason);
    }

    void cancelAnimationSynchronously(@ReorderMode int reorderMode, String reason) {
        cancelAnimation(reorderMode, true /* runSynchronously */, reason);
    }

    private void cancelAnimation(@ReorderMode int reorderMode, boolean runSynchronously,
            String reason) {
        if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "cancelAnimation(): reason=" + reason
                + " runSynchronously=" + runSynchronously);
        synchronized (mService.getWindowManagerLock()) {
            if (mCanceled) {
                // We've already canceled the animation
@@ -385,8 +395,7 @@ public class RecentsAnimationController implements DeathRecipient {
        }

        // Clean up and return to the previous app
        // Don't hold the WM lock here as it calls back to AM/RecentsAnimation
        mCallbacks.onAnimationFinished(reorderMode);
        mCallbacks.onAnimationFinished(reorderMode, runSynchronously);
    }

    void cleanupAnimation(@ReorderMode int reorderMode) {
+5 −7
Original line number Diff line number Diff line
@@ -2732,17 +2732,15 @@ public class WindowManagerService extends IWindowManager.Stub

    /**
     * Cancels any running recents animation. The caller should NOT hold the WM lock while calling
     * this method, as it can call back into AM, and locking will be done in the animation
     * controller itself.
     * this method, as it will call back into AM and may cause a deadlock. Any locking will be done
     * in the animation controller itself.
     */
    public void cancelRecentsAnimation(@RecentsAnimationController.ReorderMode int reorderMode,
            String reason) {
        // Note: Do not hold the WM lock, this will lock appropriately in the call which also
        // calls through to AM/RecentsAnimation.onAnimationFinished()
    public void cancelRecentsAnimationSynchronously(
            @RecentsAnimationController.ReorderMode int reorderMode, String reason) {
        if (mRecentsAnimationController != null) {
            // This call will call through to cleanupAnimation() below after the animation is
            // canceled
            mRecentsAnimationController.cancelAnimation(reorderMode, reason);
            mRecentsAnimationController.cancelAnimationSynchronously(reorderMode, reason);
        }
    }