From 8ed3e4a826356b5e93008653d310844ea9d4d8e5 Mon Sep 17 00:00:00 2001 From: Robin Lee Date: Thu, 23 Feb 2023 22:46:41 +0100 Subject: [PATCH] Accept a Window as shown if it's in any transition Previously, a malicious or confused app can DoS all other apps with unshown surfaces by kicking off at least one new transition every frame. For example (see linked bug), an app in a busy-loop trying to request permissions can prevent the launcher from showing Recents. The significant change here is that when we see that there is a transition set, we only block on mToken.waitingToShow if mToken is not already part of another transition. Otherwise, there can be a new transition generated every frame and the token is constantly stuck waiting to show. Test: atest CtsWindowManagerDeviceTestCases Bug: 269108443 Fix: 271085429 Change-Id: I47ce9fdf5429795cbf083516c19b669bc407d1da (cherry picked from commit on googleplex-android-review.googlesource.com host: d98e95c7c8892e45ca018b7c7227e3b658763df1) Merged-In: I47ce9fdf5429795cbf083516c19b669bc407d1da --- .../core/java/com/android/server/wm/WindowState.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 52f2b6351265b..054d68f6edfb5 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2049,16 +2049,19 @@ class WindowState extends WindowContainer implements WindowManagerP /** * Like isOnScreen(), but we don't return true if the window is part - * of a transition that has not yet been started. + * of a transition but has not yet started animating. */ boolean isReadyForDisplay() { - if (mToken.waitingToShow && getDisplayContent().mAppTransition.isTransitionSet()) { + if (!mHasSurface || mDestroying || !isVisibleByPolicy()) { + return false; + } + if (mToken.waitingToShow && getDisplayContent().mAppTransition.isTransitionSet() + && !isAnimating(TRANSITION | PARENTS, ANIMATION_TYPE_APP_TRANSITION)) { return false; } final boolean parentAndClientVisible = !isParentWindowHidden() && mViewVisibility == View.VISIBLE && mToken.isVisible(); - return mHasSurface && isVisibleByPolicy() && !mDestroying - && (parentAndClientVisible || isAnimating(TRANSITION | PARENTS)); + return parentAndClientVisible || isAnimating(TRANSITION | PARENTS, ANIMATION_TYPE_ALL); } boolean isFullyTransparent() {