Wait for windows to be drawn before ending boot animation

The WindowManagerService relies on
DisplayContent#shouldWaitForSystemDecorWindowsOnBoot to decide when to
stop the boot animation. This is using WindowState#isDrawnLw, which
retuns true even if the window animation drawn state is still
READY_TO_SHOW, which causes the animation to finish before the windows
have actually drawn its content.

Adding an extra contion of the WindowState#hasDrawn fixes the bug by
forcing the boot animation to wait for the actual drawning.

The black screen blinking after boot was probably introduced after
ag/5312659 fixed a boot timeout that happened because #isVisibleLw was
also being called as a wait condition. Fixing the timeout surfaced the
fact that isDrawnLw is not enough condition to wait for the windows to
be drawn.

Fix: 149050316
Test: atest DisplayContentTests and also manually restarting device
Change-Id: I4a24e61d61a10d898d37022549d6aa531c251df3
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 80fcf2e..e02ea81 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -97,9 +97,7 @@
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.SurfaceControl.Transaction;
-import android.view.ViewRootImpl;
 import android.view.WindowManager;
-import android.view.test.InsetsModeSession;
 
 import androidx.test.filters.SmallTest;
 
@@ -448,7 +446,7 @@
         assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
 
         // Verify not waiting for drawn windows.
-        makeWindowsDrawn(windows);
+        makeWindowsDrawnState(windows, WindowStateAnimator.HAS_DRAWN);
         assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
     }
 
@@ -469,10 +467,26 @@
         assertTrue(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
 
         // Verify not waiting for drawn windows on display with system decorations.
-        makeWindowsDrawn(windows);
+        makeWindowsDrawnState(windows, WindowStateAnimator.HAS_DRAWN);
         assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
     }
 
+    @Test
+    public void testShouldWaitForSystemDecorWindowsOnBoot_OnWindowReadyToShowAndDrawn() {
+        mWm.mSystemBooted = true;
+        final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
+        final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
+                TYPE_WALLPAPER, TYPE_APPLICATION);
+
+        // Verify waiting for windows to be drawn.
+        makeWindowsDrawnState(windows, WindowStateAnimator.READY_TO_SHOW);
+        assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
+
+        // Verify not waiting for drawn windows.
+        makeWindowsDrawnState(windows, WindowStateAnimator.HAS_DRAWN);
+        assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
+    }
+
     private WindowState[] createNotDrawnWindowsOn(DisplayContent displayContent, int... types) {
         final WindowState[] windows = new WindowState[types.length];
         for (int i = 0; i < types.length; i++) {
@@ -483,10 +497,10 @@
         return windows;
     }
 
-    private static void makeWindowsDrawn(WindowState[] windows) {
+    private static void makeWindowsDrawnState(WindowState[] windows, int state) {
         for (WindowState window : windows) {
             window.mHasSurface = true;
-            window.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
+            window.mWinAnimator.mDrawState = state;
         }
     }