RESTRICT AUTOMERGE Fix detect biometric logic.
Reverts the revert: Iea66d7782b3365dea827b854783aeddaa5c6699c and updates the detect biometric logic to forward fix the CUJ. [1] Never allow detectFingerprint or detectFace to enter the device. DetectBiometric at most can bring up the bouncer. It will never run the authenticate path. [2] When the temporary lockout state is reset, reset the fingerprint listening state so that if SysUI was running detection, SysUI will subsequently switch over to running authenticate. If there's faceDetect running when lockout resets, we allow faceDetect to complete running - if successful, it'll bring up the bouncer where the user can either enter pin/pattern/password to enter the device, or attempt face auth again by tapping the bouncer. [3] Not directly related to detect but was causing a stuck BIOMETRIC_CANCELLING_RESTARTING state: make sure to update the biometric running state if the cancellation signal times out and the biometric running state was BIOMETRIC_CANCELLING_RESTARTING. Previously, the biometric state was only STOPPED when the cancellation signal (framework didn't get back to SysUI in time) timed out Note: There's a bug b/269743883 in the detect CUJ where if its requested right after being cancelled, it can be stuck in the CANCELLING_RESTARTING state. However, this will timeout after 3000ms and restart the fingerprint listening state afterwards. This will be an issue until the framework bug is resolved to send the cancellation confirmation to SysUI. Test: atest KeyguardUpdateMonitorTest BiometricsUnlockControllerTest Test: after the lockout, putting any finger on the FP sensor will bring up the bouncer. after the lockout counter expires, putting an unenrolled finger on the FP sensor will result in a FP error. only enrolled fingerprints will allow the user to enter the device. Bug: 269574598 Bug: 269769293 Bug: 269200614 Change-Id: Ic8f3d5b8b6a898a6d22f69c6e2ed4a3c24c61a6b
This commit is contained in:
@@ -816,6 +816,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
}
|
||||
}
|
||||
|
||||
private void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
|
||||
boolean isStrongBiometric) {
|
||||
Assert.isMainThread();
|
||||
Trace.beginSection("KeyGuardUpdateMonitor#onBiometricDetected");
|
||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||
if (cb != null) {
|
||||
cb.onBiometricDetected(userId, biometricSourceType, isStrongBiometric);
|
||||
}
|
||||
}
|
||||
Trace.endSection();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void onFingerprintAuthenticated(int userId, boolean isStrongBiometric) {
|
||||
Assert.isMainThread();
|
||||
@@ -892,6 +905,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
}
|
||||
}
|
||||
|
||||
private void handleBiometricDetected(int authUserId, BiometricSourceType biometricSourceType,
|
||||
boolean isStrongBiometric) {
|
||||
Trace.beginSection("KeyGuardUpdateMonitor#handlerBiometricDetected");
|
||||
onBiometricDetected(authUserId, biometricSourceType, isStrongBiometric);
|
||||
if (biometricSourceType == FINGERPRINT) {
|
||||
mLogger.logFingerprintDetected(authUserId, isStrongBiometric);
|
||||
} else if (biometricSourceType == FACE) {
|
||||
mLogger.logFaceDetected(authUserId, isStrongBiometric);
|
||||
setFaceRunningState(BIOMETRIC_STATE_STOPPED);
|
||||
}
|
||||
|
||||
Trace.endSection();
|
||||
}
|
||||
|
||||
private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiometric) {
|
||||
Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated");
|
||||
if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
|
||||
@@ -943,8 +970,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
|
||||
private void onFingerprintCancelNotReceived() {
|
||||
mLogger.e("Fp cancellation not received, transitioning to STOPPED");
|
||||
final boolean wasCancellingRestarting = mFingerprintRunningState
|
||||
== BIOMETRIC_STATE_CANCELLING_RESTARTING;
|
||||
mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
|
||||
KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_STOP);
|
||||
if (wasCancellingRestarting) {
|
||||
KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
|
||||
} else {
|
||||
KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_STOP);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleFingerprintError(int msgId, String errString) {
|
||||
@@ -1031,6 +1064,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
() -> updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE),
|
||||
getBiometricLockoutDelay());
|
||||
} else {
|
||||
boolean temporaryLockoutReset = wasLockout && !mFingerprintLockedOut;
|
||||
if (temporaryLockoutReset) {
|
||||
mLogger.d("temporaryLockoutReset - stopListeningForFingerprint() to stop"
|
||||
+ " detectFingerprint");
|
||||
stopListeningForFingerprint();
|
||||
}
|
||||
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
|
||||
}
|
||||
|
||||
@@ -1730,10 +1769,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
}
|
||||
};
|
||||
|
||||
private final FingerprintManager.FingerprintDetectionCallback mFingerprintDetectionCallback =
|
||||
(sensorId, userId, isStrongBiometric) -> {
|
||||
// Trigger the fingerprint detected path so the bouncer can be shown
|
||||
handleBiometricDetected(userId, FINGERPRINT, isStrongBiometric);
|
||||
};
|
||||
|
||||
private final FaceManager.FaceDetectionCallback mFaceDetectionCallback
|
||||
= (sensorId, userId, isStrongBiometric) -> {
|
||||
// Trigger the face success path so the bouncer can be shown
|
||||
handleFaceAuthenticated(userId, isStrongBiometric);
|
||||
// Trigger the face detected path so the bouncer can be shown
|
||||
handleBiometricDetected(userId, FACE, isStrongBiometric);
|
||||
};
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -2765,8 +2810,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
|
||||
boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
|
||||
&& shouldListenBouncerState && shouldListenUdfpsState
|
||||
&& shouldListenSideFpsState
|
||||
&& !isFingerprintLockedOut();
|
||||
&& shouldListenSideFpsState;
|
||||
logListenerModelData(
|
||||
new KeyguardFingerprintListenModel(
|
||||
System.currentTimeMillis(),
|
||||
@@ -2825,8 +2869,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
final boolean supportsDetect = !mFaceSensorProperties.isEmpty()
|
||||
&& mFaceSensorProperties.get(0).supportsFaceDetection
|
||||
&& canBypass && !mPrimaryBouncerIsOrWillBeShowing
|
||||
&& !isUserInLockdown(user)
|
||||
&& !isFingerprintLockedOut();
|
||||
&& !isUserInLockdown(user);
|
||||
final boolean faceAuthAllowedOrDetectionIsNeeded = faceAuthAllowed || supportsDetect;
|
||||
|
||||
// If the face or fp has recently been authenticated do not attempt to authenticate again.
|
||||
@@ -2922,11 +2965,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
mLogger.v("startListeningForFingerprint - detect");
|
||||
mFpm.detectFingerprint(
|
||||
mFingerprintCancelSignal,
|
||||
(sensorId, user, isStrongBiometric) -> {
|
||||
mLogger.d("fingerprint detected");
|
||||
// Trigger the fingerprint success path so the bouncer can be shown
|
||||
handleFingerprintAuthenticated(user, isStrongBiometric);
|
||||
},
|
||||
mFingerprintDetectionCallback,
|
||||
userId);
|
||||
} else {
|
||||
mLogger.v("startListeningForFingerprint - authenticate");
|
||||
|
||||
@@ -214,13 +214,21 @@ public class KeyguardUpdateMonitorCallback {
|
||||
public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) { }
|
||||
|
||||
/**
|
||||
* Called when a biometric is recognized.
|
||||
* Called when a biometric is authenticated.
|
||||
* @param userId the user id for which the biometric sample was authenticated
|
||||
* @param biometricSourceType
|
||||
*/
|
||||
public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
|
||||
boolean isStrongBiometric) { }
|
||||
|
||||
/**
|
||||
* Called when a biometric is detected but not successfully authenticated.
|
||||
* @param userId the user id for which the biometric sample was detected
|
||||
* @param biometricSourceType
|
||||
*/
|
||||
public void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
|
||||
boolean isStrongBiometric) { }
|
||||
|
||||
/**
|
||||
* Called when biometric authentication provides help string (e.g. "Try again")
|
||||
* @param msgId
|
||||
|
||||
@@ -167,6 +167,20 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
|
||||
}, {"Fingerprint auth successful: userId: $int1, isStrongBiometric: $bool1"})
|
||||
}
|
||||
|
||||
fun logFaceDetected(userId: Int, isStrongBiometric: Boolean) {
|
||||
logBuffer.log(TAG, DEBUG, {
|
||||
int1 = userId
|
||||
bool1 = isStrongBiometric
|
||||
}, {"Face detected: userId: $int1, isStrongBiometric: $bool1"})
|
||||
}
|
||||
|
||||
fun logFingerprintDetected(userId: Int, isStrongBiometric: Boolean) {
|
||||
logBuffer.log(TAG, DEBUG, {
|
||||
int1 = userId
|
||||
bool1 = isStrongBiometric
|
||||
}, {"Fingerprint detected: userId: $int1, isStrongBiometric: $bool1"})
|
||||
}
|
||||
|
||||
fun logFingerprintError(msgId: Int, originalErrMsg: String) {
|
||||
logBuffer.log(TAG, DEBUG, {
|
||||
str1 = originalErrMsg
|
||||
|
||||
@@ -382,6 +382,17 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
|
||||
Trace.endSection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
|
||||
boolean isStrongBiometric) {
|
||||
Trace.beginSection("BiometricUnlockController#onBiometricDetected");
|
||||
if (mUpdateMonitor.isGoingToSleep()) {
|
||||
Trace.endSection();
|
||||
return;
|
||||
}
|
||||
startWakeAndUnlock(MODE_SHOW_BOUNCER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
|
||||
boolean isStrongBiometric) {
|
||||
|
||||
@@ -29,7 +29,6 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR
|
||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
|
||||
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
|
||||
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
|
||||
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING;
|
||||
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING;
|
||||
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
|
||||
import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT;
|
||||
@@ -622,19 +621,47 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testOnlyDetectFingerprint_whenFingerprintUnlockNotAllowed() {
|
||||
// Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
|
||||
// will trigger updateBiometricListeningState();
|
||||
clearInvocations(mFingerprintManager);
|
||||
mKeyguardUpdateMonitor.resetBiometricListeningState();
|
||||
|
||||
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
|
||||
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
|
||||
mTestableLooper.processAllMessages();
|
||||
givenDetectFingerprintWithClearingFingerprintManagerInvocations();
|
||||
|
||||
verifyFingerprintAuthenticateNeverCalled();
|
||||
verifyFingerprintDetectCall();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDetectFingerprint_biometricDetectCallback() {
|
||||
ArgumentCaptor<FingerprintManager.FingerprintDetectionCallback> fpDetectCallbackCaptor =
|
||||
ArgumentCaptor.forClass(FingerprintManager.FingerprintDetectionCallback.class);
|
||||
|
||||
givenDetectFingerprintWithClearingFingerprintManagerInvocations();
|
||||
verify(mFingerprintManager).detectFingerprint(
|
||||
any(), fpDetectCallbackCaptor.capture(), anyInt());
|
||||
fpDetectCallbackCaptor.getValue().onFingerprintDetected(0, 0, true);
|
||||
|
||||
// THEN verify keyguardUpdateMonitorCallback receives a detect callback
|
||||
// and NO authenticate callbacks
|
||||
verify(mTestCallback).onBiometricDetected(
|
||||
eq(0), eq(BiometricSourceType.FINGERPRINT), eq(true));
|
||||
verify(mTestCallback, never()).onBiometricAuthenticated(
|
||||
anyInt(), any(), anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDetectFace_biometricDetectCallback() {
|
||||
ArgumentCaptor<FaceManager.FaceDetectionCallback> faceDetectCallbackCaptor =
|
||||
ArgumentCaptor.forClass(FaceManager.FaceDetectionCallback.class);
|
||||
|
||||
givenDetectFace();
|
||||
verify(mFaceManager).detectFace(any(), faceDetectCallbackCaptor.capture(), anyInt());
|
||||
faceDetectCallbackCaptor.getValue().onFaceDetected(0, 0, false);
|
||||
|
||||
// THEN verify keyguardUpdateMonitorCallback receives a detect callback
|
||||
// and NO authenticate callbacks
|
||||
verify(mTestCallback).onBiometricDetected(
|
||||
eq(0), eq(BiometricSourceType.FACE), eq(false));
|
||||
verify(mTestCallback, never()).onBiometricAuthenticated(
|
||||
anyInt(), any(), anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnlockingWithFaceAllowed_strongAuthTrackerUnlockingWithBiometricAllowed() {
|
||||
// GIVEN unlocking with biometric is allowed
|
||||
@@ -663,7 +690,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
strongAuthNotRequired();
|
||||
|
||||
// WHEN fingerprint is locked out
|
||||
fingerprintErrorLockedOut();
|
||||
fingerprintErrorTemporaryLockedOut();
|
||||
|
||||
// THEN unlocking with face is not allowed
|
||||
Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
|
||||
@@ -686,7 +713,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
strongAuthNotRequired();
|
||||
|
||||
// WHEN fingerprint is locked out
|
||||
fingerprintErrorLockedOut();
|
||||
fingerprintErrorTemporaryLockedOut();
|
||||
|
||||
// THEN unlocking with fingerprint is not allowed
|
||||
Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
|
||||
@@ -710,7 +737,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
|
||||
|
||||
// WHEN fingerprint is locked out
|
||||
fingerprintErrorLockedOut();
|
||||
fingerprintErrorTemporaryLockedOut();
|
||||
|
||||
// THEN user is NOT considered as "having trust" and bouncer cannot be skipped
|
||||
Assert.assertFalse(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
|
||||
@@ -772,11 +799,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void nofaceDetect_whenStrongAuthRequiredAndBypassUdfpsSupportedAndFpRunning() {
|
||||
// GIVEN mocked keyguardUpdateMonitorCallback
|
||||
KeyguardUpdateMonitorCallback keyguardUpdateMonitorCallback =
|
||||
mock(KeyguardUpdateMonitorCallback.class);
|
||||
mKeyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback);
|
||||
|
||||
// GIVEN bypass is enabled, face detection is supported
|
||||
lockscreenBypassIsAllowed();
|
||||
supportsFaceDetection();
|
||||
@@ -795,22 +817,13 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
verifyFaceAuthenticateNeverCalled();
|
||||
|
||||
// THEN biometric help message sent to callback
|
||||
verify(keyguardUpdateMonitorCallback).onBiometricHelp(
|
||||
verify(mTestCallback).onBiometricHelp(
|
||||
eq(BIOMETRIC_HELP_FACE_NOT_AVAILABLE), anyString(), eq(BiometricSourceType.FACE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void faceDetect_whenStrongAuthRequiredAndBypass() {
|
||||
// GIVEN bypass is enabled, face detection is supported and strong auth is required
|
||||
lockscreenBypassIsAllowed();
|
||||
supportsFaceDetection();
|
||||
strongAuthRequiredEncrypted();
|
||||
keyguardIsVisible();
|
||||
// fingerprint is NOT running, UDFPS is NOT supported
|
||||
|
||||
// WHEN the device wakes up
|
||||
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
|
||||
mTestableLooper.processAllMessages();
|
||||
givenDetectFace();
|
||||
|
||||
// FACE detect is triggered, not authenticate
|
||||
verifyFaceDetectCall();
|
||||
@@ -826,39 +839,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
verifyFaceDetectNeverCalled();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noFaceRun_whenFpLockout() {
|
||||
// GIVEN bypass is enabled, face detection is supported and strong auth is required
|
||||
lockscreenBypassIsAllowed();
|
||||
supportsFaceDetection();
|
||||
strongAuthRequiredEncrypted();
|
||||
keyguardIsVisible();
|
||||
// fingerprint is NOT running, UDFPS is NOT supported
|
||||
|
||||
// GIVEN fp is locked out
|
||||
when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), anyInt()))
|
||||
.thenReturn(BIOMETRIC_LOCKOUT_TIMED);
|
||||
mKeyguardUpdateMonitor.handleUserSwitchComplete(0);
|
||||
assertThat(mKeyguardUpdateMonitor.isFingerprintLockedOut()).isEqualTo(true);
|
||||
|
||||
// WHEN the device wakes up
|
||||
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
// FACE detect is NOT triggered and face authenticate is NOT triggered
|
||||
verifyFaceDetectNeverCalled();
|
||||
verifyFaceAuthenticateNeverCalled();
|
||||
|
||||
// WHEN bouncer becomes visible
|
||||
setKeyguardBouncerVisibility(true);
|
||||
clearInvocations(mFaceManager);
|
||||
|
||||
// THEN face scanning is not run
|
||||
mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
|
||||
verifyFaceAuthenticateNeverCalled();
|
||||
verifyFaceDetectNeverCalled();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noFaceDetect_whenStrongAuthRequiredAndBypass_faceDetectionUnsupported() {
|
||||
// GIVEN bypass is enabled, face detection is NOT supported and strong auth is required
|
||||
@@ -1177,8 +1157,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
// Fingerprint should be cancelled on lockout if going to lockout state, else
|
||||
// restarted if it's not
|
||||
assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
|
||||
.isEqualTo(fpLocked
|
||||
? BIOMETRIC_STATE_CANCELLING : BIOMETRIC_STATE_CANCELLING_RESTARTING);
|
||||
.isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1637,7 +1616,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
|
||||
|
||||
// Fingerprint is locked out.
|
||||
fingerprintErrorLockedOut();
|
||||
fingerprintErrorTemporaryLockedOut();
|
||||
|
||||
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
|
||||
}
|
||||
@@ -2446,6 +2425,29 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
eq(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detectFingerprint_onTemporaryLockoutReset_authenticateFingerprint() {
|
||||
ArgumentCaptor<FingerprintManager.LockoutResetCallback> fpLockoutResetCallbackCaptor =
|
||||
ArgumentCaptor.forClass(FingerprintManager.LockoutResetCallback.class);
|
||||
verify(mFingerprintManager).addLockoutResetCallback(fpLockoutResetCallbackCaptor.capture());
|
||||
|
||||
// GIVEN device is locked out
|
||||
fingerprintErrorTemporaryLockedOut();
|
||||
|
||||
// GIVEN FP detection is running
|
||||
givenDetectFingerprintWithClearingFingerprintManagerInvocations();
|
||||
verifyFingerprintDetectCall();
|
||||
verifyFingerprintAuthenticateNeverCalled();
|
||||
|
||||
// WHEN temporary lockout resets
|
||||
fpLockoutResetCallbackCaptor.getValue().onLockoutReset(0);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
// THEN fingerprint detect state should cancel & then restart (for authenticate call)
|
||||
assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
|
||||
.isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
|
||||
}
|
||||
|
||||
private void verifyFingerprintAuthenticateNeverCalled() {
|
||||
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
|
||||
anyInt(), anyInt());
|
||||
@@ -2550,7 +2552,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
mKeyguardUpdateMonitor.setSwitchingUser(true);
|
||||
}
|
||||
|
||||
private void fingerprintErrorLockedOut() {
|
||||
private void fingerprintErrorTemporaryLockedOut() {
|
||||
mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback
|
||||
.onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT, "Fingerprint locked out");
|
||||
}
|
||||
@@ -2690,6 +2692,30 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
receiver.setPendingResult(pendingResult);
|
||||
}
|
||||
|
||||
private void givenDetectFingerprintWithClearingFingerprintManagerInvocations() {
|
||||
// Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
|
||||
// will trigger updateBiometricListeningState();
|
||||
clearInvocations(mFingerprintManager);
|
||||
mKeyguardUpdateMonitor.resetBiometricListeningState();
|
||||
|
||||
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
|
||||
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
|
||||
mTestableLooper.processAllMessages();
|
||||
}
|
||||
|
||||
private void givenDetectFace() {
|
||||
// GIVEN bypass is enabled, face detection is supported and strong auth is required
|
||||
lockscreenBypassIsAllowed();
|
||||
supportsFaceDetection();
|
||||
strongAuthRequiredEncrypted();
|
||||
keyguardIsVisible();
|
||||
// fingerprint is NOT running, UDFPS is NOT supported
|
||||
|
||||
// WHEN the device wakes up
|
||||
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
|
||||
mTestableLooper.processAllMessages();
|
||||
}
|
||||
|
||||
private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
|
||||
int subscription = simInited
|
||||
? 1/* mock subid=1 */ : SubscriptionManager.PLACEHOLDER_SUBSCRIPTION_ID_BASE;
|
||||
|
||||
@@ -537,6 +537,26 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
|
||||
verify(mVibratorHelper).vibrateAuthError(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onFingerprintDetect_showBouncer() {
|
||||
// WHEN fingerprint detect occurs
|
||||
mBiometricUnlockController.onBiometricDetected(UserHandle.USER_CURRENT,
|
||||
BiometricSourceType.FINGERPRINT, true /* isStrongBiometric */);
|
||||
|
||||
// THEN shows primary bouncer
|
||||
verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onFaceDetect_showBouncer() {
|
||||
// WHEN face detect occurs
|
||||
mBiometricUnlockController.onBiometricDetected(UserHandle.USER_CURRENT,
|
||||
BiometricSourceType.FACE, false /* isStrongBiometric */);
|
||||
|
||||
// THEN shows primary bouncer
|
||||
verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(anyBoolean());
|
||||
}
|
||||
|
||||
private void givenFingerprintModeUnlockCollapsing() {
|
||||
when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
|
||||
when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
|
||||
|
||||
@@ -452,13 +452,6 @@ public class FingerprintService extends SystemService {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) {
|
||||
// If this happens, something in KeyguardUpdateMonitor is wrong. This should only
|
||||
// ever be invoked when the user is encrypted or lockdown.
|
||||
Slog.e(TAG, "detectFingerprint invoked when user is not encrypted or lockdown");
|
||||
return -1;
|
||||
}
|
||||
|
||||
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Null provider for detectFingerprint");
|
||||
|
||||
Reference in New Issue
Block a user