Merge "Add onBiometricAuthenticated in BiometricUnlockController to control when the auth ripple is shown" into udc-dev

This commit is contained in:
Chandru S
2023-04-05 19:25:22 +00:00
committed by Android (Google) Code Review
7 changed files with 93 additions and 97 deletions

View File

@@ -34,6 +34,7 @@ import com.android.systemui.animation.Interpolators
import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.plugins.log.LogLevel
import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.CircleReveal import com.android.systemui.statusbar.CircleReveal
import com.android.systemui.statusbar.LiftReveal import com.android.systemui.statusbar.LiftReveal
@@ -43,7 +44,6 @@ import com.android.systemui.statusbar.commandline.Command
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.CentralSurfaces import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
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.statusbar.policy.KeyguardStateController
@@ -52,7 +52,7 @@ import java.io.PrintWriter
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Provider import javax.inject.Provider
/*** /**
* Controls two ripple effects: * Controls two ripple effects:
* 1. Unlocked ripple: shows when authentication is successful * 1. Unlocked ripple: shows when authentication is successful
* 2. UDFPS dwell ripple: shows when the user has their finger down on the UDFPS area and reacts * 2. UDFPS dwell ripple: shows when the user has their finger down on the UDFPS area and reacts
@@ -71,14 +71,15 @@ class AuthRippleController @Inject constructor(
private val wakefulnessLifecycle: WakefulnessLifecycle, 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 biometricUnlockController: BiometricUnlockController,
private val udfpsControllerProvider: Provider<UdfpsController>, private val udfpsControllerProvider: Provider<UdfpsController>,
private val statusBarStateController: StatusBarStateController, private val statusBarStateController: StatusBarStateController,
private val featureFlags: FeatureFlags, private val featureFlags: FeatureFlags,
private val logger: KeyguardLogger, private val logger: KeyguardLogger,
rippleView: AuthRippleView? private val biometricUnlockController: BiometricUnlockController,
) : ViewController<AuthRippleView>(rippleView), KeyguardStateController.Callback, rippleView: AuthRippleView?
) :
ViewController<AuthRippleView>(rippleView),
KeyguardStateController.Callback,
WakefulnessLifecycle.Observer { WakefulnessLifecycle.Observer {
@VisibleForTesting @VisibleForTesting
@@ -102,8 +103,24 @@ class AuthRippleController @Inject constructor(
keyguardStateController.addCallback(this) keyguardStateController.addCallback(this)
wakefulnessLifecycle.addObserver(this) wakefulnessLifecycle.addObserver(this)
commandRegistry.registerCommand("auth-ripple") { AuthRippleCommand() } commandRegistry.registerCommand("auth-ripple") { AuthRippleCommand() }
biometricUnlockController.addListener(biometricModeListener)
} }
private val biometricModeListener =
object : BiometricUnlockController.BiometricUnlockEventsListener {
override fun onBiometricUnlockedWithKeyguardDismissal(
biometricSourceType: BiometricSourceType?
) {
if (biometricSourceType != null) {
showUnlockRipple(biometricSourceType)
} else {
logger.log(TAG,
LogLevel.ERROR,
"Unexpected scenario where biometricSourceType is null")
}
}
}
@VisibleForTesting @VisibleForTesting
public override fun onViewDetached() { public override fun onViewDetached() {
udfpsController?.removeCallback(udfpsControllerCallback) udfpsController?.removeCallback(udfpsControllerCallback)
@@ -113,6 +130,7 @@ class AuthRippleController @Inject constructor(
keyguardStateController.removeCallback(this) keyguardStateController.removeCallback(this)
wakefulnessLifecycle.removeObserver(this) wakefulnessLifecycle.removeObserver(this)
commandRegistry.unregisterCommand("auth-ripple") commandRegistry.unregisterCommand("auth-ripple")
biometricUnlockController.removeListener(biometricModeListener)
notificationShadeWindowController.setForcePluginOpen(false, this) notificationShadeWindowController.setForcePluginOpen(false, this)
} }
@@ -143,9 +161,6 @@ class AuthRippleController @Inject constructor(
showUnlockedRipple() showUnlockedRipple()
} }
} else if (biometricSourceType == BiometricSourceType.FACE) { } else if (biometricSourceType == BiometricSourceType.FACE) {
if (!bypassController.canBypass() && !authController.isUdfpsFingerDown) {
return
}
faceSensorLocation?.let { faceSensorLocation?.let {
mView.setSensorLocation(it) mView.setSensorLocation(it)
circleReveal = CircleReveal( circleReveal = CircleReveal(
@@ -267,7 +282,6 @@ class AuthRippleController @Inject constructor(
if (biometricSourceType == BiometricSourceType.FINGERPRINT) { if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
mView.fadeDwellRipple() mView.fadeDwellRipple()
} }
showUnlockRipple(biometricSourceType)
} }
override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType) { override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType) {

View File

@@ -471,7 +471,7 @@ constructor(
} }
val callback = val callback =
object : BiometricUnlockController.BiometricModeListener { object : BiometricUnlockController.BiometricUnlockEventsListener {
override fun onModeChanged(@WakeAndUnlockMode mode: Int) { override fun onModeChanged(@WakeAndUnlockMode mode: Int) {
dispatchUpdate() dispatchUpdate()
} }
@@ -481,10 +481,10 @@ constructor(
} }
} }
biometricUnlockController.addBiometricModeListener(callback) biometricUnlockController.addListener(callback)
dispatchUpdate() dispatchUpdate()
awaitClose { biometricUnlockController.removeBiometricModeListener(callback) } awaitClose { biometricUnlockController.removeListener(callback) }
} }
override val wakefulness: Flow<WakefulnessModel> = conflatedCallbackFlow { override val wakefulness: Flow<WakefulnessModel> = conflatedCallbackFlow {

View File

@@ -163,7 +163,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
private PendingAuthenticated mPendingAuthenticated = null; private PendingAuthenticated mPendingAuthenticated = null;
private boolean mHasScreenTurnedOnSinceAuthenticating; private boolean mHasScreenTurnedOnSinceAuthenticating;
private boolean mFadedAwayAfterWakeAndUnlock; private boolean mFadedAwayAfterWakeAndUnlock;
private Set<BiometricModeListener> mBiometricModeListeners = new HashSet<>(); private Set<BiometricUnlockEventsListener> mBiometricUnlockEventsListeners = new HashSet<>();
private final MetricsLogger mMetricsLogger; private final MetricsLogger mMetricsLogger;
private final AuthController mAuthController; private final AuthController mAuthController;
@@ -314,14 +314,14 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
mKeyguardViewController = keyguardViewController; mKeyguardViewController = keyguardViewController;
} }
/** Adds a {@link BiometricModeListener}. */ /** Adds a {@link BiometricUnlockEventsListener}. */
public void addBiometricModeListener(BiometricModeListener listener) { public void addListener(BiometricUnlockEventsListener listener) {
mBiometricModeListeners.add(listener); mBiometricUnlockEventsListeners.add(listener);
} }
/** Removes a {@link BiometricModeListener}. */ /** Removes a {@link BiometricUnlockEventsListener}. */
public void removeBiometricModeListener(BiometricModeListener listener) { public void removeListener(BiometricUnlockEventsListener listener) {
mBiometricModeListeners.remove(listener); mBiometricUnlockEventsListeners.remove(listener);
} }
private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() { private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() {
@@ -387,7 +387,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
@Override @Override
public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType, public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
boolean isStrongBiometric) { boolean isStrongBiometric) {
Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated"); Trace.beginSection("BiometricUnlockController#onBiometricUnlocked");
if (mUpdateMonitor.isGoingToSleep()) { if (mUpdateMonitor.isGoingToSleep()) {
mLogger.deferringAuthenticationDueToSleep(userId, mLogger.deferringAuthenticationDueToSleep(userId,
biometricSourceType, biometricSourceType,
@@ -411,10 +411,15 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
mKeyguardViewMediator.userActivity(); mKeyguardViewMediator.userActivity();
startWakeAndUnlock(biometricSourceType, isStrongBiometric); startWakeAndUnlock(biometricSourceType, isStrongBiometric);
} else { } else {
mLogger.d("onBiometricAuthenticated aborted by bypass controller"); mLogger.d("onBiometricUnlocked aborted by bypass controller");
} }
} }
/**
* Wake and unlock the device in response to successful authentication using biometrics.
* @param biometricSourceType Biometric source that was used to authenticate.
* @param isStrongBiometric
*/
public void startWakeAndUnlock(BiometricSourceType biometricSourceType, public void startWakeAndUnlock(BiometricSourceType biometricSourceType,
boolean isStrongBiometric) { boolean isStrongBiometric) {
int mode = calculateMode(biometricSourceType, isStrongBiometric); int mode = calculateMode(biometricSourceType, isStrongBiometric);
@@ -422,6 +427,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
|| mode == MODE_WAKE_AND_UNLOCK_PULSING || mode == MODE_UNLOCK_COLLAPSING || mode == MODE_WAKE_AND_UNLOCK_PULSING || mode == MODE_UNLOCK_COLLAPSING
|| mode == MODE_WAKE_AND_UNLOCK_FROM_DREAM || mode == MODE_DISMISS_BOUNCER) { || mode == MODE_WAKE_AND_UNLOCK_FROM_DREAM || mode == MODE_DISMISS_BOUNCER) {
vibrateSuccess(biometricSourceType); vibrateSuccess(biometricSourceType);
onBiometricUnlockedWithKeyguardDismissal(biometricSourceType);
} }
startWakeAndUnlock(mode); startWakeAndUnlock(mode);
} }
@@ -502,11 +508,17 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
} }
private void onModeChanged(@WakeAndUnlockMode int mode) { private void onModeChanged(@WakeAndUnlockMode int mode) {
for (BiometricModeListener listener : mBiometricModeListeners) { for (BiometricUnlockEventsListener listener : mBiometricUnlockEventsListeners) {
listener.onModeChanged(mode); listener.onModeChanged(mode);
} }
} }
private void onBiometricUnlockedWithKeyguardDismissal(BiometricSourceType biometricSourceType) {
for (BiometricUnlockEventsListener listener : mBiometricUnlockEventsListeners) {
listener.onBiometricUnlockedWithKeyguardDismissal(biometricSourceType);
}
}
public boolean hasPendingAuthentication() { public boolean hasPendingAuthentication() {
return mPendingAuthenticated != null return mPendingAuthenticated != null
&& mUpdateMonitor && mUpdateMonitor
@@ -777,7 +789,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
mMode = MODE_NONE; mMode = MODE_NONE;
mBiometricType = null; mBiometricType = null;
mNotificationShadeWindowController.setForceDozeBrightness(false); mNotificationShadeWindowController.setForceDozeBrightness(false);
for (BiometricModeListener listener : mBiometricModeListeners) { for (BiometricUnlockEventsListener listener : mBiometricUnlockEventsListeners) {
listener.onResetMode(); listener.onResetMode();
} }
mNumConsecutiveFpFailures = 0; mNumConsecutiveFpFailures = 0;
@@ -895,10 +907,17 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
} }
/** An interface to interact with the {@link BiometricUnlockController}. */ /** An interface to interact with the {@link BiometricUnlockController}. */
public interface BiometricModeListener { public interface BiometricUnlockEventsListener {
/** Called when {@code mMode} is reset to {@link #MODE_NONE}. */ /** Called when {@code mMode} is reset to {@link #MODE_NONE}. */
default void onResetMode() {} default void onResetMode() {}
/** Called when {@code mMode} has changed in {@link #startWakeAndUnlock(int)}. */ /** Called when {@code mMode} has changed in {@link #startWakeAndUnlock(int)}. */
default void onModeChanged(@WakeAndUnlockMode int mode) {} default void onModeChanged(@WakeAndUnlockMode int mode) {}
/**
* Called when the device is unlocked successfully using biometrics with the keyguard also
* being dismissed.
*/
default void onBiometricUnlockedWithKeyguardDismissal(
BiometricSourceType biometricSourceType) { }
} }
} }

View File

@@ -1675,8 +1675,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mStatusBarStateController.addCallback(mStateListener, mStatusBarStateController.addCallback(mStateListener,
SysuiStatusBarStateController.RANK_STATUS_BAR); SysuiStatusBarStateController.RANK_STATUS_BAR);
mBiometricUnlockController = mBiometricUnlockControllerLazy.get(); mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
mBiometricUnlockController.addBiometricModeListener( mBiometricUnlockController.addListener(
new BiometricUnlockController.BiometricModeListener() { new BiometricUnlockController.BiometricUnlockEventsListener() {
@Override @Override
public void onResetMode() { public void onResetMode() {
setWakeAndUnlocking(false); setWakeAndUnlocking(false);

View File

@@ -36,7 +36,6 @@ 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.CentralSurfaces import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.KeyguardBypassController
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.statusbar.policy.KeyguardStateController
import com.android.systemui.util.leak.RotationUtils import com.android.systemui.util.leak.RotationUtils
@@ -50,6 +49,7 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers import org.mockito.ArgumentMatchers
import org.mockito.ArgumentMatchers.eq import org.mockito.ArgumentMatchers.eq
import org.mockito.Captor
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
import org.mockito.Mockito.never import org.mockito.Mockito.never
@@ -73,16 +73,28 @@ class AuthRippleControllerTest : SysuiTestCase() {
@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 keyguardStateController: KeyguardStateController
@Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle @Mock
@Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
@Mock private lateinit var bypassController: KeyguardBypassController @Mock
@Mock private lateinit var biometricUnlockController: BiometricUnlockController private lateinit var notificationShadeWindowController: NotificationShadeWindowController
@Mock private lateinit var udfpsControllerProvider: Provider<UdfpsController> @Mock
@Mock private lateinit var udfpsController: UdfpsController private lateinit var biometricUnlockController: BiometricUnlockController
@Mock private lateinit var statusBarStateController: StatusBarStateController @Mock
@Mock private lateinit var featureFlags: FeatureFlags private lateinit var udfpsControllerProvider: Provider<UdfpsController>
@Mock private lateinit var lightRevealScrim: LightRevealScrim @Mock
@Mock private lateinit var fpSensorProp: FingerprintSensorPropertiesInternal private lateinit var udfpsController: UdfpsController
@Mock
private lateinit var statusBarStateController: StatusBarStateController
@Mock
private lateinit var featureFlags: FeatureFlags
@Mock
private lateinit var lightRevealScrim: LightRevealScrim
@Mock
private lateinit var fpSensorProp: FingerprintSensorPropertiesInternal
@Captor
private lateinit var biometricUnlockListener:
ArgumentCaptor<BiometricUnlockController.BiometricUnlockEventsListener>
@Before @Before
fun setUp() { fun setUp() {
@@ -106,13 +118,12 @@ class AuthRippleControllerTest : SysuiTestCase() {
wakefulnessLifecycle, wakefulnessLifecycle,
commandRegistry, commandRegistry,
notificationShadeWindowController, notificationShadeWindowController,
bypassController,
biometricUnlockController,
udfpsControllerProvider, udfpsControllerProvider,
statusBarStateController, statusBarStateController,
featureFlags, featureFlags,
KeyguardLogger(logcatLogBuffer(AuthRippleController.TAG)), KeyguardLogger(logcatLogBuffer(AuthRippleController.TAG)),
rippleView biometricUnlockController,
rippleView,
) )
controller.init() controller.init()
`when`(mCentralSurfaces.lightRevealScrim).thenReturn(lightRevealScrim) `when`(mCentralSurfaces.lightRevealScrim).thenReturn(lightRevealScrim)
@@ -134,12 +145,9 @@ class AuthRippleControllerTest : SysuiTestCase() {
eq(BiometricSourceType.FINGERPRINT))).thenReturn(true) eq(BiometricSourceType.FINGERPRINT))).thenReturn(true)
// WHEN fingerprint authenticated // WHEN fingerprint authenticated
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java) verify(biometricUnlockController).addListener(biometricUnlockListener.capture())
verify(keyguardUpdateMonitor).registerCallback(captor.capture()) biometricUnlockListener.value
captor.value.onBiometricAuthenticated( .onBiometricUnlockedWithKeyguardDismissal(BiometricSourceType.FINGERPRINT)
0 /* userId */,
BiometricSourceType.FINGERPRINT /* type */,
false /* isStrongBiometric */)
// THEN update sensor location and show ripple // THEN update sensor location and show ripple
verify(rippleView).setFingerprintSensorLocation(fpsLocation, 0f) verify(rippleView).setFingerprintSensorLocation(fpsLocation, 0f)
@@ -190,51 +198,6 @@ class AuthRippleControllerTest : SysuiTestCase() {
verify(rippleView, never()).startUnlockedRipple(any()) verify(rippleView, never()).startUnlockedRipple(any())
} }
@Test
fun testFaceTriggerBypassEnabled_Ripple() {
// GIVEN face auth sensor exists, keyguard is showing & unlocking with face is allowed
val faceLocation = Point(5, 5)
`when`(authController.faceSensorLocation).thenReturn(faceLocation)
controller.onViewAttached()
`when`(keyguardStateController.isShowing).thenReturn(true)
`when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
BiometricSourceType.FACE)).thenReturn(true)
// WHEN bypass is enabled & face authenticated
`when`(bypassController.canBypass()).thenReturn(true)
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
verify(keyguardUpdateMonitor).registerCallback(captor.capture())
captor.value.onBiometricAuthenticated(
0 /* userId */,
BiometricSourceType.FACE /* type */,
false /* isStrongBiometric */)
// THEN show ripple
verify(rippleView).setSensorLocation(faceLocation)
verify(rippleView).startUnlockedRipple(any())
}
@Test
fun testFaceTriggerNonBypass_NoRipple() {
// GIVEN face auth sensor exists
val faceLocation = Point(5, 5)
`when`(authController.faceSensorLocation).thenReturn(faceLocation)
controller.onViewAttached()
// WHEN bypass isn't enabled & face authenticated
`when`(bypassController.canBypass()).thenReturn(false)
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
verify(keyguardUpdateMonitor).registerCallback(captor.capture())
captor.value.onBiometricAuthenticated(
0 /* userId */,
BiometricSourceType.FACE /* type */,
false /* isStrongBiometric */)
// THEN no ripple
verify(rippleView, never()).startUnlockedRipple(any())
}
@Test @Test
fun testNullFaceSensorLocationDoesNothing() { fun testNullFaceSensorLocationDoesNothing() {
`when`(authController.faceSensorLocation).thenReturn(null) `when`(authController.faceSensorLocation).thenReturn(null)

View File

@@ -461,8 +461,8 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
val job = underTest.biometricUnlockState.onEach(values::add).launchIn(this) val job = underTest.biometricUnlockState.onEach(values::add).launchIn(this)
runCurrent() runCurrent()
val captor = argumentCaptor<BiometricUnlockController.BiometricModeListener>() val captor = argumentCaptor<BiometricUnlockController.BiometricUnlockEventsListener>()
verify(biometricUnlockController).addBiometricModeListener(captor.capture()) verify(biometricUnlockController).addListener(captor.capture())
listOf( listOf(
BiometricUnlockController.MODE_NONE, BiometricUnlockController.MODE_NONE,
@@ -498,7 +498,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
job.cancel() job.cancel()
runCurrent() runCurrent()
verify(biometricUnlockController).removeBiometricModeListener(captor.value) verify(biometricUnlockController).removeListener(captor.value)
} }
@Test @Test

View File

@@ -89,7 +89,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
@Mock @Mock
private KeyguardViewMediator mKeyguardViewMediator; private KeyguardViewMediator mKeyguardViewMediator;
@Mock @Mock
private BiometricUnlockController.BiometricModeListener mBiometricModeListener; private BiometricUnlockController.BiometricUnlockEventsListener mBiometricUnlockEventsListener;
@Mock @Mock
private KeyguardStateController mKeyguardStateController; private KeyguardStateController mKeyguardStateController;
@Mock @Mock
@@ -145,7 +145,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
mSystemClock mSystemClock
); );
mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager); mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
mBiometricUnlockController.addBiometricModeListener(mBiometricModeListener); mBiometricUnlockController.addListener(mBiometricUnlockEventsListener);
when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(mStrongAuthTracker); when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(mStrongAuthTracker);
} }