From cbcf2ca2324d03451ddc8dc9520d300963aedb80 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 15 Jul 2021 10:13:39 -0700 Subject: [PATCH] Fix a couple more issues with canceling the recents animation w/ screenshots - There are a couple scenarios that were exposed in further testing of cancelling the recents animation with screenshots: 1) ensure that we force-cancel the recents animation (ie. continue cancel when deferred) if the process dies, the failsafe occurs or starting a new animation. Previous the failsafe was not continuing since it was already canceled 2) Add a failsafe when deferring cancelling. This is a catch-all for cases where launcher fails to return promptly, the system won't be stuck in a pending state waiting for the cleanup 3) Always finish the animation when requested by the runner even if there is a deferred cancel. Launcher was assuming that this was the case, but we were actually skipping the finish (which also causes the controller on the launcher side to be cleared) which prevents the cleanupScreenshot() from happening. Bug: 192564669 Test: atest RecentsAnimationControllerTest Change-Id: I8952a0c404bb17056c03f2bc8e78f51fc5bd0a1e --- .../android/server/wm/RecentsAnimation.java | 6 ++- .../server/wm/RecentsAnimationController.java | 39 ++++++++++--------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java index a10b5d6e81771..b1bdc11ecee43 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimation.java +++ b/services/core/java/com/android/server/wm/RecentsAnimation.java @@ -239,8 +239,10 @@ class RecentsAnimation implements RecentsAnimationCallbacks, OnRootTaskOrderChan // Fetch all the surface controls and pass them to the client to get the animation // started. Cancel any existing recents animation running synchronously (do not hold the // WM lock) - mWindowManager.cancelRecentsAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, - "startRecentsActivity"); + if (mWindowManager.getRecentsAnimationController() != null) { + mWindowManager.getRecentsAnimationController().forceCancelAnimation( + REORDER_MOVE_TO_ORIGINAL_POSITION, "startRecentsActivity"); + } mWindowManager.initializeRecentsAnimation(mTargetActivityType, recentsAnimationRunner, this, mDefaultTaskDisplayArea.getDisplayId(), mTaskSupervisor.mRecentTasks.getRecentTaskIds(), targetActivity); diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 9e147b1326820..e346e3ec7db91 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -122,9 +122,7 @@ public class RecentsAnimationController implements DeathRecipient { new ArrayList<>(); private final int mDisplayId; private boolean mWillFinishToHome = false; - private final Runnable mFailsafeRunnable = () -> cancelAnimation( - mWillFinishToHome ? REORDER_MOVE_TO_TOP : REORDER_MOVE_TO_ORIGINAL_POSITION, - "failSafeRunnable"); + private final Runnable mFailsafeRunnable = this::onFailsafe; // The recents component app token that is shown behind the visibile tasks private ActivityRecord mTargetActivityRecord; @@ -262,9 +260,6 @@ public class RecentsAnimationController implements DeathRecipient { final long token = Binder.clearCallingIdentity(); try { synchronized (mService.getWindowManagerLock()) { - if (mCanceled) { - return; - } // Remove all new task targets. for (int i = mPendingNewTaskTargets.size() - 1; i >= 0; i--) { removeTaskInternal(mPendingNewTaskTargets.get(i)); @@ -807,6 +802,14 @@ public class RecentsAnimationController implements DeathRecipient { }, mPendingWallpaperAnimations); } + void forceCancelAnimation(@ReorderMode int reorderMode, String reason) { + if (!mCanceled) { + cancelAnimation(reorderMode, reason); + } else { + continueDeferredCancelAnimation(); + } + } + void cancelAnimation(@ReorderMode int reorderMode, String reason) { cancelAnimation(reorderMode, false /*screenshot */, reason); } @@ -821,9 +824,6 @@ public class RecentsAnimationController implements DeathRecipient { * finish the animation. */ public void cancelAnimationForHomeStart() { - if (mCanceled) { - return; - } final int reorderMode = mTargetActivityType == ACTIVITY_TYPE_HOME && mWillFinishToHome ? REORDER_MOVE_TO_TOP : REORDER_KEEP_IN_PLACE; @@ -836,9 +836,6 @@ public class RecentsAnimationController implements DeathRecipient { * how to finish the animation. */ public void cancelAnimationForDisplayChange() { - if (mCanceled) { - return; - } cancelAnimation(mWillFinishToHome ? REORDER_MOVE_TO_TOP : REORDER_MOVE_TO_ORIGINAL_POSITION, true /* screenshot */, "cancelAnimationForDisplayChange"); } @@ -868,6 +865,8 @@ public class RecentsAnimationController implements DeathRecipient { if (taskSnapshot != null) { // Defer until the runner calls back to cleanupScreenshot() adapter.setSnapshotOverlay(taskSnapshot); + // Schedule a new failsafe for if the runner doesn't clean up the screenshot + scheduleFailsafe(); } else { // Do a normal cancel since we couldn't screenshot mCallbacks.onAnimationFinished(reorderMode, false /* sendUserLeaveHint */); @@ -1014,6 +1013,12 @@ public class RecentsAnimationController implements DeathRecipient { mService.mH.postDelayed(mFailsafeRunnable, FAILSAFE_DELAY); } + void onFailsafe() { + forceCancelAnimation( + mWillFinishToHome ? REORDER_MOVE_TO_TOP : REORDER_MOVE_TO_ORIGINAL_POSITION, + "onFailsafe"); + } + private void linkToDeathOfRunner() throws RemoteException { if (!mLinkedToDeathOfRunner) { mRunner.asBinder().linkToDeath(this, 0); @@ -1030,13 +1035,7 @@ public class RecentsAnimationController implements DeathRecipient { @Override public void binderDied() { - if (!mCanceled) { - cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "binderDied"); - } else { - // If we are already canceled but with a screenshot, and are waiting for the - // cleanupScreenshot() callback, then force-finish the animation now - continueDeferredCancelAnimation(); - } + forceCancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "binderDied"); synchronized (mService.getWindowManagerLock()) { // Clear associated input consumers on runner death @@ -1358,5 +1357,7 @@ public class RecentsAnimationController implements DeathRecipient { + mCancelOnNextTransitionStart); pw.print(innerPrefix); pw.println("mCancelDeferredWithScreenshot=" + mCancelDeferredWithScreenshot); + pw.print(innerPrefix); pw.println("mPendingCancelWithScreenshotReorderMode=" + + mPendingCancelWithScreenshotReorderMode); } }