diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index e1fdefd026cc2..e02cce4b946a0 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -421,7 +421,10 @@ public class RecentsAnimationController implements DeathRecipient { if (skipAnimation(task)) { continue; } - addAnimation(task, !recentTaskIds.get(task.mTaskId)); + addAnimation(task, !recentTaskIds.get(task.mTaskId), false /* hidden */, + (type, anim) -> task.forAllWindows(win -> { + win.onAnimationFinished(type, anim); + }, true /* traverseTopToBottom */)); } // Skip the animation if there is nothing to animate diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 09fbce0346395..1efb363204d6e 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2595,11 +2595,12 @@ public class WindowManagerService extends IWindowManager.Stub } else if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) { focusMayChange = true; win.mAnimatingExit = true; - } else if (win.isAnimating(TRANSITION | PARENTS)) { + } else if (win.mDisplayContent.okToAnimate() && win.isAnimating(TRANSITION | PARENTS)) { // Currently in a hide animation... turn this into // an exit. win.mAnimatingExit = true; - } else if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) { + } else if (win.mDisplayContent.okToAnimate() + && win.mDisplayContent.mWallpaperController.isWallpaperTarget(win)) { // If the wallpaper is currently behind this // window, we need to change both of them inside // of a transaction to avoid artifacts. 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 409bad416cf89..c6be987802b5d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java @@ -493,7 +493,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { initializeRecentsAnimationController(mController, homeActivity); // Verify RecentsAnimationController will animate visible leaf task by default. - verify(mController).addAnimation(eq(leafTask), anyBoolean(), anyBoolean(), eq(null)); + verify(mController).addAnimation(eq(leafTask), anyBoolean(), anyBoolean(), any()); assertTrue(leafTask.isAnimatingByRecents()); // Make sure isAnimatingByRecents will also return true when it called by the parent task. @@ -543,6 +543,35 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { verify(navBarFadeAnimationController, never()).fadeWindowToken(anyBoolean()); } + @Test + public void testCleanupAnimation_expectExitAnimationDone() { + 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.startAnimation(); + + spyOn(win1); + spyOn(win1.mWinAnimator); + // Simulate when the window is exiting and cleanupAnimation invoked + // (e.g. screen off during RecentsAnimation animating), will expect the window receives + // onExitAnimationDone to destroy the surface when the removal is allowed. + win1.mWinAnimator.mSurfaceController = mock(WindowSurfaceController.class); + win1.mHasSurface = true; + win1.mAnimatingExit = true; + win1.mRemoveOnExit = true; + win1.mWindowRemovalAllowed = true; + mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION); + verify(win1).onAnimationFinished(eq(ANIMATION_TYPE_RECENTS), any()); + verify(win1).onExitAnimationDone(); + verify(win1).destroySurface(eq(false), eq(false)); + assertFalse(win1.mAnimatingExit); + assertFalse(win1.mHasSurface); + } + private ActivityRecord createHomeActivity() { final ActivityRecord homeActivity = new ActivityBuilder(mWm.mAtmService) .setParentTask(mRootHomeTask)