Loading packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +11 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) { Loading @@ -533,8 +535,14 @@ public abstract class AuthBiometricView extends LinearLayout implements AuthBiom } announceForAccessibility(getResources() .getString(R.string.biometric_dialog_authenticated)); 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: Loading packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +3 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading services/core/java/com/android/server/biometrics/AuthSession.java +54 −18 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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 */); Loading Loading @@ -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(), Loading @@ -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 Loading @@ -739,7 +773,8 @@ public final class AuthSession implements IBinder.DeathRecipient { + ", Latency: " + latency); } // Auth canceled BiometricFrameworkStatsLogger.getInstance().error( if (error != 0) { mBiometricFrameworkStatsLogger.error( mBiometricContext.updateContext(new OperationContextExt(true /* isBP */), isCrypto()), statsModality(), Loading @@ -752,6 +787,7 @@ public final class AuthSession implements IBinder.DeathRecipient { mUserId); } } } void onDialogDismissed(@BiometricPrompt.DismissedReason int reason, @Nullable byte[] credentialAttestation) { Loading services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java +88 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 { Loading Loading @@ -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) { Loading Loading
packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +11 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) { Loading @@ -533,8 +535,14 @@ public abstract class AuthBiometricView extends LinearLayout implements AuthBiom } announceForAccessibility(getResources() .getString(R.string.biometric_dialog_authenticated)); 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: Loading
packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +3 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading
packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
services/core/java/com/android/server/biometrics/AuthSession.java +54 −18 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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 */); Loading Loading @@ -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(), Loading @@ -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 Loading @@ -739,7 +773,8 @@ public final class AuthSession implements IBinder.DeathRecipient { + ", Latency: " + latency); } // Auth canceled BiometricFrameworkStatsLogger.getInstance().error( if (error != 0) { mBiometricFrameworkStatsLogger.error( mBiometricContext.updateContext(new OperationContextExt(true /* isBP */), isCrypto()), statsModality(), Loading @@ -752,6 +787,7 @@ public final class AuthSession implements IBinder.DeathRecipient { mUserId); } } } void onDialogDismissed(@BiometricPrompt.DismissedReason int reason, @Nullable byte[] credentialAttestation) { Loading
services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java +88 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 { Loading Loading @@ -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) { Loading