From 97a0b1d50e4a3b5952c00c25b8c146f89695c509 Mon Sep 17 00:00:00 2001 From: Lucas Silva Date: Wed, 16 Mar 2022 18:04:10 -0400 Subject: [PATCH] Implement bouncer fade-in animation over dreams. This updates the scrim logic to properly fade in the bouncer over dreams. Bug: 220307939 Test: locally on device Test: atest ScrimControllerTest Change-Id: I50a6d4681bc2a9cdc51dd73d404779ed58257c8f --- .../statusbar/phone/CentralSurfaces.java | 11 ++++++ .../statusbar/phone/ScrimController.java | 37 ++++++++++++++++++- .../systemui/statusbar/phone/ScrimState.java | 19 ++++++++++ .../phone/StatusBarKeyguardViewManager.java | 11 ++++++ .../statusbar/phone/ScrimControllerTest.java | 24 +++++++++++- 5 files changed, 99 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index 1932680de2faf..a2d22bc365899 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -3745,6 +3745,14 @@ public class CentralSurfaces extends CoreStartable implements mTransitionToFullShadeProgress = transitionToFullShadeProgress; } + /** + * Sets the amount of progress to the bouncer being fully hidden/visible. 1 means the bouncer + * is fully hidden, while 0 means the bouncer is visible. + */ + public void setBouncerHiddenFraction(float expansion) { + mScrimController.setBouncerHiddenFraction(expansion); + } + @VisibleForTesting public void updateScrimController() { Trace.beginSection("CentralSurfaces#updateScrimController"); @@ -3797,6 +3805,8 @@ public class CentralSurfaces extends CoreStartable implements mScrimController.transitionTo(ScrimState.AOD); } else if (mKeyguardStateController.isShowing() && !isOccluded() && !unlocking) { mScrimController.transitionTo(ScrimState.KEYGUARD); + } else if (mKeyguardStateController.isShowing() && mKeyguardUpdateMonitor.isDreaming()) { + mScrimController.transitionTo(ScrimState.DREAMING); } else { mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); } @@ -4203,6 +4213,7 @@ public class CentralSurfaces extends CoreStartable implements new KeyguardUpdateMonitorCallback() { @Override public void onDreamingStateChanged(boolean dreaming) { + updateScrimController(); if (dreaming) { maybeEscalateHeadsUp(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 7e22510c99afe..841abb0defeef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -137,6 +137,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump */ private boolean mUnOcclusionAnimationRunning; + /** + * The percentage of the bouncer which is hidden. If 1, the bouncer is completely hidden. If + * 0, the bouncer is visible. + */ + @FloatRange(from = 0, to = 1) + private float mBouncerHiddenFraction = KeyguardBouncer.EXPANSION_HIDDEN; + /** * Set whether an unocclusion animation is currently running on the notification panel. Used * to avoid bright flickers of the notification scrim. @@ -586,6 +593,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump boolean relevantState = (mState == ScrimState.UNLOCKED || mState == ScrimState.KEYGUARD + || mState == ScrimState.DREAMING || mState == ScrimState.SHADE_LOCKED || mState == ScrimState.PULSING); if (!(relevantState && mExpansionAffectsAlpha) || mAnimatingPanelExpansionOnUnlock) { @@ -676,6 +684,21 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump } } + /** + * Updates the percentage of the bouncer which is hidden. + */ + public void setBouncerHiddenFraction(@FloatRange(from = 0, to = 1) float bouncerHiddenAmount) { + if (mBouncerHiddenFraction == bouncerHiddenAmount) { + return; + } + mBouncerHiddenFraction = bouncerHiddenAmount; + if (mState == ScrimState.DREAMING) { + // Only the dreaming state requires this for the scrim calculation, so we should + // only trigger an update if dreaming. + applyAndDispatchState(); + } + } + /** * If QS and notification scrims should not overlap, and should be clipped to each other's * bounds instead. @@ -741,7 +764,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump return; } - if (mState == ScrimState.UNLOCKED) { + if (mState == ScrimState.UNLOCKED || mState == ScrimState.DREAMING) { // Darken scrim as you pull down the shade when unlocked, unless the shade is expanding // because we're doing the screen off animation OR the shade is collapsing because // we're playing the unlock animation @@ -759,8 +782,20 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump mNotificationsAlpha = MathUtils.constrainedMap(0f, 1f, 0.3f, 0.75f, mPanelExpansionFraction); } + mBehindTint = mState.getBehindTint(); mInFrontAlpha = 0; } + + if (mBouncerHiddenFraction != KeyguardBouncer.EXPANSION_HIDDEN) { + final float interpolatedFraction = + BouncerPanelExpansionCalculator.getBackScrimScaledExpansion( + mBouncerHiddenFraction); + mBehindAlpha = MathUtils.lerp(mDefaultScrimAlpha, mBehindAlpha, + interpolatedFraction); + mBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(), + mBehindTint, + interpolatedFraction); + } } else if (mState == ScrimState.AUTH_SCRIMMED_SHADE) { float behindFraction = getInterpolatedFraction(); behindFraction = (float) Math.pow(behindFraction, 0.8f); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java index 902887027667f..47b705845fceb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java @@ -258,6 +258,25 @@ public enum ScrimState { mBlankScreen = true; } + if (mClipQsScrim) { + updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK); + } + } + }, + + DREAMING { + @Override + public void prepare(ScrimState previousState) { + mFrontTint = Color.TRANSPARENT; + mBehindTint = Color.BLACK; + mNotifTint = mClipQsScrim ? Color.BLACK : Color.TRANSPARENT; + + mFrontAlpha = 0; + mBehindAlpha = mClipQsScrim ? 1 : 0; + mNotifAlpha = 0; + + mBlankScreen = false; + if (mClipQsScrim) { updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index b8478855e8ff1..ff352e42da2da 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -121,9 +121,13 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private final FoldAodAnimationController mFoldAodAnimationController; private KeyguardMessageAreaController mKeyguardMessageAreaController; private final Lazy mShadeController; + private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() { + private boolean mBouncerAnimating; + @Override public void onFullyShown() { + mBouncerAnimating = false; updateStates(); mCentralSurfaces.wakeUpIfDozing(SystemClock.uptimeMillis(), mCentralSurfaces.getBouncerContainer(), "BOUNCER_VISIBLE"); @@ -131,16 +135,19 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public void onStartingToHide() { + mBouncerAnimating = true; updateStates(); } @Override public void onStartingToShow() { + mBouncerAnimating = true; updateStates(); } @Override public void onFullyHidden() { + mBouncerAnimating = false; } @Override @@ -148,6 +155,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb if (mAlternateAuthInterceptor != null) { mAlternateAuthInterceptor.setBouncerExpansionChanged(expansion); } + if (mBouncerAnimating) { + mCentralSurfaces.setBouncerHiddenFraction(expansion); + } updateStates(); } @@ -155,6 +165,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void onVisibilityChanged(boolean isVisible) { if (!isVisible) { cancelPostAuthActions(); + mCentralSurfaces.setBouncerHiddenFraction(KeyguardBouncer.EXPANSION_HIDDEN); } if (mAlternateAuthInterceptor != null) { mAlternateAuthInterceptor.onBouncerVisibilityChanged(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index 134ad4b9d0fbf..3892ba77b76f4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -1078,8 +1078,9 @@ public class ScrimControllerTest extends SysuiTestCase { ScrimState.OFF, ScrimState.AOD, ScrimState.PULSING)); HashSet regularStates = new HashSet<>(Arrays.asList( ScrimState.UNINITIALIZED, ScrimState.KEYGUARD, ScrimState.BOUNCER, - ScrimState.BOUNCER_SCRIMMED, ScrimState.BRIGHTNESS_MIRROR, ScrimState.UNLOCKED, - ScrimState.SHADE_LOCKED, ScrimState.AUTH_SCRIMMED, ScrimState.AUTH_SCRIMMED_SHADE)); + ScrimState.DREAMING, ScrimState.BOUNCER_SCRIMMED, ScrimState.BRIGHTNESS_MIRROR, + ScrimState.UNLOCKED, ScrimState.SHADE_LOCKED, ScrimState.AUTH_SCRIMMED, + ScrimState.AUTH_SCRIMMED_SHADE)); for (ScrimState state : ScrimState.values()) { if (!lowPowerModeStates.contains(state) && !regularStates.contains(state)) { @@ -1323,6 +1324,25 @@ public class ScrimControllerTest extends SysuiTestCase { assertThat(mScrimInFront.getTranslationY()).isEqualTo(0); } + @Test + public void transitionToDreaming() { + mScrimController.setRawPanelExpansionFraction(0f); + mScrimController.setBouncerHiddenFraction(KeyguardBouncer.EXPANSION_HIDDEN); + mScrimController.transitionTo(ScrimState.DREAMING); + finishAnimationsImmediately(); + + assertScrimAlpha(Map.of( + mScrimInFront, TRANSPARENT, + mNotificationsScrim, TRANSPARENT, + mScrimBehind, TRANSPARENT)); + + assertScrimTinted(Map.of( + mScrimInFront, false, + mScrimBehind, true, + mNotificationsScrim, false + )); + } + private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) { mScrimController.setRawPanelExpansionFraction(expansion); finishAnimationsImmediately();