From d63ed921ea9f9df7b1133c79bbcf574c94e027cb Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Tue, 18 Jan 2022 18:05:44 +0000 Subject: [PATCH] [Fold to AOD animation] part 3: do not collapse notification shade and delay doze display mode Fixes a few issues with fold to AOD animation: 1) Sometimes when folding a foldable device and showing AOD we see the underlying app (launcher/wallpaper) for 1-2 seconds. It happens because the system sends 'hide system dialogs' broadcast when starting dreaming which collapses and hides the notification shade. We need the notification shade in expanded state to show the scrims and AOD UI. Added ignoring of collapsing when fold to AOD animation is hapenning. 2) When folding from unlocked state the animation was playing with reduced FPS (the display was going into doze mode). Added delay for going into doze mode when animation is about to happen. Bug: 202844967 Test: fold/unfold when locked/unlocked Test: power button screen off from locked/unlocked states Change-Id: I2af5e4965ef7db234a1931ca442640c96000ec56 --- .../systemui/doze/DozeScreenState.java | 22 ++++++++++++++----- .../systemui/statusbar/LightRevealScrim.kt | 3 ++- .../statusbar/phone/DozeParameters.java | 8 +++++++ .../phone/ScreenOffAnimationController.kt | 9 ++++++++ .../statusbar/phone/ShadeControllerImpl.java | 3 ++- .../systemui/statusbar/phone/StatusBar.java | 14 ++++++++++-- .../UnlockedScreenOffAnimationController.kt | 3 +++ .../unfold/FoldAodAnimationController.kt | 2 ++ .../systemui/doze/DozeScreenStateTest.java | 4 ++-- 9 files changed, 57 insertions(+), 11 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java index 36319380ad50d..63d4d6becc27e 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java @@ -163,16 +163,12 @@ public class DozeScreenState implements DozeMachine.Part { // Delay screen state transitions even longer while animations are running. boolean shouldDelayTransitionEnteringDoze = newState == DOZE_AOD - && mParameters.shouldControlScreenOff() && !turningOn; + && mParameters.shouldDelayDisplayDozeTransition() && !turningOn; // Delay screen state transition longer if UDFPS is actively authenticating a fp boolean shouldDelayTransitionForUDFPS = newState == DOZE_AOD && mUdfpsController != null && mUdfpsController.isFingerDown(); - if (shouldDelayTransitionEnteringDoze || shouldDelayTransitionForUDFPS) { - mWakeLock.setAcquired(true); - } - if (!messagePending) { if (DEBUG) { Log.d(TAG, "Display state changed to " + screenState + " delayed by " @@ -180,6 +176,18 @@ public class DozeScreenState implements DozeMachine.Part { } if (shouldDelayTransitionEnteringDoze) { + if (justInitialized) { + // If we are delaying transitioning to doze and the display was not + // turned on we set it to 'on' first to make sure that the animation + // is visible before eventually moving it to doze state. + // The display might be off at this point for example on foldable devices + // when we switch displays and go to doze at the same time. + applyScreenState(Display.STATE_ON); + + // Restore pending screen state as it gets cleared by 'applyScreenState' + mPendingScreenState = screenState; + } + mHandler.postDelayed(mApplyPendingScreenState, ENTER_DOZE_DELAY); } else if (shouldDelayTransitionForUDFPS) { mDozeLog.traceDisplayStateDelayedByUdfps(mPendingScreenState); @@ -190,6 +198,10 @@ public class DozeScreenState implements DozeMachine.Part { } else if (DEBUG) { Log.d(TAG, "Pending display state change to " + screenState); } + + if (shouldDelayTransitionEnteringDoze || shouldDelayTransitionForUDFPS) { + mWakeLock.setAcquired(true); + } } else if (turningOff) { mDozeHost.prepareForGentleSleep(() -> applyScreenState(screenState)); } else { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt index c8115e2c197a2..9a932bae833e8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt @@ -355,7 +355,8 @@ class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context, } override fun onDraw(canvas: Canvas?) { - if (canvas == null || revealGradientWidth <= 0 || revealGradientHeight <= 0) { + if (canvas == null || revealGradientWidth <= 0 || revealGradientHeight <= 0 + || revealAmount == 0f) { if (revealAmount < 1f) { canvas?.drawColor(revealGradientEndColor) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java index 1b42b58a55aa8..d610b372702df 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -304,6 +304,14 @@ public class DozeParameters implements return mScreenOffAnimationController.shouldAnimateDozingChange(); } + /** + * When this method returns true then moving display state to power save mode will be + * delayed for a few seconds. This might be useful to play animations without reducing FPS. + */ + public boolean shouldDelayDisplayDozeTransition() { + return mScreenOffAnimationController.shouldDelayDisplayDozeTransition(); + } + /** * Whether we're capable of controlling the screen off animation if we want to. This isn't * possible if AOD isn't even enabled or if the flag is disabled. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenOffAnimationController.kt index e806ca0d9005d..091831f360222 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenOffAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenOffAnimationController.kt @@ -179,6 +179,14 @@ class ScreenOffAnimationController @Inject constructor( fun shouldAnimateDozingChange(): Boolean = animations.all { it.shouldAnimateDozingChange() } + /** + * Returns true when moving display state to power save mode should be + * delayed for a few seconds. This might be useful to play animations in full quality, + * without reducing FPS. + */ + fun shouldDelayDisplayDozeTransition(): Boolean = + animations.any { it.shouldDelayDisplayDozeTransition() } + /** * Return true to animate large <-> small clock transition */ @@ -207,6 +215,7 @@ interface ScreenOffAnimation { fun shouldHideScrimOnWakeUp(): Boolean = false fun overrideNotificationsDozeAmount(): Boolean = false fun shouldShowAodIconsWhenShade(): Boolean = false + fun shouldDelayDisplayDozeTransition(): Boolean = false fun shouldAnimateAodIcons(): Boolean = true fun shouldAnimateDozingChange(): Boolean = true fun shouldAnimateClockChange(): Boolean = true diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java index f8b0535b7ec7d..72237b1ca6c6c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java @@ -123,7 +123,8 @@ public class ShadeControllerImpl implements ShadeController { + " canPanelBeCollapsed(): " + getNotificationPanelViewController().canPanelBeCollapsed()); if (getNotificationShadeWindowView() != null - && getNotificationPanelViewController().canPanelBeCollapsed()) { + && getNotificationPanelViewController().canPanelBeCollapsed() + && (flags & CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL) == 0) { // release focus immediately to kick off focus change transition mNotificationShadeWindowController.setNotificationShadeFocusable(false); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index fdced64bf1c0c..07ae33c42c213 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -268,6 +268,7 @@ public class StatusBar extends CoreStartable implements // Should match the values in PhoneWindowManager public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; + public static final String SYSTEM_DIALOG_REASON_DREAM = "dream"; static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot"; private static final String BANNER_ACTION_CANCEL = @@ -2635,8 +2636,17 @@ public class StatusBar extends CoreStartable implements if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) { int flags = CommandQueue.FLAG_EXCLUDE_NONE; String reason = intent.getStringExtra("reason"); - if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) { - flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL; + if (reason != null) { + if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) { + flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL; + } + // Do not collapse notifications when starting dreaming if the notifications + // shade is used for the screen off animation. It might require expanded + // state for the scrims to be visible + if (reason.equals(SYSTEM_DIALOG_REASON_DREAM) + && mScreenOffAnimationController.shouldExpandNotifications()) { + flags |= CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL; + } } mShadeController.animateCollapsePanels(flags); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt index ea0dd72d673f5..6746b3e8883a9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt @@ -290,6 +290,9 @@ class UnlockedScreenOffAnimationController @Inject constructor( return true } + override fun shouldDelayDisplayDozeTransition(): Boolean = + dozeParameters.get().shouldControlUnlockedScreenOff() + fun addCallback(callback: Callback) { callbacks.add(callback) } diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt index 4f037a0f1acec..aaf35afe936d9 100644 --- a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt @@ -136,6 +136,8 @@ constructor( override fun shouldAnimateClockChange(): Boolean = !isAnimationPlaying() + override fun shouldDelayDisplayDozeTransition(): Boolean = shouldPlayAnimation() + /** Called when AOD status is changed */ override fun onAlwaysOnChanged(alwaysOn: Boolean) { alwaysOnEnabled = alwaysOn diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java index 3e19cc436dca6..cdffaecadd77a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java @@ -192,7 +192,7 @@ public class DozeScreenStateTest extends SysuiTestCase { public void test_holdsWakeLockWhenGoingToLowPowerDelayed() { // Transition to low power mode will be delayed to let // animations play at 60 fps. - when(mDozeParameters.shouldControlScreenOff()).thenReturn(true); + when(mDozeParameters.shouldDelayDisplayDozeTransition()).thenReturn(true); mHandlerFake.setMode(QUEUEING); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); @@ -209,7 +209,7 @@ public class DozeScreenStateTest extends SysuiTestCase { public void test_releasesWakeLock_abortingLowPowerDelayed() { // Transition to low power mode will be delayed to let // animations play at 60 fps. - when(mDozeParameters.shouldControlScreenOff()).thenReturn(true); + when(mDozeParameters.shouldDelayDisplayDozeTransition()).thenReturn(true); mHandlerFake.setMode(QUEUEING); mScreen.transitionTo(UNINITIALIZED, INITIALIZED);