Merge "Added the view dismissed reason due to confirm button pressing" into udc-dev
This commit is contained in:
@@ -109,6 +109,7 @@ public abstract class AuthBiometricView extends LinearLayout implements AuthBiom
|
||||
int ACTION_ERROR = 5;
|
||||
int ACTION_USE_DEVICE_CREDENTIAL = 6;
|
||||
int ACTION_START_DELAYED_FINGERPRINT_SENSOR = 7;
|
||||
int ACTION_AUTHENTICATED_AND_CONFIRMED = 8;
|
||||
|
||||
/**
|
||||
* When an action has occurred. The caller will only invoke this when the callback should
|
||||
@@ -509,7 +510,8 @@ public abstract class AuthBiometricView extends LinearLayout implements AuthBiom
|
||||
}
|
||||
|
||||
public void updateState(@BiometricState int newState) {
|
||||
Log.v(TAG, "newState: " + newState);
|
||||
Log.d(TAG, "newState: " + newState);
|
||||
|
||||
mIconController.updateState(mState, newState);
|
||||
|
||||
switch (newState) {
|
||||
@@ -533,8 +535,14 @@ public abstract class AuthBiometricView extends LinearLayout implements AuthBiom
|
||||
}
|
||||
announceForAccessibility(getResources()
|
||||
.getString(R.string.biometric_dialog_authenticated));
|
||||
mHandler.postDelayed(() -> mCallback.onAction(Callback.ACTION_AUTHENTICATED),
|
||||
getDelayAfterAuthenticatedDurationMs());
|
||||
if (mState == STATE_PENDING_CONFIRMATION) {
|
||||
mHandler.postDelayed(() -> mCallback.onAction(
|
||||
Callback.ACTION_AUTHENTICATED_AND_CONFIRMED),
|
||||
getDelayAfterAuthenticatedDurationMs());
|
||||
} else {
|
||||
mHandler.postDelayed(() -> mCallback.onAction(Callback.ACTION_AUTHENTICATED),
|
||||
getDelayAfterAuthenticatedDurationMs());
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_PENDING_CONFIRMATION:
|
||||
|
||||
@@ -213,6 +213,9 @@ public class AuthContainerView extends LinearLayout
|
||||
case AuthBiometricView.Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR:
|
||||
mConfig.mCallback.onStartFingerprintNow(getRequestId());
|
||||
break;
|
||||
case AuthBiometricView.Callback.ACTION_AUTHENTICATED_AND_CONFIRMED:
|
||||
animateAway(AuthDialogCallback.DISMISSED_BUTTON_POSITIVE);
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Unhandled action: " + action);
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() {
|
||||
waitForIdleSync()
|
||||
|
||||
assertThat(biometricView.isAuthenticated).isTrue()
|
||||
verify(callback).onAction(AuthBiometricView.Callback.ACTION_AUTHENTICATED)
|
||||
verify(callback).onAction(AuthBiometricView.Callback.ACTION_AUTHENTICATED_AND_CONFIRMED)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -76,7 +76,7 @@ import java.util.function.Function;
|
||||
*/
|
||||
public final class AuthSession implements IBinder.DeathRecipient {
|
||||
private static final String TAG = "BiometricService/AuthSession";
|
||||
private static final boolean DEBUG = false;
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
/*
|
||||
* Defined in biometrics.proto
|
||||
@@ -118,6 +118,7 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
||||
@VisibleForTesting final IBinder mToken;
|
||||
// Info to be shown on BiometricDialog when all cookies are returned.
|
||||
@VisibleForTesting final PromptInfo mPromptInfo;
|
||||
@VisibleForTesting final BiometricFrameworkStatsLogger mBiometricFrameworkStatsLogger;
|
||||
private final long mRequestId;
|
||||
private final long mOperationId;
|
||||
private final int mUserId;
|
||||
@@ -164,6 +165,32 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
||||
@NonNull PromptInfo promptInfo,
|
||||
boolean debugEnabled,
|
||||
@NonNull List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties) {
|
||||
this(context, biometricContext, statusBarService, sysuiReceiver, keystore, random,
|
||||
clientDeathReceiver, preAuthInfo, token, requestId, operationId, userId,
|
||||
sensorReceiver, clientReceiver, opPackageName, promptInfo, debugEnabled,
|
||||
fingerprintSensorProperties, BiometricFrameworkStatsLogger.getInstance());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
AuthSession(@NonNull Context context,
|
||||
@NonNull BiometricContext biometricContext,
|
||||
@NonNull IStatusBarService statusBarService,
|
||||
@NonNull IBiometricSysuiReceiver sysuiReceiver,
|
||||
@NonNull KeyStore keystore,
|
||||
@NonNull Random random,
|
||||
@NonNull ClientDeathReceiver clientDeathReceiver,
|
||||
@NonNull PreAuthInfo preAuthInfo,
|
||||
@NonNull IBinder token,
|
||||
long requestId,
|
||||
long operationId,
|
||||
int userId,
|
||||
@NonNull IBiometricSensorReceiver sensorReceiver,
|
||||
@NonNull IBiometricServiceReceiver clientReceiver,
|
||||
@NonNull String opPackageName,
|
||||
@NonNull PromptInfo promptInfo,
|
||||
boolean debugEnabled,
|
||||
@NonNull List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties,
|
||||
@NonNull BiometricFrameworkStatsLogger logger) {
|
||||
Slog.d(TAG, "Creating AuthSession with: " + preAuthInfo);
|
||||
mContext = context;
|
||||
mBiometricContext = biometricContext;
|
||||
@@ -184,6 +211,7 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
||||
mDebugEnabled = debugEnabled;
|
||||
mFingerprintSensorProperties = fingerprintSensorProperties;
|
||||
mCancelled = false;
|
||||
mBiometricFrameworkStatsLogger = logger;
|
||||
|
||||
try {
|
||||
mClientReceiver.asBinder().linkToDeath(this, 0 /* flags */);
|
||||
@@ -708,7 +736,7 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
||||
+ ", Latency: " + latency);
|
||||
}
|
||||
|
||||
BiometricFrameworkStatsLogger.getInstance().authenticate(
|
||||
mBiometricFrameworkStatsLogger.authenticate(
|
||||
mBiometricContext.updateContext(new OperationContextExt(true /* isBP */),
|
||||
isCrypto()),
|
||||
statsModality(),
|
||||
@@ -723,11 +751,17 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
||||
} else {
|
||||
final long latency = System.currentTimeMillis() - mStartTimeMs;
|
||||
|
||||
int error = reason == BiometricPrompt.DISMISSED_REASON_NEGATIVE
|
||||
? BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON
|
||||
: reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL
|
||||
? BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED
|
||||
: 0;
|
||||
int error = 0;
|
||||
switch(reason) {
|
||||
case BiometricPrompt.DISMISSED_REASON_NEGATIVE:
|
||||
error = BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON;
|
||||
break;
|
||||
case BiometricPrompt.DISMISSED_REASON_USER_CANCEL:
|
||||
error = BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "Dismissed! Modality: " + statsModality()
|
||||
+ ", User: " + mUserId
|
||||
@@ -739,17 +773,19 @@ public final class AuthSession implements IBinder.DeathRecipient {
|
||||
+ ", Latency: " + latency);
|
||||
}
|
||||
// Auth canceled
|
||||
BiometricFrameworkStatsLogger.getInstance().error(
|
||||
mBiometricContext.updateContext(new OperationContextExt(true /* isBP */),
|
||||
isCrypto()),
|
||||
statsModality(),
|
||||
BiometricsProtoEnums.ACTION_AUTHENTICATE,
|
||||
BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
|
||||
mDebugEnabled,
|
||||
latency,
|
||||
error,
|
||||
0 /* vendorCode */,
|
||||
mUserId);
|
||||
if (error != 0) {
|
||||
mBiometricFrameworkStatsLogger.error(
|
||||
mBiometricContext.updateContext(new OperationContextExt(true /* isBP */),
|
||||
isCrypto()),
|
||||
statsModality(),
|
||||
BiometricsProtoEnums.ACTION_AUTHENTICATE,
|
||||
BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
|
||||
mDebugEnabled,
|
||||
latency,
|
||||
error,
|
||||
0 /* vendorCode */,
|
||||
mUserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ package com.android.server.biometrics;
|
||||
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
|
||||
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON;
|
||||
import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED;
|
||||
import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED;
|
||||
import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_NEGATIVE;
|
||||
|
||||
import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_CALLED;
|
||||
@@ -32,6 +35,7 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyObject;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -45,6 +49,7 @@ import android.app.trust.ITrustManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.biometrics.BiometricManager.Authenticators;
|
||||
import android.hardware.biometrics.BiometricsProtoEnums;
|
||||
import android.hardware.biometrics.ComponentInfoInternal;
|
||||
import android.hardware.biometrics.IBiometricAuthenticator;
|
||||
import android.hardware.biometrics.IBiometricSensorReceiver;
|
||||
@@ -64,7 +69,10 @@ import android.security.KeyStore;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.server.biometrics.log.BiometricContext;
|
||||
import com.android.server.biometrics.log.BiometricFrameworkStatsLogger;
|
||||
import com.android.server.biometrics.log.OperationContextExt;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -95,6 +103,7 @@ public class AuthSessionTest {
|
||||
@Mock private IBiometricSysuiReceiver mSysuiReceiver;
|
||||
@Mock private KeyStore mKeyStore;
|
||||
@Mock private AuthSession.ClientDeathReceiver mClientDeathReceiver;
|
||||
@Mock private BiometricFrameworkStatsLogger mBiometricFrameworkStatsLogger;
|
||||
|
||||
private Random mRandom;
|
||||
private IBinder mToken;
|
||||
@@ -395,6 +404,84 @@ public class AuthSessionTest {
|
||||
eq(FingerprintManager.FINGERPRINT_ACQUIRED_VENDOR_BASE), eq(acquiredStrVendor));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLogOnDialogDismissed_authenticatedWithConfirmation() throws RemoteException {
|
||||
final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
|
||||
|
||||
setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator);
|
||||
final AuthSession session = createAuthSession(mSensors,
|
||||
false /* checkDevicePolicyManager */,
|
||||
Authenticators.BIOMETRIC_STRONG,
|
||||
TEST_REQUEST_ID,
|
||||
0 /* operationId */,
|
||||
0 /* userId */);
|
||||
session.goToInitialState();
|
||||
assertEquals(STATE_AUTH_CALLED, session.getState());
|
||||
|
||||
session.onDialogDismissed(DISMISSED_REASON_BIOMETRIC_CONFIRMED, null);
|
||||
verify(mBiometricFrameworkStatsLogger, times(1)).authenticate(
|
||||
(OperationContextExt) anyObject(),
|
||||
eq(BiometricsProtoEnums.MODALITY_FACE),
|
||||
eq(BiometricsProtoEnums.ACTION_UNKNOWN),
|
||||
eq(BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT),
|
||||
eq(false), /* debugEnabled */
|
||||
anyLong(), /* latency */
|
||||
eq(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED),
|
||||
eq(true), /* confirmationRequired */
|
||||
eq(0) /* userId */,
|
||||
eq(-1f) /* ambientLightLux */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLogOnDialogDismissed_authenticatedWithoutConfirmation() throws RemoteException {
|
||||
final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
|
||||
|
||||
setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator);
|
||||
final AuthSession session = createAuthSession(mSensors,
|
||||
false /* checkDevicePolicyManager */,
|
||||
Authenticators.BIOMETRIC_STRONG,
|
||||
TEST_REQUEST_ID,
|
||||
0 /* operationId */,
|
||||
0 /* userId */);
|
||||
session.goToInitialState();
|
||||
assertEquals(STATE_AUTH_CALLED, session.getState());
|
||||
|
||||
session.onDialogDismissed(DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED, null);
|
||||
verify(mBiometricFrameworkStatsLogger, never()).authenticate(
|
||||
anyObject(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyLong(), anyInt(),
|
||||
anyBoolean(), anyInt(), eq(-1f));
|
||||
verify(mBiometricFrameworkStatsLogger, never()).error(
|
||||
anyObject(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyLong(), anyInt(),
|
||||
anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLogOnDialogDismissed_error() throws RemoteException {
|
||||
final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
|
||||
|
||||
setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator);
|
||||
final AuthSession session = createAuthSession(mSensors,
|
||||
false /* checkDevicePolicyManager */,
|
||||
Authenticators.BIOMETRIC_STRONG,
|
||||
TEST_REQUEST_ID,
|
||||
0 /* operationId */,
|
||||
0 /* userId */);
|
||||
session.goToInitialState();
|
||||
assertEquals(STATE_AUTH_CALLED, session.getState());
|
||||
|
||||
session.onDialogDismissed(DISMISSED_REASON_NEGATIVE, null);
|
||||
verify(mBiometricFrameworkStatsLogger, times(1)).error(
|
||||
(OperationContextExt) anyObject(),
|
||||
eq(BiometricsProtoEnums.MODALITY_FACE),
|
||||
eq(BiometricsProtoEnums.ACTION_AUTHENTICATE),
|
||||
eq(BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT),
|
||||
eq(false),
|
||||
anyLong(),
|
||||
eq(BIOMETRIC_ERROR_NEGATIVE_BUTTON),
|
||||
eq(0) /* vendorCode */,
|
||||
eq(0) /* userId */);
|
||||
}
|
||||
|
||||
// TODO (b/208484275) : Enable these tests
|
||||
// @Test
|
||||
// public void testPreAuth_canAuthAndPrivacyDisabled() throws Exception {
|
||||
@@ -498,7 +585,7 @@ public class AuthSessionTest {
|
||||
return new AuthSession(mContext, mBiometricContext, mStatusBarService, mSysuiReceiver,
|
||||
mKeyStore, mRandom, mClientDeathReceiver, preAuthInfo, mToken, requestId,
|
||||
operationId, userId, mSensorReceiver, mClientReceiver, TEST_PACKAGE, promptInfo,
|
||||
false /* debugEnabled */, mFingerprintSensorProps);
|
||||
false /* debugEnabled */, mFingerprintSensorProps, mBiometricFrameworkStatsLogger);
|
||||
}
|
||||
|
||||
private PromptInfo createPromptInfo(@Authenticators.Types int authenticators) {
|
||||
|
||||
Reference in New Issue
Block a user