Clean up windows which stuck in animatingExit state.
WM delays to destroy window surface if the window is running an exit animation, and clean it up after the animation finishes. In case the clean up process was not triggered, we do it before starting an app transition. Note that this is a safe guard for potential bugs. The surface shall be destroyed as soon as an animation finishes, so the clean up should have been done before an app transition starts. Bug: 205335975 Test: atest AppTransitionControllerTest Change-Id: I9c37ab9ebc57ef48827df25ecc52bf09101ad419
This commit is contained in:
@@ -889,6 +889,12 @@
|
||||
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
|
||||
"at": "com\/android\/server\/wm\/NonAppWindowAnimationAdapter.java"
|
||||
},
|
||||
"-1145384901": {
|
||||
"message": "shouldWaitAnimatingExit: isTransition: %s",
|
||||
"level": "DEBUG",
|
||||
"group": "WM_DEBUG_APP_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/WindowState.java"
|
||||
},
|
||||
"-1142279614": {
|
||||
"message": "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s",
|
||||
"level": "VERBOSE",
|
||||
@@ -1273,6 +1279,12 @@
|
||||
"group": "WM_DEBUG_SCREEN_ON",
|
||||
"at": "com\/android\/server\/wm\/WindowManagerService.java"
|
||||
},
|
||||
"-743856570": {
|
||||
"message": "shouldWaitAnimatingExit: isAnimating: %s",
|
||||
"level": "DEBUG",
|
||||
"group": "WM_DEBUG_APP_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/WindowState.java"
|
||||
},
|
||||
"-743431900": {
|
||||
"message": "Configuration no differences in %s",
|
||||
"level": "VERBOSE",
|
||||
@@ -1777,6 +1789,12 @@
|
||||
"group": "WM_DEBUG_SYNC_ENGINE",
|
||||
"at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
|
||||
},
|
||||
"-208825711": {
|
||||
"message": "shouldWaitAnimatingExit: isWallpaperTarget: %s",
|
||||
"level": "DEBUG",
|
||||
"group": "WM_DEBUG_APP_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/WindowState.java"
|
||||
},
|
||||
"-198463978": {
|
||||
"message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b",
|
||||
"level": "VERBOSE",
|
||||
@@ -2989,6 +3007,12 @@
|
||||
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
|
||||
"at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java"
|
||||
},
|
||||
"1087494661": {
|
||||
"message": "Clear window stuck on animatingExit status: %s",
|
||||
"level": "WARN",
|
||||
"group": "WM_DEBUG_APP_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/WindowState.java"
|
||||
},
|
||||
"1088929964": {
|
||||
"message": "onLockTaskPackagesUpdated: starting new locktask task=%s",
|
||||
"level": "DEBUG",
|
||||
|
||||
@@ -176,6 +176,9 @@ public class AppTransitionController {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "AppTransitionReady");
|
||||
|
||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "**** GOOD TO GO");
|
||||
// TODO(b/205335975): Remove window which stuck in animatingExit status. Find actual cause.
|
||||
mDisplayContent.forAllWindows(WindowState::cleanupAnimatingExitWindow,
|
||||
true /* traverseTopToBottom */);
|
||||
// TODO(new-app-transition): Remove code using appTransition.getAppTransition()
|
||||
final AppTransition appTransition = mDisplayContent.mAppTransition;
|
||||
|
||||
|
||||
@@ -5069,6 +5069,48 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean shouldFinishAnimatingExit() {
|
||||
// Exit animation might be applied soon.
|
||||
if (inTransition()) {
|
||||
ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "shouldWaitAnimatingExit: isTransition: %s",
|
||||
this);
|
||||
return false;
|
||||
}
|
||||
if (!mDisplayContent.okToAnimate()) {
|
||||
return true;
|
||||
}
|
||||
// Exit animation is running.
|
||||
if (isAnimating(TRANSITION | PARENTS, EXIT_ANIMATING_TYPES)) {
|
||||
ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "shouldWaitAnimatingExit: isAnimating: %s",
|
||||
this);
|
||||
return false;
|
||||
}
|
||||
// If the wallpaper is currently behind this app window, we need to change both of
|
||||
// them inside of a transaction to avoid artifacts.
|
||||
if (mDisplayContent.mWallpaperController.isWallpaperTarget(this)) {
|
||||
ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
|
||||
"shouldWaitAnimatingExit: isWallpaperTarget: %s", this);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is window is stuck in the animatingExit status, resume clean up procedure blocked
|
||||
* by the exit animation.
|
||||
*/
|
||||
void cleanupAnimatingExitWindow() {
|
||||
// TODO(b/205335975): WindowManagerService#tryStartExitingAnimation starts an exit animation
|
||||
// and set #mAnimationExit. After the exit animation finishes, #onExitAnimationDone shall
|
||||
// be called, but there seems to be a case that #onExitAnimationDone is not triggered, so
|
||||
// a windows stuck in the animatingExit status.
|
||||
if (mAnimatingExit && shouldFinishAnimatingExit()) {
|
||||
ProtoLog.w(WM_DEBUG_APP_TRANSITIONS, "Clear window stuck on animatingExit status: %s",
|
||||
this);
|
||||
onExitAnimationDone();
|
||||
}
|
||||
}
|
||||
|
||||
void onExitAnimationDone() {
|
||||
if (DEBUG_ANIM) Slog.v(TAG, "onExitAnimationDone in " + this
|
||||
+ ": exiting=" + mAnimatingExit + " remove=" + mRemoveOnExit
|
||||
|
||||
@@ -333,6 +333,18 @@ public class AppTransitionControllerTest extends WindowTestsBase {
|
||||
new ArraySet<>(), closing, false /* visible */));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExitAnimationDone_beforeAppTransition() {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final WindowState win = createAppWindow(task, ACTIVITY_TYPE_STANDARD, "Win");
|
||||
spyOn(win);
|
||||
win.mAnimatingExit = true;
|
||||
mDisplayContent.mAppTransition.setTimeout();
|
||||
mDisplayContent.mAppTransitionController.handleAppTransitionReady();
|
||||
|
||||
verify(win).onExitAnimationDone();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnimationTargets_windowsAreBeingReplaced() {
|
||||
// [DisplayContent] -+- [Task1] - [ActivityRecord1] (opening, visible)
|
||||
|
||||
Reference in New Issue
Block a user