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
This commit is contained in:
Winson Chung
2021-07-15 10:13:39 -07:00
parent 4162c032bf
commit cbcf2ca232
2 changed files with 24 additions and 21 deletions

View File

@@ -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);

View File

@@ -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);
}
}