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;
}
}