diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index cb30f1624e677..9e147b1326820 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -1030,7 +1030,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 79feb8d30dfde..d88fbee6ae13a 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);