diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 8ccf02caf8c02..6bfbd8d55ab0c 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -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", diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index 878822522d083..721907c21904b 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -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; diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 9128732db366c..44d2a7f593d05 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -5064,6 +5064,48 @@ class WindowState extends WindowContainer 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 diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java index 6fa306b004a2d..506270657e42f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java @@ -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)