Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57283fb6 authored by Lais Andrade's avatar Lais Andrade
Browse files

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
parent e66ac51e
Loading
Loading
Loading
Loading
+14 −9
Original line number Diff line number Diff line
@@ -3577,17 +3577,22 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        drawnWindowTypes.put(TYPE_NOTIFICATION_SHADE, true);

        final WindowState visibleNotDrawnWindow = getWindow(w -> {
            if (w.mViewVisibility == View.VISIBLE && !w.mObscured && !w.isDrawnLw()) {
            boolean isVisible = w.mViewVisibility == View.VISIBLE && !w.mObscured;
            boolean hasDrawn = w.isDrawnLw() && w.hasDrawnLw();
            if (isVisible && !hasDrawn) {
                return true;
            }
            if (w.isDrawnLw()) {
                final int type = w.mAttrs.type;
                if (type == TYPE_BOOT_PROGRESS || type == TYPE_BASE_APPLICATION
                        || type == TYPE_WALLPAPER) {
                    drawnWindowTypes.put(type, true);
                } else if (type == TYPE_NOTIFICATION_SHADE) {
            if (hasDrawn) {
                switch (w.mAttrs.type) {
                    case TYPE_BOOT_PROGRESS:
                    case TYPE_BASE_APPLICATION:
                    case TYPE_WALLPAPER:
                        drawnWindowTypes.put(w.mAttrs.type, true);
                        break;
                    case TYPE_NOTIFICATION_SHADE:
                        drawnWindowTypes.put(TYPE_NOTIFICATION_SHADE,
                                mWmService.mPolicy.isKeyguardDrawnLw());
                        break;
                }
            }
            return false;
+20 −6
Original line number Diff line number Diff line
@@ -97,9 +97,7 @@ import android.view.InsetsState;
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 @@ public class DisplayContentTests extends WindowTestsBase {
        assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());

        // Verify not waiting for drawn windows.
        makeWindowsDrawn(windows);
        makeWindowsDrawnState(windows, WindowStateAnimator.HAS_DRAWN);
        assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot());
    }

@@ -469,10 +467,26 @@ public class DisplayContentTests extends WindowTestsBase {
        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 @@ public class DisplayContentTests extends WindowTestsBase {
        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;
        }
    }