From 8bf68858937d007fdc421e7cf959ffd7e0477ea6 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Mon, 12 Jul 2021 14:17:46 -0700 Subject: [PATCH] Force-finish pending cancellation of the recents animation when process dies - If the recents animation is cancelled, then we need to continue the deferred cancel when the process dies to ensure that the animation is cleaned up correctly (just calling cancel will no-op if the animation was already canceled and waiting for cleanupScreenshot()). This call to continue the deferred cancel is a no-op if there is no deferred cleanup. Bug: 192564669 Test: atest RecentsAnimationControllerTest Test: Defer cleanupScreenshot() and kill launcher process after canceling Change-Id: I500b12dff2b3263e9e1529b4c094e4a422762d66 --- .../server/wm/RecentsAnimationController.java | 8 ++++++- .../wm/RecentsAnimationControllerTest.java | 23 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 737ef338f9b2f..4d2dc73871c69 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -1029,7 +1029,13 @@ public class RecentsAnimationController implements DeathRecipient { @Override public void binderDied() { - cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "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(); + } synchronized (mService.getWindowManagerLock()) { // Clear associated input consumers on runner death diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java index a034ac267287f..5128b3e4d441d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java @@ -306,6 +306,29 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { assertTrue(activity.shouldAnimate()); } + @Test + public void testBinderDiedAfterCancelWithDeferredScreenshot() throws Exception { + mWm.setRecentsAnimationController(mController); + final ActivityRecord homeActivity = createHomeActivity(); + final ActivityRecord activity = createActivityRecord(mDefaultDisplay); + final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1"); + activity.addWindow(win1); + + initializeRecentsAnimationController(mController, homeActivity); + mController.setWillFinishToHome(true); + + // Verify cancel is called with a snapshot and that we've created an overlay + spyOn(mWm.mTaskSnapshotController); + doReturn(mMockTaskSnapshot).when(mWm.mTaskSnapshotController).getSnapshot(anyInt(), + anyInt(), eq(false) /* restoreFromDisk */, eq(false) /* isLowResolution */); + mController.cancelAnimationWithScreenshot(true /* screenshot */); + verify(mMockRunner).onAnimationCanceled(any()); + + // Simulate process crashing and ensure the animation is still canceled + mController.binderDied(); + verify(mAnimationCallbacks).onAnimationFinished(REORDER_KEEP_IN_PLACE, false); + } + @Test public void testRecentViewInFixedPortraitWhenTopAppInLandscape() { unblockDisplayRotation(mDefaultDisplay);