Wait for system decor windows on all displays during boot

To prevent from showing empty content on some displays temporarily,
wait for displays which support system decorations that have the
expected window types to be drawn.

Also correct the conditions for waiting:
- isVisibleLw and !isDrawnLw are contradicted because they both
  check mHasSurface.
- TYPE_APPLICATION must belong to an activity so it is more
  reasonable to check BASE_APPLICATION.

Bug: 117597389
Test: atest DisplayContentTests \
      #testShouldWaitForSystemDecorWindowsOnBoot_OnSecondaryDisplay
Test: manual enable "Simulate secondary displays" in dev options.
      Reboot and check no "BOOT TIMEOUT" in log.

Change-Id: Ie0890cd006da74f290ecc6cbcf1064a0b26de574
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 ae40742..ade0b14 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -39,6 +39,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
@@ -46,6 +47,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
@@ -396,6 +398,59 @@
                 mWm.mRoot.getTopFocusedDisplayContent().getDisplayId());
     }
 
+    @Test
+    public void testShouldWaitForSystemDecorWindowsOnBoot_OnDefaultDisplay() {
+        mWm.mSystemBooted = true;
+        final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked();
+        final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay,
+                TYPE_WALLPAPER, TYPE_APPLICATION);
+
+        // Verify waiting for windows to be drawn.
+        assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
+
+        // Verify not waiting for drawn windows.
+        makeWindowsDrawn(windows);
+        assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
+    }
+
+    @Test
+    public void testShouldWaitForSystemDecorWindowsOnBoot_OnSecondaryDisplay() {
+        mWm.mSystemBooted = true;
+        final DisplayContent secondaryDisplay = createNewDisplay();
+        final WindowState[] windows = createNotDrawnWindowsOn(secondaryDisplay,
+                TYPE_WALLPAPER, TYPE_APPLICATION);
+
+        // Verify not waiting for display without system decorations.
+        doReturn(false).when(secondaryDisplay).supportsSystemDecorations();
+        assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
+
+        // Verify waiting for non-drawn windows on display with system decorations.
+        reset(secondaryDisplay);
+        doReturn(true).when(secondaryDisplay).supportsSystemDecorations();
+        assertTrue(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
+
+        // Verify not waiting for drawn windows on display with system decorations.
+        makeWindowsDrawn(windows);
+        assertFalse(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot());
+    }
+
+    private WindowState[] createNotDrawnWindowsOn(DisplayContent displayContent, int... types) {
+        final WindowState[] windows = new WindowState[types.length];
+        for (int i = 0; i < types.length; i++) {
+            final int type = types[i];
+            windows[i] = createWindow(null /* parent */, type, displayContent, "window-" + type);
+            windows[i].mHasSurface = false;
+        }
+        return windows;
+    }
+
+    private static void makeWindowsDrawn(WindowState[] windows) {
+        for (WindowState window : windows) {
+            window.mHasSurface = true;
+            window.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
+        }
+    }
+
     /**
      * This tests setting the maximum ui width on a display.
      */