Ensure all WindowStates are considered before determining all drawn.

The drawn state of an AppWindowToken is calculated on demand in
updateAllDrawn. updateAllDrawn assumes that updateDrawnWindowStates
has been called on every child window beforehand. If a window has
been added but not had updateDrawnWindowStates called for it, the
results of updateAllDrawn will be wrong. This leads to situations
where we will determine we are ready to execute a transition to
home, yet not have a wallpaper activity.

This changelist addresses this issue by recording which WindowStates
have had updateDrawnWindowStates called on them and making sure all
present children have been processed in updateAllDrawn.

Bug: 62846907
Test: go/wm-smoke
Test: turn launcher rotation on, open dialer in portrait, turn off
      screen, rotate to landscape, unlock with fingerprint, press
      home while rotating. make sure transition is correct.

Change-Id: I3d129e686326d868862ae988725fb091a2c86e4e
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 8afc4fd..d01c8b9 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1343,15 +1343,38 @@
     }
 
     /**
+     * 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}
      */
     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 @@
      *         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);