Merge "Fallback to fingerprint on all error types." into sc-dev
This commit is contained in:
@@ -130,19 +130,29 @@ public class AuthBiometricFaceToFingerprintView extends AuthBiometricFaceView {
|
|||||||
@Override
|
@Override
|
||||||
public void onAuthenticationFailed(
|
public void onAuthenticationFailed(
|
||||||
@Modality int modality, @Nullable String failureReason) {
|
@Modality int modality, @Nullable String failureReason) {
|
||||||
if (modality == TYPE_FACE && mActiveSensorType == TYPE_FACE) {
|
super.onAuthenticationFailed(modality, checkErrorForFallback(failureReason));
|
||||||
// switching from face -> fingerprint mode, suppress soft error messages
|
|
||||||
failureReason = mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead);
|
|
||||||
}
|
}
|
||||||
super.onAuthenticationFailed(modality, failureReason);
|
|
||||||
|
@Override
|
||||||
|
public void onError(int modality, String error) {
|
||||||
|
super.onError(modality, checkErrorForFallback(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String checkErrorForFallback(String message) {
|
||||||
|
if (mActiveSensorType == TYPE_FACE) {
|
||||||
|
Log.d(TAG, "Falling back to fingerprint: " + message);
|
||||||
|
|
||||||
|
// switching from face -> fingerprint mode, suppress root error messages
|
||||||
|
mCallback.onAction(Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR);
|
||||||
|
return mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@BiometricState
|
@BiometricState
|
||||||
protected int getStateForAfterError() {
|
protected int getStateForAfterError() {
|
||||||
if (mActiveSensorType == TYPE_FACE) {
|
if (mActiveSensorType == TYPE_FACE) {
|
||||||
mHandler.post(() -> mCallback.onAction(
|
|
||||||
Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
|
|
||||||
return STATE_AUTHENTICATING;
|
return STATE_AUTHENTICATING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import static org.junit.Assert.assertEquals;
|
|||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.inOrder;
|
import static org.mockito.Mockito.inOrder;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.reset;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -124,16 +126,50 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testModeUpdated_whenSwitchToFingerprint() {
|
public void testModeUpdated_onSoftError_whenSwitchToFingerprint() {
|
||||||
mFaceToFpView.onDialogAnimatedIn();
|
mFaceToFpView.onDialogAnimatedIn();
|
||||||
mFaceToFpView.onAuthenticationFailed(TYPE_FACE, "no face");
|
mFaceToFpView.onAuthenticationFailed(TYPE_FACE, "no face");
|
||||||
waitForIdleSync();
|
waitForIdleSync();
|
||||||
|
|
||||||
verify(mIndicatorView).setText(
|
verify(mIndicatorView).setText(
|
||||||
eq(mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead)));
|
eq(mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead)));
|
||||||
|
verify(mCallback).onAction(
|
||||||
|
eq(AuthBiometricView.Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
|
||||||
assertEquals(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING, mFaceToFpView.mState);
|
assertEquals(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING, mFaceToFpView.mState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testModeUpdated_onHardError_whenSwitchToFingerprint() {
|
||||||
|
mFaceToFpView.onDialogAnimatedIn();
|
||||||
|
mFaceToFpView.onError(TYPE_FACE, "oh no!");
|
||||||
|
waitForIdleSync();
|
||||||
|
|
||||||
|
verify(mIndicatorView).setText(
|
||||||
|
eq(mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead)));
|
||||||
|
verify(mCallback).onAction(
|
||||||
|
eq(AuthBiometricView.Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
|
||||||
|
assertEquals(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING, mFaceToFpView.mState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFingerprintOnlyStartsOnFirstError() {
|
||||||
|
mFaceToFpView.onDialogAnimatedIn();
|
||||||
|
verify(mFaceToFpView.mIconController)
|
||||||
|
.updateState(anyInt(), eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING));
|
||||||
|
|
||||||
|
mFaceToFpView.onDialogAnimatedIn();
|
||||||
|
mFaceToFpView.updateState(AuthBiometricFaceToFingerprintView.STATE_ERROR);
|
||||||
|
mFaceToFpView.updateState(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING);
|
||||||
|
|
||||||
|
reset(mCallback);
|
||||||
|
|
||||||
|
mFaceToFpView.onError(TYPE_FACE, "oh no!");
|
||||||
|
mFaceToFpView.onAuthenticationFailed(TYPE_FACE, "no face");
|
||||||
|
|
||||||
|
verify(mCallback, never()).onAction(
|
||||||
|
eq(AuthBiometricView.Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
|
||||||
|
}
|
||||||
|
|
||||||
public class TestableView extends AuthBiometricFaceToFingerprintView {
|
public class TestableView extends AuthBiometricFaceToFingerprintView {
|
||||||
public TestableView(Context context) {
|
public TestableView(Context context) {
|
||||||
super(context, null, new MockInjector());
|
super(context, null, new MockInjector());
|
||||||
|
|||||||
@@ -355,10 +355,6 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cancelAllFingerprintSensors() {
|
|
||||||
cancelAllSensors(sensor -> sensor.modality == TYPE_FINGERPRINT);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cancelAllSensors() {
|
private void cancelAllSensors() {
|
||||||
cancelAllSensors(sensor -> true);
|
cancelAllSensors(sensor -> true);
|
||||||
}
|
}
|
||||||
@@ -387,6 +383,9 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
|||||||
*/
|
*/
|
||||||
boolean onErrorReceived(int sensorId, int cookie, @BiometricConstants.Errors int error,
|
boolean onErrorReceived(int sensorId, int cookie, @BiometricConstants.Errors int error,
|
||||||
int vendorCode) throws RemoteException {
|
int vendorCode) throws RemoteException {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.v(TAG, "onErrorReceived sensor: " + sensorId + " error: " + error);
|
||||||
|
}
|
||||||
|
|
||||||
if (!containsCookie(cookie)) {
|
if (!containsCookie(cookie)) {
|
||||||
Slog.e(TAG, "Unknown/expired cookie: " + cookie);
|
Slog.e(TAG, "Unknown/expired cookie: " + cookie);
|
||||||
@@ -454,12 +453,14 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
|||||||
// a round trip to SystemUI.
|
// a round trip to SystemUI.
|
||||||
mClientReceiver.onError(modality, error, vendorCode);
|
mClientReceiver.onError(modality, error, vendorCode);
|
||||||
return true;
|
return true;
|
||||||
} else if (shouldErrorTriggerMultiSensorTransition()) {
|
|
||||||
// wait for the UI to signal when modality should switch
|
|
||||||
mMultiSensorState = MULTI_SENSOR_STATE_SWITCHING;
|
|
||||||
Slog.d(TAG, "onErrorReceived: waiting for modality switch callback");
|
|
||||||
} else {
|
} else {
|
||||||
mState = STATE_ERROR_PENDING_SYSUI;
|
mState = STATE_ERROR_PENDING_SYSUI;
|
||||||
|
if (mMultiSensorMode == BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT
|
||||||
|
&& mMultiSensorState == MULTI_SENSOR_STATE_FACE_SCANNING) {
|
||||||
|
// wait for the UI to signal when modality should switch
|
||||||
|
Slog.d(TAG, "onErrorReceived: waiting for modality switch callback");
|
||||||
|
mMultiSensorState = MULTI_SENSOR_STATE_SWITCHING;
|
||||||
|
}
|
||||||
mStatusBarService.onBiometricError(modality, error, vendorCode);
|
mStatusBarService.onBiometricError(modality, error, vendorCode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -627,7 +628,7 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
|||||||
void onDeviceCredentialPressed() {
|
void onDeviceCredentialPressed() {
|
||||||
// Cancel authentication. Skip the token/package check since we are cancelling
|
// Cancel authentication. Skip the token/package check since we are cancelling
|
||||||
// from system server. The interface is permission protected so this is fine.
|
// from system server. The interface is permission protected so this is fine.
|
||||||
cancelBiometricOnly();
|
cancelAllSensors();
|
||||||
mState = STATE_SHOWING_DEVICE_CREDENTIAL;
|
mState = STATE_SHOWING_DEVICE_CREDENTIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -733,12 +734,10 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
|||||||
}
|
}
|
||||||
mClientReceiver.onAuthenticationSucceeded(
|
mClientReceiver.onAuthenticationSucceeded(
|
||||||
Utils.getAuthenticationTypeForResult(reason));
|
Utils.getAuthenticationTypeForResult(reason));
|
||||||
cancelBiometricOnly();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BiometricPrompt.DISMISSED_REASON_NEGATIVE:
|
case BiometricPrompt.DISMISSED_REASON_NEGATIVE:
|
||||||
mClientReceiver.onDialogDismissed(reason);
|
mClientReceiver.onDialogDismissed(reason);
|
||||||
cancelBiometricOnly();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BiometricPrompt.DISMISSED_REASON_USER_CANCEL:
|
case BiometricPrompt.DISMISSED_REASON_USER_CANCEL:
|
||||||
@@ -747,7 +746,6 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
|||||||
BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
|
BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
|
||||||
0 /* vendorCode */
|
0 /* vendorCode */
|
||||||
);
|
);
|
||||||
cancelBiometricOnly();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED:
|
case BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED:
|
||||||
@@ -765,6 +763,9 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
|||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Slog.e(TAG, "Remote exception", e);
|
Slog.e(TAG, "Remote exception", e);
|
||||||
|
} finally {
|
||||||
|
// ensure everything is cleaned up when dismissed
|
||||||
|
cancelAllSensors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,8 +781,8 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
|||||||
|| mState == STATE_AUTH_STARTED
|
|| mState == STATE_AUTH_STARTED
|
||||||
|| mState == STATE_AUTH_STARTED_UI_SHOWING;
|
|| mState == STATE_AUTH_STARTED_UI_SHOWING;
|
||||||
|
|
||||||
if (authStarted && !force) {
|
|
||||||
cancelAllSensors();
|
cancelAllSensors();
|
||||||
|
if (authStarted && !force) {
|
||||||
// Wait for ERROR_CANCELED to be returned from the sensors
|
// Wait for ERROR_CANCELED to be returned from the sensors
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@@ -804,22 +805,6 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancels biometric authentication only. AuthSession may either be going into
|
|
||||||
* {@link #STATE_SHOWING_DEVICE_CREDENTIAL} or dismissed.
|
|
||||||
*/
|
|
||||||
private void cancelBiometricOnly() {
|
|
||||||
if (mState == STATE_AUTH_STARTED || mState == STATE_AUTH_STARTED_UI_SHOWING) {
|
|
||||||
cancelAllSensors();
|
|
||||||
} else if (mMultiSensorMode == BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT) {
|
|
||||||
cancelAllFingerprintSensors();
|
|
||||||
} else {
|
|
||||||
if (DEBUG) {
|
|
||||||
Slog.v(TAG, "nothing to cancel - wrong state: " + mState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isCrypto() {
|
boolean isCrypto() {
|
||||||
return mOperationId != 0;
|
return mOperationId != 0;
|
||||||
}
|
}
|
||||||
@@ -896,13 +881,6 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldErrorTriggerMultiSensorTransition() {
|
|
||||||
if (mMultiSensorMode == BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT) {
|
|
||||||
return mMultiSensorState == MULTI_SENSOR_STATE_FACE_SCANNING;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@BiometricMultiSensorMode
|
@BiometricMultiSensorMode
|
||||||
private static int getMultiSensorModeForNewSession(Collection<BiometricSensor> sensors) {
|
private static int getMultiSensorModeForNewSession(Collection<BiometricSensor> sensors) {
|
||||||
boolean hasFace = false;
|
boolean hasFace = false;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.server.biometrics;
|
|||||||
|
|
||||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
|
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
|
||||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||||
|
import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_NEGATIVE;
|
||||||
|
|
||||||
import static com.android.server.biometrics.BiometricServiceStateProto.*;
|
import static com.android.server.biometrics.BiometricServiceStateProto.*;
|
||||||
|
|
||||||
@@ -38,7 +39,6 @@ import android.annotation.NonNull;
|
|||||||
import android.app.admin.DevicePolicyManager;
|
import android.app.admin.DevicePolicyManager;
|
||||||
import android.app.trust.ITrustManager;
|
import android.app.trust.ITrustManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.hardware.biometrics.BiometricConstants;
|
|
||||||
import android.hardware.biometrics.BiometricManager.Authenticators;
|
import android.hardware.biometrics.BiometricManager.Authenticators;
|
||||||
import android.hardware.biometrics.ComponentInfoInternal;
|
import android.hardware.biometrics.ComponentInfoInternal;
|
||||||
import android.hardware.biometrics.IBiometricAuthenticator;
|
import android.hardware.biometrics.IBiometricAuthenticator;
|
||||||
@@ -67,6 +67,7 @@ import org.mockito.MockitoAnnotations;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@Presubmit
|
@Presubmit
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@@ -245,9 +246,6 @@ public class AuthSessionTest {
|
|||||||
assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState());
|
assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState());
|
||||||
assertEquals(BiometricSensor.STATE_COOKIE_RETURNED,
|
assertEquals(BiometricSensor.STATE_COOKIE_RETURNED,
|
||||||
session.mPreAuthInfo.eligibleSensors.get(fingerprintSensorId).getSensorState());
|
session.mPreAuthInfo.eligibleSensors.get(fingerprintSensorId).getSensorState());
|
||||||
session.onErrorReceived(fingerprintSensorId,
|
|
||||||
session.mPreAuthInfo.eligibleSensors.get(fingerprintSensorId).getCookie(),
|
|
||||||
BiometricConstants.BIOMETRIC_ERROR_VENDOR, 0 /* vendorCode */);
|
|
||||||
session.onStartFingerprint();
|
session.onStartFingerprint();
|
||||||
}
|
}
|
||||||
assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState());
|
assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState());
|
||||||
@@ -258,6 +256,21 @@ public class AuthSessionTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCancelAuthentication_whenStateAuthCalled_invokesCancel()
|
public void testCancelAuthentication_whenStateAuthCalled_invokesCancel()
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
|
testInvokesCancel(session -> session.onCancelAuthSession(false /* force */));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCancelAuthentication_whenStateAuthForcedCalled_invokesCancel()
|
||||||
|
throws RemoteException {
|
||||||
|
testInvokesCancel(session -> session.onCancelAuthSession(true /* force */));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCancelAuthentication_whenDialogDismissed() throws RemoteException {
|
||||||
|
testInvokesCancel(session -> session.onDialogDismissed(DISMISSED_REASON_NEGATIVE, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testInvokesCancel(Consumer<AuthSession> sessionConsumer) throws RemoteException {
|
||||||
final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
|
final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
|
||||||
|
|
||||||
setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator);
|
setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator);
|
||||||
@@ -269,7 +282,8 @@ public class AuthSessionTest {
|
|||||||
|
|
||||||
session.goToInitialState();
|
session.goToInitialState();
|
||||||
assertEquals(STATE_AUTH_CALLED, session.getState());
|
assertEquals(STATE_AUTH_CALLED, session.getState());
|
||||||
session.onCancelAuthSession(false /* force */);
|
|
||||||
|
sessionConsumer.accept(session);
|
||||||
|
|
||||||
verify(faceAuthenticator).cancelAuthenticationFromService(eq(mToken), eq(TEST_PACKAGE));
|
verify(faceAuthenticator).cancelAuthenticationFromService(eq(mToken), eq(TEST_PACKAGE));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1036,7 +1036,7 @@ public class BiometricServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDismissedReasonNegative_whilePaused_doesntInvokeHalCancel() throws Exception {
|
public void testDismissedReasonNegative_whilePaused_invokeHalCancel() throws Exception {
|
||||||
setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
|
setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
|
||||||
invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
|
invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
|
||||||
false /* requireConfirmation */, null /* authenticators */);
|
false /* requireConfirmation */, null /* authenticators */);
|
||||||
@@ -1050,14 +1050,12 @@ public class BiometricServiceTest {
|
|||||||
BiometricPrompt.DISMISSED_REASON_NEGATIVE, null /* credentialAttestation */);
|
BiometricPrompt.DISMISSED_REASON_NEGATIVE, null /* credentialAttestation */);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
|
|
||||||
verify(mBiometricService.mSensors.get(0).impl,
|
verify(mBiometricService.mSensors.get(0).impl)
|
||||||
never()).cancelAuthenticationFromService(
|
.cancelAuthenticationFromService(any(), any());
|
||||||
any(),
|
|
||||||
any());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDismissedReasonUserCancel_whilePaused_doesntInvokeHalCancel() throws
|
public void testDismissedReasonUserCancel_whilePaused_invokesHalCancel() throws
|
||||||
Exception {
|
Exception {
|
||||||
setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
|
setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
|
||||||
invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
|
invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
|
||||||
@@ -1072,10 +1070,8 @@ public class BiometricServiceTest {
|
|||||||
BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */);
|
BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
|
|
||||||
verify(mBiometricService.mSensors.get(0).impl,
|
verify(mBiometricService.mSensors.get(0).impl)
|
||||||
never()).cancelAuthenticationFromService(
|
.cancelAuthenticationFromService(any(), any());
|
||||||
any(),
|
|
||||||
any());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1091,11 +1087,8 @@ public class BiometricServiceTest {
|
|||||||
BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */);
|
BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
|
|
||||||
// doesn't send cancel to HAL
|
verify(mBiometricService.mSensors.get(0).impl)
|
||||||
verify(mBiometricService.mSensors.get(0).impl,
|
.cancelAuthenticationFromService(any(), any());
|
||||||
never()).cancelAuthenticationFromService(
|
|
||||||
any(),
|
|
||||||
any());
|
|
||||||
verify(mReceiver1).onError(
|
verify(mReceiver1).onError(
|
||||||
eq(BiometricAuthenticator.TYPE_FACE),
|
eq(BiometricAuthenticator.TYPE_FACE),
|
||||||
eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED),
|
eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED),
|
||||||
|
|||||||
Reference in New Issue
Block a user