From 29bfa72754bda094435f403d39db276fff2c4edd Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Fri, 3 Jul 2020 21:46:24 +0800 Subject: [PATCH] Fix boot timeout and reduce boot time Since the notification shade has been separated from status bar to another window where the keyguard resides. It won't be visible until KeyguardViewMediator receives system ready. By making the visibility of notification shade consistent with the initial state of keyguard when attaching the window, window manager won't miss to wait for it. That avoids dismissing boot animation too early. The windows of notification shade and wallpaper can also be drawn earlier, that reduces the total waiting time of drawn windows by about 50~100ms on a mid-end device. The logic of wait-for-visible-not-drawn-window is restored to be the same as Q. The isVisible considers the independent visibility of wallpaper and visibility of the insets client. The isDrawnLw accepts READY_TO_SHOW so even keyguard decides not to use wallpaper, the procedure won't wait until timeout. Bug: 160271169 Bug: 158144185 Bug: 157746100 Bug: 157281833 Test: atest DisplayContentTests# \ testShouldWaitForSystemDecorWindowsOnBoot_OnDefaultDisplay NotificationShadeWindowControllerTest#attach_visibleWithWallpaper Test: Boot with enable/disable keyguard/wallpaper, there is no timeout and black screen or flickering. Change-Id: I2f979055e89ae5e40af05e469741bb89e2e24ce6 Merged-In: I2f979055e89ae5e40af05e469741bb89e2e24ce6 --- ...ummyNotificationShadeWindowController.java | 5 ++- .../NotificationShadeWindowController.java | 8 +++++ .../bubbles/BubbleControllerTest.java | 7 +++-- .../NewNotifPipelineBubbleControllerTest.java | 7 +++-- ...NotificationShadeWindowControllerTest.java | 18 +++++++++-- .../com/android/server/wm/DisplayContent.java | 8 ++--- .../server/wm/DisplayContentTests.java | 31 ++++++------------- 7 files changed, 52 insertions(+), 32 deletions(-) diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DummyNotificationShadeWindowController.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DummyNotificationShadeWindowController.java index a4230032858e5..13f2b7ed45db2 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DummyNotificationShadeWindowController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DummyNotificationShadeWindowController.java @@ -23,6 +23,7 @@ import android.view.WindowManager; import com.android.systemui.car.window.SystemUIOverlayWindowController; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dump.DumpManager; +import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.DozeParameters; @@ -49,12 +50,14 @@ public class DummyNotificationShadeWindowController extends NotificationShadeWin DozeParameters dozeParameters, StatusBarStateController statusBarStateController, ConfigurationController configurationController, + KeyguardViewMediator keyguardViewMediator, KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor, DumpManager dumpManager, SystemUIOverlayWindowController overlayWindowController) { super(context, windowManager, activityManager, dozeParameters, statusBarStateController, - configurationController, keyguardBypassController, colorExtractor, dumpManager); + configurationController, keyguardViewMediator, keyguardBypassController, + colorExtractor, dumpManager); mOverlayWindowController = overlayWindowController; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java index 2e4a929ded5b8..5164440c14638 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java @@ -84,6 +84,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, private final boolean mKeyguardScreenRotation; private final long mLockScreenDisplayTimeout; private final Display.Mode mKeyguardDisplayMode; + private final KeyguardViewMediator mKeyguardViewMediator; private final KeyguardBypassController mKeyguardBypassController; private ViewGroup mNotificationShadeView; private LayoutParams mLp; @@ -104,6 +105,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, IActivityManager activityManager, DozeParameters dozeParameters, StatusBarStateController statusBarStateController, ConfigurationController configurationController, + KeyguardViewMediator keyguardViewMediator, KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor, DumpManager dumpManager) { mContext = context; @@ -113,6 +115,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, mDozeParameters = dozeParameters; mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze(); mLpChanged = new LayoutParams(); + mKeyguardViewMediator = keyguardViewMediator; mKeyguardBypassController = keyguardBypassController; mColorExtractor = colorExtractor; dumpManager.registerDumpable(getClass().getName(), this); @@ -202,6 +205,11 @@ public class NotificationShadeWindowController implements Callback, Dumpable, mWindowManager.addView(mNotificationShadeView, mLp); mLpChanged.copyFrom(mLp); onThemeChanged(); + + // Make the state consistent with KeyguardViewMediator#setupLocked during initialization. + if (mKeyguardViewMediator.isShowingAndNotOccluded()) { + setKeyguardShowing(true); + } } public void setNotificationShadeView(ViewGroup view) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index 5b46b7fa4d9ff..15828b41cc7c9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -63,6 +63,7 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.SysuiTestCase; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dump.DumpManager; +import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.QuickStepContract; @@ -135,6 +136,8 @@ public class BubbleControllerTest extends SysuiTestCase { @Mock private SysuiStatusBarStateController mStatusBarStateController; @Mock + private KeyguardViewMediator mKeyguardViewMediator; + @Mock private KeyguardBypassController mKeyguardBypassController; @Mock private FloatingContentCoordinator mFloatingContentCoordinator; @@ -198,8 +201,8 @@ public class BubbleControllerTest extends SysuiTestCase { mNotificationShadeWindowController = new NotificationShadeWindowController(mContext, mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, - mConfigurationController, mKeyguardBypassController, mColorExtractor, - mDumpManager); + mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController, + mColorExtractor, mDumpManager); mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView); mNotificationShadeWindowController.attach(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java index 52c64cc40e79c..b318e45eda869 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java @@ -60,6 +60,7 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.SysuiTestCase; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dump.DumpManager; +import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.FeatureFlags; @@ -132,6 +133,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { @Mock private SysuiStatusBarStateController mStatusBarStateController; @Mock + private KeyguardViewMediator mKeyguardViewMediator; + @Mock private KeyguardBypassController mKeyguardBypassController; @Mock private FloatingContentCoordinator mFloatingContentCoordinator; @@ -194,8 +197,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { // Bubbles get added to status bar window view mNotificationShadeWindowController = new NotificationShadeWindowController(mContext, mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, - mConfigurationController, mKeyguardBypassController, mColorExtractor, - mDumpManager); + mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController, + mColorExtractor, mDumpManager); mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView); mNotificationShadeWindowController.attach(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java index ca6c16f91ad80..8c37cf1514fde 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; +import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static com.google.common.truth.Truth.assertThat; @@ -41,6 +42,7 @@ import com.android.internal.colorextraction.ColorExtractor; import com.android.systemui.SysuiTestCase; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dump.DumpManager; +import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -63,6 +65,7 @@ public class NotificationShadeWindowControllerTest extends SysuiTestCase { @Mock private IActivityManager mActivityManager; @Mock private SysuiStatusBarStateController mStatusBarStateController; @Mock private ConfigurationController mConfigurationController; + @Mock private KeyguardViewMediator mKeyguardViewMediator; @Mock private KeyguardBypassController mKeyguardBypassController; @Mock private SysuiColorExtractor mColorExtractor; @Mock ColorExtractor.GradientColors mGradientColors; @@ -79,8 +82,8 @@ public class NotificationShadeWindowControllerTest extends SysuiTestCase { mNotificationShadeWindowController = new NotificationShadeWindowController(mContext, mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, - mConfigurationController, mKeyguardBypassController, mColorExtractor, - mDumpManager); + mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController, + mColorExtractor, mDumpManager); mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView); mNotificationShadeWindowController.attach(); @@ -119,6 +122,17 @@ public class NotificationShadeWindowControllerTest extends SysuiTestCase { mNotificationShadeWindowController.setForcePluginOpen(true); } + @Test + public void attach_visibleWithWallpaper() { + clearInvocations(mWindowManager); + when(mKeyguardViewMediator.isShowingAndNotOccluded()).thenReturn(true); + mNotificationShadeWindowController.attach(); + + verify(mNotificationShadeWindowView).setVisibility(eq(View.VISIBLE)); + verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture()); + assertThat((mLayoutParameters.getValue().flags & FLAG_SHOW_WALLPAPER) != 0).isTrue(); + } + @Test public void setBackgroundBlurRadius_expandedWithBlurs() { mNotificationShadeWindowController.setBackgroundBlurRadius(10); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index c56440785bba5..6998adac57602 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3706,12 +3706,12 @@ class DisplayContent extends WindowContainer { - boolean isVisible = w.mViewVisibility == View.VISIBLE && !w.mObscured; - boolean hasDrawn = w.isDrawnLw() && w.hasDrawnLw(); - if (isVisible && !hasDrawn) { + final boolean isVisible = w.isVisible() && !w.mObscured; + final boolean isDrawn = w.isDrawnLw(); + if (isVisible && !isDrawn) { return true; } - if (hasDrawn) { + if (isDrawn) { switch (w.mAttrs.type) { case TYPE_BOOT_PROGRESS: case TYPE_BASE_APPLICATION: 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 ddb186a1d2da5..98e767a0a4f69 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -482,12 +482,17 @@ public class DisplayContentTests extends WindowTestsBase { final DisplayContent defaultDisplay = mWm.getDefaultDisplayContentLocked(); final WindowState[] windows = createNotDrawnWindowsOn(defaultDisplay, TYPE_WALLPAPER, TYPE_APPLICATION); + final WindowState wallpaper = windows[0]; + assertTrue(wallpaper.mIsWallpaper); + // By default WindowState#mWallpaperVisible is false. + assertFalse(wallpaper.isVisible()); // Verify waiting for windows to be drawn. assertTrue(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot()); - // Verify not waiting for drawn windows. - makeWindowsDrawnState(windows, WindowStateAnimator.HAS_DRAWN); + // Verify not waiting for drawn window and invisible wallpaper. + setDrawnState(WindowStateAnimator.READY_TO_SHOW, wallpaper); + setDrawnState(WindowStateAnimator.HAS_DRAWN, windows[1]); assertFalse(defaultDisplay.shouldWaitForSystemDecorWindowsOnBoot()); } @@ -508,26 +513,10 @@ public class DisplayContentTests extends WindowTestsBase { assertTrue(secondaryDisplay.shouldWaitForSystemDecorWindowsOnBoot()); // Verify not waiting for drawn windows on display with system decorations. - makeWindowsDrawnState(windows, WindowStateAnimator.HAS_DRAWN); + setDrawnState(WindowStateAnimator.HAS_DRAWN, windows); 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++) { @@ -538,9 +527,9 @@ public class DisplayContentTests extends WindowTestsBase { return windows; } - private static void makeWindowsDrawnState(WindowState[] windows, int state) { + private static void setDrawnState(int state, WindowState... windows) { for (WindowState window : windows) { - window.mHasSurface = true; + window.mHasSurface = state != WindowStateAnimator.NO_SURFACE; window.mWinAnimator.mDrawState = state; } }