Fix app afterimage flashing while device unlocking
The problem is because in WMS#tryStartExitingAnimation set
win.mAnimatingExit as ture but not destroy surface when pressing
power button, so let `WindowState#mHasSurface` keeps true when
screen off. (Normally the surface should be destroyed when screen off)
This results when unlocking the screen will can see both the app
window afterimage and launcher are animating.
Check with DC#okToAnimate in tryStartExitingAnimation to ensure the
surface can be destroyed when the display is not ready to animate (e.g.
screen off).
Also, in order to cleanly clean up surfaces while cancelling recents
animation when the removal is allowed, make sure to invoke
onAnimationFinished for task's windows to finish the process of
the surface removal.
Fix: 173379232
Test: atest WmTests CtsWindowManagerDeviceTestCases
Test: atest RecentsAnimationControllerTests#\
testCleanupAnimation_expectExitAnimationDone
Test: manul as below steps:
1. in gesture nav mode, launch any apps (e.g. Settings).
2. swipe up app task to launcher
3. before swipe up animation finish, quickly pressing power button.
4. turn on screen and unlock, see if the app window flashing then back
to launcher.
Change-Id: Ib2778c1b2677752039be12a16a42623a25773fa2
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -2563,11 +2563,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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user