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

Commit 693dc3e1 authored by Lucas Dupin's avatar Lucas Dupin Committed by Automerger Merge Worker
Browse files

Merge "Revealing the light reveal scrim only during keyguard exit animation"...

Merge "Revealing the light reveal scrim only during keyguard exit animation" into sc-dev am: 5837f7b4 am: 130b0643

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15738322

Change-Id: I359d1ef366c0f11b6d4e4c4eb96c86d7914678f8
parents 3062b3cc 130b0643
Loading
Loading
Loading
Loading
+50 −12
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package com.android.systemui.biometrics
package com.android.systemui.biometrics


import android.animation.ValueAnimator
import android.content.Context
import android.content.Context
import android.content.res.Configuration
import android.content.res.Configuration
import android.graphics.PointF
import android.graphics.PointF
@@ -26,6 +27,8 @@ import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.settingslib.Utils
import com.android.settingslib.Utils
import com.android.systemui.R
import com.android.systemui.R
import com.android.systemui.animation.Interpolators
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.statusbar.CircleReveal
import com.android.systemui.statusbar.CircleReveal
import com.android.systemui.statusbar.LightRevealEffect
import com.android.systemui.statusbar.LightRevealEffect
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.NotificationShadeWindowController
@@ -36,12 +39,15 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.StatusBar
import com.android.systemui.statusbar.phone.StatusBar
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.ViewController
import com.android.systemui.util.ViewController
import java.io.PrintWriter
import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Provider
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.plugins.statusbar.StatusBarStateController


private const val WAKE_AND_UNLOCK_FADE_DURATION = 180L

/***
/***
 * Controls the ripple effect that shows when authentication is successful.
 * Controls the ripple effect that shows when authentication is successful.
 * The ripple uses the accent color of the current theme.
 * The ripple uses the accent color of the current theme.
@@ -53,6 +59,8 @@ class AuthRippleController @Inject constructor(
    private val authController: AuthController,
    private val authController: AuthController,
    private val configurationController: ConfigurationController,
    private val configurationController: ConfigurationController,
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    private val keyguardStateController: KeyguardStateController,
    private val wakefulnessLifecycle: WakefulnessLifecycle,
    private val commandRegistry: CommandRegistry,
    private val commandRegistry: CommandRegistry,
    private val notificationShadeWindowController: NotificationShadeWindowController,
    private val notificationShadeWindowController: NotificationShadeWindowController,
    private val bypassController: KeyguardBypassController,
    private val bypassController: KeyguardBypassController,
@@ -60,7 +68,11 @@ class AuthRippleController @Inject constructor(
    private val udfpsControllerProvider: Provider<UdfpsController>,
    private val udfpsControllerProvider: Provider<UdfpsController>,
    private val statusBarStateController: StatusBarStateController,
    private val statusBarStateController: StatusBarStateController,
    rippleView: AuthRippleView?
    rippleView: AuthRippleView?
) : ViewController<AuthRippleView>(rippleView) {
) : ViewController<AuthRippleView>(rippleView), KeyguardStateController.Callback,
    WakefulnessLifecycle.Observer {

    @VisibleForTesting
    internal var startLightRevealScrimOnKeyguardFadingAway = false
    var fingerprintSensorLocation: PointF? = null
    var fingerprintSensorLocation: PointF? = null
    private var faceSensorLocation: PointF? = null
    private var faceSensorLocation: PointF? = null
    private var circleReveal: LightRevealEffect? = null
    private var circleReveal: LightRevealEffect? = null
@@ -87,6 +99,8 @@ class AuthRippleController @Inject constructor(
        udfpsController?.addCallback(udfpsControllerCallback)
        udfpsController?.addCallback(udfpsControllerCallback)
        configurationController.addCallback(configurationChangedListener)
        configurationController.addCallback(configurationChangedListener)
        keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
        keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
        keyguardStateController.addCallback(this)
        wakefulnessLifecycle.addObserver(this)
        commandRegistry.registerCommand("auth-ripple") { AuthRippleCommand() }
        commandRegistry.registerCommand("auth-ripple") { AuthRippleCommand() }
    }
    }


@@ -96,6 +110,8 @@ class AuthRippleController @Inject constructor(
        authController.removeCallback(authControllerCallback)
        authController.removeCallback(authControllerCallback)
        keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
        keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
        configurationController.removeCallback(configurationChangedListener)
        configurationController.removeCallback(configurationChangedListener)
        keyguardStateController.removeCallback(this)
        wakefulnessLifecycle.removeObserver(this)
        commandRegistry.unregisterCommand("auth-ripple")
        commandRegistry.unregisterCommand("auth-ripple")


        notificationShadeWindowController.setForcePluginOpen(false, this)
        notificationShadeWindowController.setForcePluginOpen(false, this)
@@ -123,30 +139,48 @@ class AuthRippleController @Inject constructor(


    private fun showUnlockedRipple() {
    private fun showUnlockedRipple() {
        notificationShadeWindowController.setForcePluginOpen(true, this)
        notificationShadeWindowController.setForcePluginOpen(true, this)
        val biometricUnlockMode = biometricUnlockController.mode
        val useCircleReveal = circleReveal != null && biometricUnlockController.isWakeAndUnlock
        val useCircleReveal = circleReveal != null &&
            (biometricUnlockMode == BiometricUnlockController.MODE_WAKE_AND_UNLOCK ||
                biometricUnlockMode == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING ||
                biometricUnlockMode == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM)
        val lightRevealScrim = statusBar.lightRevealScrim
        val lightRevealScrim = statusBar.lightRevealScrim
        if (useCircleReveal) {
        if (useCircleReveal) {
            lightRevealScrim?.revealEffect = circleReveal!!
            lightRevealScrim?.revealEffect = circleReveal!!
            startLightRevealScrimOnKeyguardFadingAway = true
        }
        }


        mView.startUnlockedRipple(
        mView.startUnlockedRipple(
            /* end runnable */
            /* end runnable */
            Runnable {
            Runnable {
                notificationShadeWindowController.setForcePluginOpen(false, this)
                notificationShadeWindowController.setForcePluginOpen(false, this)
            },
            /* circleReveal */
            if (useCircleReveal) {
                lightRevealScrim
            } else {
                null
            }
            }
        )
        )
    }
    }


    override fun onKeyguardFadingAwayChanged() {
        if (keyguardStateController.isKeyguardFadingAway) {
            val lightRevealScrim = statusBar.lightRevealScrim
            if (startLightRevealScrimOnKeyguardFadingAway && lightRevealScrim != null) {
                val revealAnimator = ValueAnimator.ofFloat(.1f, 1f).apply {
                    interpolator = Interpolators.LINEAR_OUT_SLOW_IN
                    duration = RIPPLE_ANIMATION_DURATION
                    startDelay = keyguardStateController.keyguardFadingAwayDelay
                    addUpdateListener { animator ->
                        if (lightRevealScrim.revealEffect != circleReveal) {
                            // if the something else took over the reveal, let's do nothing.
                            return@addUpdateListener
                        }
                        lightRevealScrim.revealAmount = animator.animatedValue as Float
                    }
                }
                revealAnimator.start()
                startLightRevealScrimOnKeyguardFadingAway = false
            }
        }
    }

    override fun onStartedGoingToSleep() {
        // reset the light reveal start in case we were pending an unlock
        startLightRevealScrimOnKeyguardFadingAway = false
    }

    fun updateSensorLocation() {
    fun updateSensorLocation() {
        fingerprintSensorLocation = authController.fingerprintSensorLocation
        fingerprintSensorLocation = authController.fingerprintSensorLocation
        faceSensorLocation = authController.faceAuthSensorLocation
        faceSensorLocation = authController.faceAuthSensorLocation
@@ -318,4 +352,8 @@ class AuthRippleController @Inject constructor(
            help(pw)
            help(pw)
        }
        }
    }
    }

    companion object {
        const val RIPPLE_ANIMATION_DURATION: Long = 1533
    }
}
}
+2 −14
Original line number Original line Diff line number Diff line
@@ -26,13 +26,10 @@ import android.graphics.PointF
import android.util.AttributeSet
import android.util.AttributeSet
import android.view.View
import android.view.View
import android.view.animation.PathInterpolator
import android.view.animation.PathInterpolator
import com.android.internal.R.attr.interpolator
import com.android.internal.graphics.ColorUtils
import com.android.internal.graphics.ColorUtils
import com.android.systemui.animation.Interpolators
import com.android.systemui.animation.Interpolators
import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.charging.RippleShader
import com.android.systemui.statusbar.charging.RippleShader


private const val RIPPLE_ANIMATION_DURATION: Long = 1533
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f


/**
/**
@@ -250,7 +247,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
    /**
    /**
     * Ripple that bursts outwards from the position of the sensor to the edges of the screen
     * Ripple that bursts outwards from the position of the sensor to the edges of the screen
     */
     */
    fun startUnlockedRipple(onAnimationEnd: Runnable?, lightReveal: LightRevealScrim?) {
    fun startUnlockedRipple(onAnimationEnd: Runnable?) {
        if (unlockedRippleInProgress) {
        if (unlockedRippleInProgress) {
            return // Ignore if ripple effect is already playing
            return // Ignore if ripple effect is already playing
        }
        }
@@ -266,7 +263,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at


        val rippleAnimator = ValueAnimator.ofFloat(rippleStart, 1f).apply {
        val rippleAnimator = ValueAnimator.ofFloat(rippleStart, 1f).apply {
            interpolator = Interpolators.LINEAR_OUT_SLOW_IN
            interpolator = Interpolators.LINEAR_OUT_SLOW_IN
            duration = RIPPLE_ANIMATION_DURATION
            duration = AuthRippleController.RIPPLE_ANIMATION_DURATION
            addUpdateListener { animator ->
            addUpdateListener { animator ->
                val now = animator.currentPlayTime
                val now = animator.currentPlayTime
                rippleShader.progress = animator.animatedValue as Float
                rippleShader.progress = animator.animatedValue as Float
@@ -276,14 +273,6 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
            }
            }
        }
        }


        val revealAnimator = ValueAnimator.ofFloat(.1f, 1f).apply {
            interpolator = rippleAnimator.interpolator
            duration = rippleAnimator.duration
            addUpdateListener { animator ->
                lightReveal?.revealAmount = animator.animatedValue as Float
            }
        }

        val alphaInAnimator = ValueAnimator.ofInt(0, 255).apply {
        val alphaInAnimator = ValueAnimator.ofInt(0, 255).apply {
            duration = alphaDuration
            duration = alphaDuration
            addUpdateListener { animator ->
            addUpdateListener { animator ->
@@ -298,7 +287,6 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
        val animatorSet = AnimatorSet().apply {
        val animatorSet = AnimatorSet().apply {
            playTogether(
            playTogether(
                rippleAnimator,
                rippleAnimator,
                revealAnimator,
                alphaInAnimator
                alphaInAnimator
            )
            )
            addListener(object : AnimatorListenerAdapter() {
            addListener(object : AnimatorListenerAdapter() {
+14 −3
Original line number Original line Diff line number Diff line
@@ -818,6 +818,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable,


    private final KeyguardStateController mKeyguardStateController;
    private final KeyguardStateController mKeyguardStateController;
    private final Lazy<KeyguardUnlockAnimationController> mKeyguardUnlockAnimationControllerLazy;
    private final Lazy<KeyguardUnlockAnimationController> mKeyguardUnlockAnimationControllerLazy;
    private boolean mWallpaperSupportsAmbientMode;


    /**
    /**
     * Injected constructor. See {@link KeyguardModule}.
     * Injected constructor. See {@link KeyguardModule}.
@@ -2089,13 +2090,14 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable,


            int flags = 0;
            int flags = 0;
            if (mKeyguardViewControllerLazy.get().shouldDisableWindowAnimationsForUnlock()
            if (mKeyguardViewControllerLazy.get().shouldDisableWindowAnimationsForUnlock()
                    || (mWakeAndUnlocking && !mPulsing)
                    || mWakeAndUnlocking && !mWallpaperSupportsAmbientMode) {
                    || isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe()) {
                flags |= WindowManagerPolicyConstants
                flags |= WindowManagerPolicyConstants
                        .KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
                        .KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
            }
            }
            if (mKeyguardViewControllerLazy.get().isGoingToNotificationShade()
            if (mKeyguardViewControllerLazy.get().isGoingToNotificationShade()
                    || (mWakeAndUnlocking && mPulsing)) {
                    || mWakeAndUnlocking && mWallpaperSupportsAmbientMode) {
                // When the wallpaper supports ambient mode, the scrim isn't fully opaque during
                // wake and unlock and we should fade in the app on top of the wallpaper
                flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
                flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
            }
            }
            if (mKeyguardViewControllerLazy.get().isUnlockWithWallpaper()) {
            if (mKeyguardViewControllerLazy.get().isUnlockWithWallpaper()) {
@@ -2784,6 +2786,15 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable,
        mPulsing = pulsing;
        mPulsing = pulsing;
    }
    }


    /**
     * Set if the wallpaper supports ambient mode. This is used to trigger the right animation.
     * In case it does support it, we have to fade in the incoming app, otherwise we'll reveal it
     * with the light reveal scrim.
     */
    public void setWallpaperSupportsAmbientMode(boolean supportsAmbientMode) {
        mWallpaperSupportsAmbientMode = supportsAmbientMode;
    }

    private static class StartKeyguardExitAnimParams {
    private static class StartKeyguardExitAnimParams {


        @WindowManager.TransitionOldType int mTransit;
        @WindowManager.TransitionOldType int mTransit;
+3 −1
Original line number Original line Diff line number Diff line
@@ -592,6 +592,7 @@ public class StatusBar extends SystemUI implements DemoMode,


            mNotificationShadeWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
            mNotificationShadeWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
            mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
            mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
            mKeyguardViewMediator.setWallpaperSupportsAmbientMode(supportsAmbientMode);
        }
        }
    };
    };


@@ -3924,7 +3925,8 @@ public class StatusBar extends SystemUI implements DemoMode,
    @Override
    @Override
    public void onDozeAmountChanged(float linear, float eased) {
    public void onDozeAmountChanged(float linear, float eased) {
        if (mFeatureFlags.useNewLockscreenAnimations()
        if (mFeatureFlags.useNewLockscreenAnimations()
                && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
                && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)
                && !mBiometricUnlockController.isWakeAndUnlock()) {
            mLightRevealScrim.setRevealAmount(1f - linear);
            mLightRevealScrim.setRevealAmount(1f - linear);
        }
        }
    }
    }
+51 −7
Original line number Original line Diff line number Diff line
@@ -19,17 +19,23 @@ package com.android.systemui.biometrics
import android.graphics.PointF
import android.graphics.PointF
import android.hardware.biometrics.BiometricSourceType
import android.hardware.biometrics.BiometricSourceType
import android.testing.AndroidTestingRunner
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.StatusBar
import com.android.systemui.statusbar.phone.StatusBar
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Before
import org.junit.Test
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runner.RunWith
@@ -55,12 +61,15 @@ class AuthRippleControllerTest : SysuiTestCase() {
    @Mock private lateinit var configurationController: ConfigurationController
    @Mock private lateinit var configurationController: ConfigurationController
    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
    @Mock private lateinit var authController: AuthController
    @Mock private lateinit var authController: AuthController
    @Mock private lateinit var keyguardStateController: KeyguardStateController
    @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
    @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
    @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
    @Mock private lateinit var bypassController: KeyguardBypassController
    @Mock private lateinit var bypassController: KeyguardBypassController
    @Mock private lateinit var biometricUnlockController: BiometricUnlockController
    @Mock private lateinit var biometricUnlockController: BiometricUnlockController
    @Mock private lateinit var udfpsControllerProvider: Provider<UdfpsController>
    @Mock private lateinit var udfpsControllerProvider: Provider<UdfpsController>
    @Mock private lateinit var udfpsController: UdfpsController
    @Mock private lateinit var udfpsController: UdfpsController
    @Mock private lateinit var statusBarStateController: StatusBarStateController
    @Mock private lateinit var statusBarStateController: StatusBarStateController
    @Mock private lateinit var lightRevealScrim: LightRevealScrim


    @Before
    @Before
    fun setUp() {
    fun setUp() {
@@ -73,6 +82,8 @@ class AuthRippleControllerTest : SysuiTestCase() {
            authController,
            authController,
            configurationController,
            configurationController,
            keyguardUpdateMonitor,
            keyguardUpdateMonitor,
            keyguardStateController,
            wakefulnessLifecycle,
            commandRegistry,
            commandRegistry,
            notificationShadeWindowController,
            notificationShadeWindowController,
            bypassController,
            bypassController,
@@ -82,6 +93,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
            rippleView
            rippleView
        )
        )
        controller.init()
        controller.init()
        `when`(statusBar.lightRevealScrim).thenReturn(lightRevealScrim)
    }
    }


    @Test
    @Test
@@ -103,7 +115,7 @@ class AuthRippleControllerTest : SysuiTestCase() {


        // THEN update sensor location and show ripple
        // THEN update sensor location and show ripple
        verify(rippleView).setSensorLocation(fpsLocation)
        verify(rippleView).setSensorLocation(fpsLocation)
        verify(rippleView).startUnlockedRipple(any(), any())
        verify(rippleView).startUnlockedRipple(any())
    }
    }


    @Test
    @Test
@@ -124,7 +136,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
            false /* isStrongBiometric */)
            false /* isStrongBiometric */)


        // THEN no ripple
        // THEN no ripple
        verify(rippleView, never()).startUnlockedRipple(any(), any())
        verify(rippleView, never()).startUnlockedRipple(any())
    }
    }


    @Test
    @Test
@@ -145,7 +157,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
            false /* isStrongBiometric */)
            false /* isStrongBiometric */)


        // THEN no ripple
        // THEN no ripple
        verify(rippleView, never()).startUnlockedRipple(any(), any())
        verify(rippleView, never()).startUnlockedRipple(any())
    }
    }


    @Test
    @Test
@@ -169,7 +181,7 @@ class AuthRippleControllerTest : SysuiTestCase() {


        // THEN show ripple
        // THEN show ripple
        verify(rippleView).setSensorLocation(faceLocation)
        verify(rippleView).setSensorLocation(faceLocation)
        verify(rippleView).startUnlockedRipple(any(), any())
        verify(rippleView).startUnlockedRipple(any())
    }
    }


    @Test
    @Test
@@ -189,7 +201,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
            false /* isStrongBiometric */)
            false /* isStrongBiometric */)


        // THEN no ripple
        // THEN no ripple
        verify(rippleView, never()).startUnlockedRipple(any(), any())
        verify(rippleView, never()).startUnlockedRipple(any())
    }
    }


    @Test
    @Test
@@ -204,7 +216,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
            0 /* userId */,
            0 /* userId */,
            BiometricSourceType.FACE /* type */,
            BiometricSourceType.FACE /* type */,
            false /* isStrongBiometric */)
            false /* isStrongBiometric */)
        verify(rippleView, never()).startUnlockedRipple(any(), any())
        verify(rippleView, never()).startUnlockedRipple(any())
    }
    }


    @Test
    @Test
@@ -219,7 +231,39 @@ class AuthRippleControllerTest : SysuiTestCase() {
            0 /* userId */,
            0 /* userId */,
            BiometricSourceType.FINGERPRINT /* type */,
            BiometricSourceType.FINGERPRINT /* type */,
            false /* isStrongBiometric */)
            false /* isStrongBiometric */)
        verify(rippleView, never()).startUnlockedRipple(any(), any())
        verify(rippleView, never()).startUnlockedRipple(any())
    }

    @Test
    fun registersAndDeregisters() {
        controller.onViewAttached()
        val captor = ArgumentCaptor
            .forClass(KeyguardStateController.Callback::class.java)
        verify(keyguardStateController).addCallback(captor.capture())
        val captor2 = ArgumentCaptor
            .forClass(WakefulnessLifecycle.Observer::class.java)
        verify(wakefulnessLifecycle).addObserver(captor2.capture())
        controller.onViewDetached()
        verify(keyguardStateController).removeCallback(any())
        verify(wakefulnessLifecycle).removeObserver(any())
    }

    @Test
    @RunWithLooper(setAsMainLooper = true)
    fun testAnimatorRunWhenWakeAndUnlock() {
        val fpsLocation = PointF(5f, 5f)
        `when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
        controller.onViewAttached()
        `when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
        `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)

        controller.showRipple(BiometricSourceType.FINGERPRINT)
        assertTrue("reveal didn't start on keyguardFadingAway",
            controller.startLightRevealScrimOnKeyguardFadingAway)
        `when`(keyguardStateController.isKeyguardFadingAway).thenReturn(true)
        controller.onKeyguardFadingAwayChanged()
        assertFalse("reveal triggers multiple times",
            controller.startLightRevealScrimOnKeyguardFadingAway)
    }
    }


    @Test
    @Test