From a00ebe4606daafeb0f9daa16d800c523cf1588b8 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Wed, 3 Jul 2019 15:45:59 +0200 Subject: [PATCH 1/2] Reland "Prevent dismissing starting window when reopening app" If we are changing the visibility while the app is shortly before drawing it's first frame, we cleared out the draw state, leading to a hang. We also had this issue with starting windows, but that was a fix only for starting windows, but cascaded the underlying issue. Now, we only clear out the draw state if is has fully drawn - this covers the Chrome case but doesn't clear out draw state if it's just about to show. Furthermore, we also add the window to mResizingWindows such that the client is expected to call back to us with reportDrawn, in all the edge cases. Test: go/wm-smoke Test: Open TTS settings, go back, open again Test: All the use cases from the linked bug Bug: 135706138 Bug: 135661232 Bug: 135976008 Bug: 135921478 Bug: 135780312 Bug: 135084202 Fixes: 134561008 Change-Id: I69f893a19d6426710bb0b8b0e18f3d2664cb6412 --- .../java/com/android/server/wm/AppWindowToken.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 03cae429904f1..eab5e0dd270ea 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -79,6 +79,7 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; import static com.android.server.wm.WindowManagerService.logWithStack; import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY; +import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM; @@ -540,6 +541,18 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree // If the app was already visible, don't reset the waitingToShow state. if (isHidden()) { waitingToShow = true; + + // Let's reset the draw state in order to prevent the starting window to be + // immediately dismissed when the app still has the surface. + forAllWindows(w -> { + if (w.mWinAnimator.mDrawState == HAS_DRAWN) { + w.mWinAnimator.resetDrawState(); + + // Force add to mResizingWindows, so that we are guaranteed to get + // another reportDrawn callback. + w.resetLastContentInsets(); + } + }, true /* traverseTopToBottom */); } } From 07f7d1947af6ceecb19fccf9ae44e88bae6b3f57 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Tue, 16 Jul 2019 17:43:15 +0200 Subject: [PATCH 2/2] Only consider gone for layout if parent is gone for layout If we check getParentWindowHidden, that determines mostly actual visibility. However, we don't want that because we still would like to follow the parent's window layout lifecycle, as otherwise we may be stuck in a transition in case the parent window is hidden but the child is waiting for a layout to happen. Test: Click "Customize" on wallpaper picker, go back, ensure no transition timeout Fixes: 135976008 Change-Id: I66aeab29a81cd82b170aaf337249616b1f559848 (cherry picked from commit b52b0457e1bad14697341cb81f6d391755b009be) --- services/core/java/com/android/server/wm/WindowState.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index c6c9e1b39db41..dcf0f8a99883c 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1611,7 +1611,7 @@ class WindowState extends WindowContainer implements WindowManagerP || !mRelayoutCalled || (atoken == null && mToken.isHidden()) || (atoken != null && atoken.hiddenRequested) - || isParentWindowHidden() + || isParentWindowGoneForLayout() || (mAnimatingExit && !isAnimatingLw()) || mDestroying; } @@ -3764,6 +3764,11 @@ class WindowState extends WindowContainer implements WindowManagerP return parent != null && parent.mHidden; } + private boolean isParentWindowGoneForLayout() { + final WindowState parent = getParentWindow(); + return parent != null && parent.isGoneForLayoutLw(); + } + void setWillReplaceWindow(boolean animate) { for (int i = mChildren.size() - 1; i >= 0; i--) { final WindowState c = mChildren.get(i);