diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index ad3ad5082a96d..ce44dab8fc097 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -1342,6 +1342,24 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } } + /** + * Returns whether the drawn window states of this {@link AppWindowToken} has considered every + * child {@link WindowState}. A child is considered if it has been passed into + * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine + * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as + * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered. + * + * @return {@code true} If all children have been considered, {@code false}. + */ + private boolean allDrawnStatesConsidered() { + for (WindowState child : mChildren) { + if (!child.getDrawnStatedEvaluated()) { + return false; + } + } + return true; + } + /** * Determines if the token has finished drawing. This should only be called from * {@link DisplayContent#applySurfaceChangesTransaction} @@ -1349,9 +1367,14 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree void updateAllDrawn() { if (!allDrawn) { // Number of drawn windows can be less when a window is being relaunched, wait for - // all windows to be launched and drawn for this token be considered all drawn + // all windows to be launched and drawn for this token be considered all drawn. final int numInteresting = mNumInterestingWindows; - if (numInteresting > 0 && mNumDrawnWindows >= numInteresting && !isRelaunching()) { + + // We must make sure that all present children have been considered (determined by + // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been + // drawn. + if (numInteresting > 0 && allDrawnStatesConsidered() + && mNumDrawnWindows >= numInteresting && !isRelaunching()) { if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows); allDrawn = true; @@ -1396,6 +1419,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree * windows in this app token where not considered drawn as of the last pass. */ boolean updateDrawnWindowStates(WindowState w) { + w.setDrawnStateEvaluated(true /*evaluated*/); + if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) { Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen() + " allDrawn=" + allDrawn + " freezingScreen=" + mAppAnimator.freezingScreen); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index d1fbf900ef70e..f73d3c2788495 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -559,6 +559,13 @@ class WindowState extends WindowContainer implements WindowManagerP */ final Rect mLastSurfaceInsets = new Rect(); + /** + * A flag set by the {@link WindowState} parent to indicate that the parent has examined this + * {@link WindowState} in its overall drawing context. This book-keeping allows the parent to + * make sure all children have been considered. + */ + private boolean mDrawnStateEvaluated; + /** * Compares two window sub-layers and returns -1 if the first is lesser than the second in terms * of z-order and 1 otherwise. @@ -675,6 +682,27 @@ class WindowState extends WindowContainer implements WindowManagerP mSession.windowAddedLocked(mAttrs.packageName); } + /** + * Returns whether this {@link WindowState} has been considered for drawing by its parent. + */ + boolean getDrawnStatedEvaluated() { + return mDrawnStateEvaluated; + } + + /** + * Sets whether this {@link WindowState} has been considered for drawing by its parent. Should + * be cleared when detached from parent. + */ + void setDrawnStateEvaluated(boolean evaluated) { + mDrawnStateEvaluated = evaluated; + } + + @Override + void onParentSet() { + super.onParentSet(); + setDrawnStateEvaluated(false /*evaluated*/); + } + @Override public int getOwningUid() { return mOwnerUid;