1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.biometrics; 18 19 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; 20 import static android.hardware.biometrics.BiometricManager.Authenticators; 21 import static android.hardware.biometrics.BiometricManager.BIOMETRIC_MULTI_SENSOR_DEFAULT; 22 23 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTHENTICATED_PENDING_SYSUI; 24 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_CALLED; 25 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_PAUSED; 26 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_PAUSED_RESUMING; 27 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_PENDING_CONFIRM; 28 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED; 29 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_CLIENT_DIED_CANCELLING; 30 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_ERROR_PENDING_SYSUI; 31 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_SHOWING_DEVICE_CREDENTIAL; 32 33 import static junit.framework.Assert.assertEquals; 34 import static junit.framework.Assert.assertFalse; 35 import static junit.framework.Assert.assertTrue; 36 import static junit.framework.TestCase.assertNotNull; 37 38 import static org.junit.Assert.assertNotEquals; 39 import static org.junit.Assert.assertNull; 40 import static org.mockito.ArgumentMatchers.any; 41 import static org.mockito.ArgumentMatchers.anyBoolean; 42 import static org.mockito.ArgumentMatchers.anyInt; 43 import static org.mockito.ArgumentMatchers.anyLong; 44 import static org.mockito.ArgumentMatchers.anyString; 45 import static org.mockito.ArgumentMatchers.eq; 46 import static org.mockito.Mockito.mock; 47 import static org.mockito.Mockito.never; 48 import static org.mockito.Mockito.verify; 49 import static org.mockito.Mockito.when; 50 51 import android.app.IActivityManager; 52 import android.app.admin.DevicePolicyManager; 53 import android.app.trust.ITrustManager; 54 import android.content.ContentResolver; 55 import android.content.Context; 56 import android.content.res.Resources; 57 import android.hardware.biometrics.BiometricAuthenticator; 58 import android.hardware.biometrics.BiometricConstants; 59 import android.hardware.biometrics.BiometricManager; 60 import android.hardware.biometrics.BiometricPrompt; 61 import android.hardware.biometrics.IBiometricAuthenticator; 62 import android.hardware.biometrics.IBiometricSensorReceiver; 63 import android.hardware.biometrics.IBiometricService; 64 import android.hardware.biometrics.IBiometricServiceReceiver; 65 import android.hardware.biometrics.IBiometricSysuiReceiver; 66 import android.hardware.biometrics.PromptInfo; 67 import android.hardware.fingerprint.FingerprintManager; 68 import android.os.Binder; 69 import android.os.IBinder; 70 import android.os.RemoteException; 71 import android.platform.test.annotations.Presubmit; 72 import android.security.KeyStore; 73 74 import androidx.test.InstrumentationRegistry; 75 import androidx.test.filters.SmallTest; 76 77 import com.android.internal.R; 78 import com.android.internal.statusbar.IStatusBarService; 79 import com.android.server.biometrics.sensors.LockoutTracker; 80 81 import org.junit.Before; 82 import org.junit.Test; 83 import org.mockito.AdditionalMatchers; 84 import org.mockito.ArgumentCaptor; 85 import org.mockito.Mock; 86 import org.mockito.MockitoAnnotations; 87 88 import java.util.Random; 89 90 @Presubmit 91 @SmallTest 92 public class BiometricServiceTest { 93 94 private static final String TEST_PACKAGE_NAME = "test_package"; 95 private static final long TEST_REQUEST_ID = 44; 96 97 private static final String ERROR_HW_UNAVAILABLE = "hw_unavailable"; 98 private static final String ERROR_NOT_RECOGNIZED = "not_recognized"; 99 private static final String ERROR_TIMEOUT = "error_timeout"; 100 private static final String ERROR_CANCELED = "error_canceled"; 101 private static final String ERROR_UNABLE_TO_PROCESS = "error_unable_to_process"; 102 private static final String ERROR_USER_CANCELED = "error_user_canceled"; 103 private static final String ERROR_LOCKOUT = "error_lockout"; 104 105 private static final String FINGERPRINT_ACQUIRED_SENSOR_DIRTY = "sensor_dirty"; 106 107 private static final int SENSOR_ID_FINGERPRINT = 0; 108 private static final int SENSOR_ID_FACE = 1; 109 110 private BiometricService mBiometricService; 111 112 @Mock 113 private Context mContext; 114 @Mock 115 private ContentResolver mContentResolver; 116 @Mock 117 private Resources mResources; 118 @Mock 119 IBiometricServiceReceiver mReceiver1; 120 @Mock 121 IBiometricServiceReceiver mReceiver2; 122 @Mock 123 BiometricService.Injector mInjector; 124 @Mock 125 IBiometricAuthenticator mFingerprintAuthenticator; 126 @Mock 127 IBiometricAuthenticator mFaceAuthenticator; 128 @Mock 129 ITrustManager mTrustManager; 130 @Mock 131 DevicePolicyManager mDevicePolicyManager; 132 133 @Before setUp()134 public void setUp() { 135 MockitoAnnotations.initMocks(this); 136 137 resetReceivers(); 138 139 when(mContext.getContentResolver()).thenReturn(mContentResolver); 140 when(mContext.getResources()).thenReturn(mResources); 141 when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)) 142 .thenReturn(mDevicePolicyManager); 143 144 when(mInjector.getActivityManagerService()).thenReturn(mock(IActivityManager.class)); 145 when(mInjector.getStatusBarService()).thenReturn(mock(IStatusBarService.class)); 146 when(mInjector.getSettingObserver(any(), any(), any())) 147 .thenReturn(mock(BiometricService.SettingObserver.class)); 148 when(mInjector.getKeyStore()).thenReturn(mock(KeyStore.class)); 149 when(mInjector.isDebugEnabled(any(), anyInt())).thenReturn(false); 150 when(mInjector.getBiometricStrengthController(any())) 151 .thenReturn(mock(BiometricStrengthController.class)); 152 when(mInjector.getTrustManager()).thenReturn(mTrustManager); 153 when(mInjector.getDevicePolicyManager(any())).thenReturn(mDevicePolicyManager); 154 when(mInjector.getRequestGenerator()).thenReturn(() -> TEST_REQUEST_ID); 155 156 when(mResources.getString(R.string.biometric_error_hw_unavailable)) 157 .thenReturn(ERROR_HW_UNAVAILABLE); 158 when(mResources.getString(R.string.biometric_not_recognized)) 159 .thenReturn(ERROR_NOT_RECOGNIZED); 160 when(mResources.getString(R.string.biometric_error_user_canceled)) 161 .thenReturn(ERROR_USER_CANCELED); 162 163 final String[] config = { 164 "0:2:15", // ID0:Fingerprint:Strong 165 "1:8:15", // ID1:Face:Strong 166 "2:4:255", // ID2:Iris:Weak 167 }; 168 169 when(mInjector.getConfiguration(any())).thenReturn(config); 170 } 171 172 @Test testClientBinderDied_whenPaused()173 public void testClientBinderDied_whenPaused() throws Exception { 174 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 175 176 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 177 true /* requireConfirmation */, null /* authenticators */); 178 waitForIdle(); 179 verify(mReceiver1.asBinder()).linkToDeath(eq(mBiometricService.mAuthSession), 180 anyInt()); 181 182 mBiometricService.mAuthSession.mSensorReceiver.onError( 183 SENSOR_ID_FACE, 184 getCookieForCurrentSession(mBiometricService.mAuthSession), 185 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT, 186 0 /* vendorCode */); 187 waitForIdle(); 188 189 assertEquals(STATE_AUTH_PAUSED, mBiometricService.mAuthSession.getState()); 190 191 mBiometricService.mAuthSession.binderDied(); 192 waitForIdle(); 193 194 assertNull(mBiometricService.mAuthSession); 195 verify(mBiometricService.mStatusBarService).hideAuthenticationDialog(eq(TEST_REQUEST_ID)); 196 verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); 197 } 198 199 @Test testClientBinderDied_whenAuthenticating()200 public void testClientBinderDied_whenAuthenticating() throws Exception { 201 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 202 203 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 204 true /* requireConfirmation */, null /* authenticators */); 205 waitForIdle(); 206 verify(mReceiver1.asBinder()).linkToDeath(eq(mBiometricService.mAuthSession), 207 anyInt()); 208 209 assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState()); 210 mBiometricService.mAuthSession.binderDied(); 211 waitForIdle(); 212 213 assertNotNull(mBiometricService.mAuthSession); 214 verify(mBiometricService.mStatusBarService, never()) 215 .hideAuthenticationDialog(eq(TEST_REQUEST_ID)); 216 assertEquals(STATE_CLIENT_DIED_CANCELLING, 217 mBiometricService.mAuthSession.getState()); 218 219 verify(mBiometricService.mAuthSession.mPreAuthInfo.eligibleSensors.get(0).impl) 220 .cancelAuthenticationFromService(any(), any(), anyLong()); 221 222 // Simulate ERROR_CANCELED received from HAL 223 mBiometricService.mAuthSession.mSensorReceiver.onError( 224 SENSOR_ID_FACE, 225 getCookieForCurrentSession(mBiometricService.mAuthSession), 226 BiometricConstants.BIOMETRIC_ERROR_CANCELED, 227 0 /* vendorCode */); 228 waitForIdle(); 229 verify(mBiometricService.mStatusBarService).hideAuthenticationDialog(eq(TEST_REQUEST_ID)); 230 verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); 231 assertNull(mBiometricService.mAuthSession); 232 } 233 234 @Test testAuthenticate_credentialAllowedButNotSetup_returnsNoDeviceCredential()235 public void testAuthenticate_credentialAllowedButNotSetup_returnsNoDeviceCredential() 236 throws Exception { 237 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) 238 .thenReturn(false); 239 240 mBiometricService = new BiometricService(mContext, mInjector); 241 mBiometricService.onStart(); 242 243 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, 244 Authenticators.DEVICE_CREDENTIAL); 245 waitForIdle(); 246 verify(mReceiver1).onError( 247 eq(BiometricAuthenticator.TYPE_CREDENTIAL), 248 eq(BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL), 249 eq(0 /* vendorCode */)); 250 } 251 252 @Test testAuthenticate_credentialAllowedAndSetup_callsSystemUI()253 public void testAuthenticate_credentialAllowedAndSetup_callsSystemUI() throws Exception { 254 // When no biometrics are enrolled, but credentials are set up, status bar should be 255 // invoked right away with showAuthenticationDialog 256 257 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) 258 .thenReturn(true); 259 260 mBiometricService = new BiometricService(mContext, mInjector); 261 mBiometricService.onStart(); 262 263 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, 264 Authenticators.DEVICE_CREDENTIAL); 265 waitForIdle(); 266 267 assertNotNull(mBiometricService.mAuthSession); 268 assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL, 269 mBiometricService.mAuthSession.getState()); 270 // StatusBar showBiometricDialog invoked 271 verify(mBiometricService.mStatusBarService).showAuthenticationDialog( 272 eq(mBiometricService.mAuthSession.mPromptInfo), 273 any(IBiometricSysuiReceiver.class), 274 AdditionalMatchers.aryEq(new int[0]) /* sensorIds */, 275 eq(true) /* credentialAllowed */, 276 anyBoolean() /* requireConfirmation */, 277 anyInt() /* userId */, 278 anyLong() /* operationId */, 279 eq(TEST_PACKAGE_NAME), 280 eq(TEST_REQUEST_ID), 281 eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); 282 } 283 284 @Test testAuthenticate_withoutHardware_returnsErrorHardwareNotPresent()285 public void testAuthenticate_withoutHardware_returnsErrorHardwareNotPresent() throws 286 Exception { 287 mBiometricService = new BiometricService(mContext, mInjector); 288 mBiometricService.onStart(); 289 290 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, 291 null /* authenticators */); 292 waitForIdle(); 293 verify(mReceiver1).onError( 294 eq(BiometricAuthenticator.TYPE_NONE), 295 eq(BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT), 296 eq(0 /* vendorCode */)); 297 } 298 299 @Test testAuthenticate_withoutEnrolled_returnsErrorNoBiometrics()300 public void testAuthenticate_withoutEnrolled_returnsErrorNoBiometrics() throws Exception { 301 when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true); 302 303 mBiometricService = new BiometricService(mContext, mInjector); 304 mBiometricService.onStart(); 305 mBiometricService.mImpl.registerAuthenticator(0 /* id */, 306 TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG, 307 mFingerprintAuthenticator); 308 309 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, 310 null /* authenticators */); 311 waitForIdle(); 312 verify(mReceiver1).onError( 313 eq(TYPE_FINGERPRINT), 314 eq(BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS), 315 eq(0 /* vendorCode */)); 316 } 317 318 @Test testAuthenticate_notStrongEnough_returnsHardwareNotPresent()319 public void testAuthenticate_notStrongEnough_returnsHardwareNotPresent() throws Exception { 320 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_WEAK); 321 322 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, 323 Authenticators.BIOMETRIC_STRONG); 324 waitForIdle(); 325 verify(mReceiver1).onError( 326 eq(BiometricAuthenticator.TYPE_NONE), 327 eq(BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT), 328 eq(0 /* vendorCode */)); 329 } 330 331 @Test testAuthenticate_picksStrongIfAvailable()332 public void testAuthenticate_picksStrongIfAvailable() throws Exception { 333 // If both strong and weak are available, and the caller requires STRONG, authentication 334 // is able to proceed. 335 336 final int[] modalities = new int[] { 337 TYPE_FINGERPRINT, 338 BiometricAuthenticator.TYPE_FACE, 339 }; 340 341 final int[] strengths = new int[] { 342 Authenticators.BIOMETRIC_WEAK, 343 Authenticators.BIOMETRIC_STRONG, 344 }; 345 346 setupAuthForMultiple(modalities, strengths); 347 348 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 349 false /* requireConfirmation */, Authenticators.BIOMETRIC_STRONG); 350 waitForIdle(); 351 verify(mReceiver1, never()).onError( 352 anyInt(), 353 anyInt(), 354 anyInt() /* vendorCode */); 355 356 // StatusBar showBiometricDialog invoked with face, which was set up to be STRONG 357 verify(mBiometricService.mStatusBarService).showAuthenticationDialog( 358 eq(mBiometricService.mAuthSession.mPromptInfo), 359 any(IBiometricSysuiReceiver.class), 360 AdditionalMatchers.aryEq(new int[] {SENSOR_ID_FACE}), 361 eq(false) /* credentialAllowed */, 362 eq(false) /* requireConfirmation */, 363 anyInt() /* userId */, 364 anyLong() /* operationId */, 365 eq(TEST_PACKAGE_NAME), 366 eq(TEST_REQUEST_ID), 367 eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); 368 } 369 370 @Test testAuthenticate_whenHalIsDead_returnsErrorHardwareUnavailable()371 public void testAuthenticate_whenHalIsDead_returnsErrorHardwareUnavailable() throws 372 Exception { 373 when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); 374 when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(false); 375 376 mBiometricService = new BiometricService(mContext, mInjector); 377 mBiometricService.onStart(); 378 mBiometricService.mImpl.registerAuthenticator(0 /* id */, 379 TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG, 380 mFingerprintAuthenticator); 381 382 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, 383 null /* authenticators */); 384 waitForIdle(); 385 verify(mReceiver1).onError( 386 eq(TYPE_FINGERPRINT), 387 eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), 388 eq(0 /* vendorCode */)); 389 } 390 391 @Test testAuthenticateFace_respectsUserSetting()392 public void testAuthenticateFace_respectsUserSetting() 393 throws Exception { 394 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 395 396 // Disabled in user settings receives onError 397 when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false); 398 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, 399 null /* authenticators */); 400 waitForIdle(); 401 verify(mReceiver1).onError( 402 eq(BiometricAuthenticator.TYPE_NONE), 403 eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), 404 eq(0 /* vendorCode */)); 405 406 // Enrolled, not disabled in settings, user requires confirmation in settings 407 resetReceivers(); 408 when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true); 409 when(mBiometricService.mSettingObserver.getConfirmationAlwaysRequired( 410 anyInt() /* modality */, anyInt() /* userId */)) 411 .thenReturn(true); 412 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, 413 null /* authenticators */); 414 waitForIdle(); 415 verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); 416 final byte[] HAT = generateRandomHAT(); 417 mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationSucceeded( 418 SENSOR_ID_FACE, 419 HAT); 420 waitForIdle(); 421 // Confirmation is required 422 assertEquals(STATE_AUTH_PENDING_CONFIRM, 423 mBiometricService.mAuthSession.getState()); 424 425 // Enrolled, not disabled in settings, user doesn't require confirmation in settings 426 resetReceivers(); 427 when(mBiometricService.mSettingObserver.getConfirmationAlwaysRequired( 428 anyInt() /* modality */, anyInt() /* userId */)) 429 .thenReturn(false); 430 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, 431 null /* authenticators */); 432 waitForIdle(); 433 mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationSucceeded( 434 SENSOR_ID_FACE, 435 HAT); 436 waitForIdle(); 437 // Confirmation not required, waiting for dialog to dismiss 438 assertEquals(STATE_AUTHENTICATED_PENDING_SYSUI, 439 mBiometricService.mAuthSession.getState()); 440 441 } 442 443 @Test testAuthenticate_happyPathWithoutConfirmation_strongBiometric()444 public void testAuthenticate_happyPathWithoutConfirmation_strongBiometric() throws Exception { 445 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 446 testAuthenticate_happyPathWithoutConfirmation(true /* isStrongBiometric */); 447 } 448 449 @Test testAuthenticate_happyPathWithoutConfirmation_weakBiometric()450 public void testAuthenticate_happyPathWithoutConfirmation_weakBiometric() throws Exception { 451 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_WEAK); 452 testAuthenticate_happyPathWithoutConfirmation(false /* isStrongBiometric */); 453 } 454 testAuthenticate_happyPathWithoutConfirmation(boolean isStrongBiometric)455 private void testAuthenticate_happyPathWithoutConfirmation(boolean isStrongBiometric) 456 throws Exception { 457 // Start testing the happy path 458 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, 459 null /* authenticators */); 460 waitForIdle(); 461 462 // Creates a pending auth session with the correct initial states 463 assertEquals(STATE_AUTH_CALLED, mBiometricService.mAuthSession.getState()); 464 465 // Invokes <Modality>Service#prepareForAuthentication 466 ArgumentCaptor<Integer> cookieCaptor = ArgumentCaptor.forClass(Integer.class); 467 verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); 468 verify(mBiometricService.mSensors.get(0).impl).prepareForAuthentication( 469 eq(false) /* requireConfirmation */, 470 any(IBinder.class), 471 anyLong() /* sessionId */, 472 anyInt() /* userId */, 473 any(IBiometricSensorReceiver.class), 474 anyString() /* opPackageName */, 475 eq(TEST_REQUEST_ID), 476 cookieCaptor.capture() /* cookie */, 477 anyBoolean() /* allowBackgroundAuthentication */); 478 479 // onReadyForAuthentication, mAuthSession state OK 480 mBiometricService.mImpl.onReadyForAuthentication(TEST_REQUEST_ID, cookieCaptor.getValue()); 481 waitForIdle(); 482 assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState()); 483 484 // startPreparedClient invoked 485 mBiometricService.mAuthSession.onDialogAnimatedIn(); 486 verify(mBiometricService.mSensors.get(0).impl) 487 .startPreparedClient(cookieCaptor.getValue()); 488 489 // StatusBar showBiometricDialog invoked 490 verify(mBiometricService.mStatusBarService).showAuthenticationDialog( 491 eq(mBiometricService.mAuthSession.mPromptInfo), 492 any(IBiometricSysuiReceiver.class), 493 any(), 494 eq(false) /* credentialAllowed */, 495 anyBoolean() /* requireConfirmation */, 496 anyInt() /* userId */, 497 anyLong() /* operationId */, 498 eq(TEST_PACKAGE_NAME), 499 eq(TEST_REQUEST_ID), 500 eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); 501 502 // Hardware authenticated 503 final byte[] HAT = generateRandomHAT(); 504 mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationSucceeded( 505 SENSOR_ID_FINGERPRINT, 506 HAT); 507 waitForIdle(); 508 // Waiting for SystemUI to send dismissed callback 509 assertEquals(STATE_AUTHENTICATED_PENDING_SYSUI, 510 mBiometricService.mAuthSession.getState()); 511 // Notify SystemUI hardware authenticated 512 verify(mBiometricService.mStatusBarService).onBiometricAuthenticated(TYPE_FINGERPRINT); 513 514 // SystemUI sends callback with dismissed reason 515 mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed( 516 BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED, 517 null /* credentialAttestation */); 518 waitForIdle(); 519 // HAT sent to keystore 520 if (isStrongBiometric) { 521 verify(mBiometricService.mKeyStore).addAuthToken(AdditionalMatchers.aryEq(HAT)); 522 } else { 523 verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class)); 524 } 525 // Send onAuthenticated to client 526 verify(mReceiver1).onAuthenticationSucceeded( 527 BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC); 528 // Current session becomes null 529 assertNull(mBiometricService.mAuthSession); 530 } 531 532 @Test testAuthenticate_noBiometrics_credentialAllowed()533 public void testAuthenticate_noBiometrics_credentialAllowed() throws Exception { 534 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 535 when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false); 536 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) 537 .thenReturn(true); 538 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, 539 true /* requireConfirmation */, 540 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK); 541 waitForIdle(); 542 543 assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL, 544 mBiometricService.mAuthSession.getState()); 545 assertEquals(Authenticators.DEVICE_CREDENTIAL, 546 mBiometricService.mAuthSession.mPromptInfo.getAuthenticators()); 547 verify(mBiometricService.mStatusBarService).showAuthenticationDialog( 548 eq(mBiometricService.mAuthSession.mPromptInfo), 549 any(IBiometricSysuiReceiver.class), 550 AdditionalMatchers.aryEq(new int[0]) /* sensorIds */, 551 eq(true) /* credentialAllowed */, 552 anyBoolean() /* requireConfirmation */, 553 anyInt() /* userId */, 554 anyLong() /* operationId */, 555 eq(TEST_PACKAGE_NAME), 556 eq(TEST_REQUEST_ID), 557 eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); 558 } 559 560 @Test testAuthenticate_happyPathWithConfirmation_strongBiometric()561 public void testAuthenticate_happyPathWithConfirmation_strongBiometric() throws Exception { 562 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 563 testAuthenticate_happyPathWithConfirmation(true /* isStrongBiometric */); 564 } 565 566 @Test testAuthenticate_happyPathWithConfirmation_weakBiometric()567 public void testAuthenticate_happyPathWithConfirmation_weakBiometric() throws Exception { 568 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_WEAK); 569 testAuthenticate_happyPathWithConfirmation(false /* isStrongBiometric */); 570 } 571 testAuthenticate_happyPathWithConfirmation(boolean isStrongBiometric)572 private void testAuthenticate_happyPathWithConfirmation(boolean isStrongBiometric) 573 throws Exception { 574 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 575 true /* requireConfirmation */, null /* authenticators */); 576 577 // Test authentication succeeded goes to PENDING_CONFIRMATION and that the HAT is not 578 // sent to KeyStore yet 579 final byte[] HAT = generateRandomHAT(); 580 mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationSucceeded( 581 SENSOR_ID_FACE, 582 HAT); 583 waitForIdle(); 584 // Waiting for SystemUI to send confirmation callback 585 assertEquals(STATE_AUTH_PENDING_CONFIRM, mBiometricService.mAuthSession.getState()); 586 verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class)); 587 588 // SystemUI sends confirm, HAT is sent to keystore and client is notified. 589 mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed( 590 BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED, 591 null /* credentialAttestation */); 592 waitForIdle(); 593 if (isStrongBiometric) { 594 verify(mBiometricService.mKeyStore).addAuthToken(AdditionalMatchers.aryEq(HAT)); 595 } else { 596 verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class)); 597 } 598 verify(mReceiver1).onAuthenticationSucceeded( 599 BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC); 600 } 601 602 @Test testAuthenticate_no_Biometrics_noCredential()603 public void testAuthenticate_no_Biometrics_noCredential() throws Exception { 604 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 605 when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false); 606 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) 607 .thenReturn(false); 608 609 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, 610 true /* requireConfirmation */, 611 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG); 612 waitForIdle(); 613 614 verify(mReceiver1).onError(anyInt() /* modality */, 615 eq(BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS)/* error */, 616 eq(0) /* vendorCode */); 617 } 618 619 @Test testRejectFace_whenAuthenticating_notifiesSystemUIAndClient_thenPaused()620 public void testRejectFace_whenAuthenticating_notifiesSystemUIAndClient_thenPaused() 621 throws Exception { 622 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 623 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 624 false /* requireConfirmation */, null /* authenticators */); 625 626 mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationFailed(SENSOR_ID_FACE); 627 waitForIdle(); 628 629 verify(mBiometricService.mStatusBarService).onBiometricError( 630 eq(BiometricAuthenticator.TYPE_FACE), 631 eq(BiometricConstants.BIOMETRIC_PAUSED_REJECTED), 632 eq(0 /* vendorCode */)); 633 verify(mReceiver1).onAuthenticationFailed(); 634 assertEquals(STATE_AUTH_PAUSED, mBiometricService.mAuthSession.getState()); 635 } 636 637 @Test testRejectFingerprint_whenAuthenticating_notifiesAndKeepsAuthenticating()638 public void testRejectFingerprint_whenAuthenticating_notifiesAndKeepsAuthenticating() 639 throws Exception { 640 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 641 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 642 false /* requireConfirmation */, null /* authenticators */); 643 644 mBiometricService.mAuthSession.mSensorReceiver 645 .onAuthenticationFailed(SENSOR_ID_FINGERPRINT); 646 waitForIdle(); 647 648 verify(mBiometricService.mStatusBarService).onBiometricError( 649 eq(TYPE_FINGERPRINT), 650 eq(BiometricConstants.BIOMETRIC_PAUSED_REJECTED), 651 eq(0 /* vendorCode */)); 652 verify(mReceiver1).onAuthenticationFailed(); 653 assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState()); 654 } 655 656 @Test testRequestAuthentication_whenAlreadyAuthenticating()657 public void testRequestAuthentication_whenAlreadyAuthenticating() throws Exception { 658 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 659 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 660 false /* requireConfirmation */, null /* authenticators */); 661 662 invokeAuthenticate(mBiometricService.mImpl, mReceiver2, false /* requireConfirmation */, 663 null /* authenticators */); 664 waitForIdle(); 665 666 verify(mReceiver1).onError( 667 eq(BiometricAuthenticator.TYPE_FACE), 668 eq(BiometricPrompt.BIOMETRIC_ERROR_CANCELED), 669 eq(0) /* vendorCode */); 670 verify(mBiometricService.mStatusBarService).hideAuthenticationDialog(eq(TEST_REQUEST_ID)); 671 672 verify(mReceiver2, never()).onError(anyInt(), anyInt(), anyInt()); 673 } 674 675 @Test testErrorHalTimeout_whenAuthenticating_entersPausedState()676 public void testErrorHalTimeout_whenAuthenticating_entersPausedState() throws Exception { 677 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 678 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 679 false /* requireConfirmation */, null /* authenticators */); 680 681 mBiometricService.mAuthSession.mSensorReceiver.onError( 682 SENSOR_ID_FACE, 683 getCookieForCurrentSession(mBiometricService.mAuthSession), 684 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT, 685 0 /* vendorCode */); 686 waitForIdle(); 687 688 assertEquals(STATE_AUTH_PAUSED, mBiometricService.mAuthSession.getState()); 689 verify(mBiometricService.mStatusBarService).onBiometricError( 690 eq(BiometricAuthenticator.TYPE_FACE), 691 eq(BiometricConstants.BIOMETRIC_ERROR_TIMEOUT), 692 eq(0 /* vendorCode */)); 693 // Timeout does not count as fail as per BiometricPrompt documentation. 694 verify(mReceiver1, never()).onAuthenticationFailed(); 695 696 // No auth session. Pressing try again will create one. 697 assertEquals(STATE_AUTH_PAUSED, mBiometricService.mAuthSession.getState()); 698 699 // Pressing "Try again" on SystemUI 700 mBiometricService.mAuthSession.mSysuiReceiver.onTryAgainPressed(); 701 waitForIdle(); 702 verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); 703 704 // AuthSession is now resuming 705 assertEquals(STATE_AUTH_PAUSED_RESUMING, mBiometricService.mAuthSession.getState()); 706 707 // Test resuming when hardware becomes ready. SystemUI should not be requested to 708 // show another dialog since it's already showing. 709 resetStatusBar(); 710 startPendingAuthSession(mBiometricService); 711 waitForIdle(); 712 verify(mBiometricService.mStatusBarService, never()).showAuthenticationDialog( 713 any(PromptInfo.class), 714 any(IBiometricSysuiReceiver.class), 715 any() /* sensorIds */, 716 anyBoolean() /* credentialAllowed */, 717 anyBoolean() /* requireConfirmation */, 718 anyInt() /* userId */, 719 anyLong() /* operationId */, 720 anyString(), 721 anyLong() /* requestId */, 722 eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); 723 } 724 725 @Test testErrorFromHal_whenPaused_notifiesSystemUIAndClient()726 public void testErrorFromHal_whenPaused_notifiesSystemUIAndClient() throws Exception { 727 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 728 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 729 false /* requireConfirmation */, null /* authenticators */); 730 731 mBiometricService.mAuthSession.mSensorReceiver.onError( 732 SENSOR_ID_FACE, 733 getCookieForCurrentSession(mBiometricService.mAuthSession), 734 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT, 735 0 /* vendorCode */); 736 mBiometricService.mAuthSession.mSensorReceiver.onError( 737 SENSOR_ID_FACE, 738 getCookieForCurrentSession(mBiometricService.mAuthSession), 739 BiometricConstants.BIOMETRIC_ERROR_CANCELED, 740 0 /* vendorCode */); 741 waitForIdle(); 742 743 // Client receives error immediately 744 verify(mReceiver1).onError( 745 eq(BiometricAuthenticator.TYPE_FACE), 746 eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED), 747 eq(0 /* vendorCode */)); 748 // Dialog is hidden immediately 749 verify(mBiometricService.mStatusBarService).hideAuthenticationDialog(eq(TEST_REQUEST_ID)); 750 // Auth session is over 751 assertNull(mBiometricService.mAuthSession); 752 } 753 754 @Test testErrorFromHal_whileAuthenticating_waitsForSysUIBeforeNotifyingClient()755 public void testErrorFromHal_whileAuthenticating_waitsForSysUIBeforeNotifyingClient() 756 throws Exception { 757 // For errors that show in SystemUI, BiometricService stays in STATE_ERROR_PENDING_SYSUI 758 // until SystemUI notifies us that the dialog is dismissed at which point the current 759 // session is done. 760 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 761 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 762 false /* requireConfirmation */, null /* authenticators */); 763 764 mBiometricService.mAuthSession.mSensorReceiver.onError( 765 SENSOR_ID_FINGERPRINT, 766 getCookieForCurrentSession(mBiometricService.mAuthSession), 767 BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS, 768 0 /* vendorCode */); 769 waitForIdle(); 770 771 // Sends error to SystemUI and does not notify client yet 772 assertEquals(STATE_ERROR_PENDING_SYSUI, mBiometricService.mAuthSession.getState()); 773 verify(mBiometricService.mStatusBarService).onBiometricError( 774 eq(TYPE_FINGERPRINT), 775 eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS), 776 eq(0 /* vendorCode */)); 777 verify(mBiometricService.mStatusBarService, never()) 778 .hideAuthenticationDialog(eq(TEST_REQUEST_ID)); 779 verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); 780 781 // SystemUI animation completed, client is notified, auth session is over 782 mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed( 783 BiometricPrompt.DISMISSED_REASON_ERROR, null /* credentialAttestation */); 784 waitForIdle(); 785 verify(mReceiver1).onError( 786 eq(TYPE_FINGERPRINT), 787 eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS), 788 eq(0 /* vendorCode */)); 789 assertNull(mBiometricService.mAuthSession); 790 } 791 792 @Test testErrorFromHal_whilePreparingAuthentication_credentialAllowed()793 public void testErrorFromHal_whilePreparingAuthentication_credentialAllowed() throws Exception { 794 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 795 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, 796 false /* requireConfirmation */, 797 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK); 798 waitForIdle(); 799 800 assertEquals(STATE_AUTH_CALLED, mBiometricService.mAuthSession.getState()); 801 mBiometricService.mAuthSession.mSensorReceiver.onError( 802 SENSOR_ID_FINGERPRINT, 803 getCookieForPendingSession(mBiometricService.mAuthSession), 804 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT, 805 0 /* vendorCode */); 806 waitForIdle(); 807 808 // We should be showing device credential now 809 assertNotNull(mBiometricService.mAuthSession); 810 assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL, 811 mBiometricService.mAuthSession.getState()); 812 assertEquals(Authenticators.DEVICE_CREDENTIAL, 813 mBiometricService.mAuthSession.mPromptInfo.getAuthenticators()); 814 verify(mBiometricService.mStatusBarService).showAuthenticationDialog( 815 eq(mBiometricService.mAuthSession.mPromptInfo), 816 any(IBiometricSysuiReceiver.class), 817 AdditionalMatchers.aryEq(new int[0]) /* sensorIds */, 818 eq(true) /* credentialAllowed */, 819 anyBoolean() /* requireConfirmation */, 820 anyInt() /* userId */, 821 anyLong() /* operationId */, 822 eq(TEST_PACKAGE_NAME), 823 eq(TEST_REQUEST_ID), 824 eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); 825 } 826 827 @Test testErrorFromHal_whilePreparingAuthentication_credentialNotAllowed()828 public void testErrorFromHal_whilePreparingAuthentication_credentialNotAllowed() 829 throws Exception { 830 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 831 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, 832 false /* requireConfirmation */, null /* authenticators */); 833 waitForIdle(); 834 835 mBiometricService.mAuthSession.mSensorReceiver.onError( 836 SENSOR_ID_FINGERPRINT, 837 getCookieForPendingSession(mBiometricService.mAuthSession), 838 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT, 839 0 /* vendorCode */); 840 waitForIdle(); 841 842 // Error is sent to client 843 verify(mReceiver1).onError(eq(TYPE_FINGERPRINT), 844 eq(BiometricConstants.BIOMETRIC_ERROR_LOCKOUT), 845 eq(0) /* vendorCode */); 846 assertNull(mBiometricService.mAuthSession); 847 } 848 849 @Test testBiometricAuth_whenBiometricLockoutTimed_sendsErrorAndModality()850 public void testBiometricAuth_whenBiometricLockoutTimed_sendsErrorAndModality() 851 throws Exception { 852 testBiometricAuth_whenLockout(LockoutTracker.LOCKOUT_TIMED, 853 BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT); 854 } 855 856 @Test testBiometricAuth_whenBiometricLockoutPermanent_sendsErrorAndModality()857 public void testBiometricAuth_whenBiometricLockoutPermanent_sendsErrorAndModality() 858 throws Exception { 859 testBiometricAuth_whenLockout(LockoutTracker.LOCKOUT_PERMANENT, 860 BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT_PERMANENT); 861 } 862 testBiometricAuth_whenLockout(@ockoutTracker.LockoutMode int lockoutMode, int biometricPromptError)863 private void testBiometricAuth_whenLockout(@LockoutTracker.LockoutMode int lockoutMode, 864 int biometricPromptError) throws Exception { 865 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 866 when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt())) 867 .thenReturn(lockoutMode); 868 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, 869 false /* requireConfirmation */, null /* authenticators */); 870 waitForIdle(); 871 872 // Modality and error are sent 873 verify(mReceiver1).onError(eq(TYPE_FINGERPRINT), 874 eq(biometricPromptError), eq(0) /* vendorCode */); 875 } 876 877 @Test testBiometricOrCredentialAuth_whenBiometricLockout_showsCredential()878 public void testBiometricOrCredentialAuth_whenBiometricLockout_showsCredential() 879 throws Exception { 880 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())).thenReturn(true); 881 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 882 when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt())) 883 .thenReturn(LockoutTracker.LOCKOUT_PERMANENT); 884 invokeAuthenticate(mBiometricService.mImpl, mReceiver1, 885 false /* requireConfirmation */, 886 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG); 887 waitForIdle(); 888 889 verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); 890 assertNotNull(mBiometricService.mAuthSession); 891 assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL, 892 mBiometricService.mAuthSession.getState()); 893 assertEquals(Authenticators.DEVICE_CREDENTIAL, 894 mBiometricService.mAuthSession.mPromptInfo.getAuthenticators()); 895 verify(mBiometricService.mStatusBarService).showAuthenticationDialog( 896 eq(mBiometricService.mAuthSession.mPromptInfo), 897 any(IBiometricSysuiReceiver.class), 898 AdditionalMatchers.aryEq(new int[0]) /* sensorIds */, 899 eq(true) /* credentialAllowed */, 900 anyBoolean() /* requireConfirmation */, 901 anyInt() /* userId */, 902 anyLong() /* operationId */, 903 eq(TEST_PACKAGE_NAME), 904 eq(TEST_REQUEST_ID), 905 eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); 906 } 907 908 @Test testCombineAuthenticatorBundles_withKeyDeviceCredential_andKeyAuthenticators()909 public void testCombineAuthenticatorBundles_withKeyDeviceCredential_andKeyAuthenticators() { 910 final boolean allowDeviceCredential = false; 911 final @Authenticators.Types int authenticators = 912 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK; 913 final PromptInfo promptInfo = new PromptInfo(); 914 915 promptInfo.setDeviceCredentialAllowed(allowDeviceCredential); 916 promptInfo.setAuthenticators(authenticators); 917 Utils.combineAuthenticatorBundles(promptInfo); 918 919 assertFalse(promptInfo.isDeviceCredentialAllowed()); 920 assertEquals(authenticators, promptInfo.getAuthenticators()); 921 } 922 923 @Test testCombineAuthenticatorBundles_withNoKeyDeviceCredential_andKeyAuthenticators()924 public void testCombineAuthenticatorBundles_withNoKeyDeviceCredential_andKeyAuthenticators() { 925 final @Authenticators.Types int authenticators = 926 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK; 927 final PromptInfo promptInfo = new PromptInfo(); 928 929 promptInfo.setAuthenticators(authenticators); 930 Utils.combineAuthenticatorBundles(promptInfo); 931 932 assertFalse(promptInfo.isDeviceCredentialAllowed()); 933 assertEquals(authenticators, promptInfo.getAuthenticators()); 934 } 935 936 @Test testCombineAuthenticatorBundles_withKeyDeviceCredential_andNoKeyAuthenticators()937 public void testCombineAuthenticatorBundles_withKeyDeviceCredential_andNoKeyAuthenticators() { 938 final boolean allowDeviceCredential = true; 939 final PromptInfo promptInfo = new PromptInfo(); 940 941 promptInfo.setDeviceCredentialAllowed(allowDeviceCredential); 942 Utils.combineAuthenticatorBundles(promptInfo); 943 944 assertFalse(promptInfo.isDeviceCredentialAllowed()); 945 assertEquals(Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK, 946 promptInfo.getAuthenticators()); 947 } 948 949 @Test testCombineAuthenticatorBundles_withNoKeyDeviceCredential_andNoKeyAuthenticators()950 public void testCombineAuthenticatorBundles_withNoKeyDeviceCredential_andNoKeyAuthenticators() { 951 final PromptInfo promptInfo = new PromptInfo(); 952 953 Utils.combineAuthenticatorBundles(promptInfo); 954 955 assertFalse(promptInfo.isDeviceCredentialAllowed()); 956 assertEquals(Authenticators.BIOMETRIC_WEAK, promptInfo.getAuthenticators()); 957 } 958 959 @Test testErrorFromHal_whileShowingDeviceCredential_doesntNotifySystemUI()960 public void testErrorFromHal_whileShowingDeviceCredential_doesntNotifySystemUI() 961 throws Exception { 962 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 963 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 964 false /* requireConfirmation */, 965 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK); 966 967 mBiometricService.mAuthSession.mSysuiReceiver.onDeviceCredentialPressed(); 968 waitForIdle(); 969 970 assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL, 971 mBiometricService.mAuthSession.getState()); 972 verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); 973 974 mBiometricService.mAuthSession.mSensorReceiver.onError( 975 SENSOR_ID_FINGERPRINT, 976 getCookieForCurrentSession(mBiometricService.mAuthSession), 977 BiometricConstants.BIOMETRIC_ERROR_CANCELED, 978 0 /* vendorCode */); 979 waitForIdle(); 980 981 assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL, 982 mBiometricService.mAuthSession.getState()); 983 verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); 984 } 985 986 @Test testLockout_whileAuthenticating_credentialAllowed()987 public void testLockout_whileAuthenticating_credentialAllowed() throws Exception { 988 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 989 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 990 false /* requireConfirmation */, 991 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK); 992 993 assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState()); 994 995 mBiometricService.mAuthSession.mSensorReceiver.onError( 996 SENSOR_ID_FINGERPRINT, 997 getCookieForCurrentSession(mBiometricService.mAuthSession), 998 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT, 999 0 /* vendorCode */); 1000 waitForIdle(); 1001 1002 assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL, 1003 mBiometricService.mAuthSession.getState()); 1004 verify(mBiometricService.mStatusBarService).onBiometricError( 1005 eq(TYPE_FINGERPRINT), 1006 eq(BiometricConstants.BIOMETRIC_ERROR_LOCKOUT), 1007 eq(0 /* vendorCode */)); 1008 } 1009 1010 @Test testLockout_whenAuthenticating_credentialNotAllowed()1011 public void testLockout_whenAuthenticating_credentialNotAllowed() throws Exception { 1012 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 1013 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 1014 false /* requireConfirmation */, null /* authenticators */); 1015 1016 assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState()); 1017 1018 mBiometricService.mAuthSession.mSensorReceiver.onError( 1019 SENSOR_ID_FINGERPRINT, 1020 getCookieForCurrentSession(mBiometricService.mAuthSession), 1021 BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS, 1022 0 /* vendorCode */); 1023 waitForIdle(); 1024 1025 assertEquals(STATE_ERROR_PENDING_SYSUI, 1026 mBiometricService.mAuthSession.getState()); 1027 verify(mBiometricService.mStatusBarService).onBiometricError( 1028 eq(TYPE_FINGERPRINT), 1029 eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS), 1030 eq(0 /* vendorCode */)); 1031 } 1032 1033 @Test testDismissedReasonUserCancel_whileAuthenticating_cancelsHalAuthentication()1034 public void testDismissedReasonUserCancel_whileAuthenticating_cancelsHalAuthentication() 1035 throws Exception { 1036 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 1037 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 1038 false /* requireConfirmation */, null /* authenticators */); 1039 1040 mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed( 1041 BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */); 1042 waitForIdle(); 1043 verify(mReceiver1).onError( 1044 eq(TYPE_FINGERPRINT), 1045 eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED), 1046 eq(0 /* vendorCode */)); 1047 verify(mBiometricService.mSensors.get(0).impl).cancelAuthenticationFromService( 1048 any(), any(), anyLong()); 1049 assertNull(mBiometricService.mAuthSession); 1050 } 1051 1052 @Test testDismissedReasonNegative_whilePaused_invokeHalCancel()1053 public void testDismissedReasonNegative_whilePaused_invokeHalCancel() throws Exception { 1054 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 1055 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 1056 false /* requireConfirmation */, null /* authenticators */); 1057 1058 mBiometricService.mAuthSession.mSensorReceiver.onError( 1059 SENSOR_ID_FACE, 1060 getCookieForCurrentSession(mBiometricService.mAuthSession), 1061 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT, 1062 0 /* vendorCode */); 1063 mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed( 1064 BiometricPrompt.DISMISSED_REASON_NEGATIVE, null /* credentialAttestation */); 1065 waitForIdle(); 1066 1067 verify(mBiometricService.mSensors.get(0).impl) 1068 .cancelAuthenticationFromService(any(), any(), anyLong()); 1069 } 1070 1071 @Test testDismissedReasonUserCancel_whilePaused_invokesHalCancel()1072 public void testDismissedReasonUserCancel_whilePaused_invokesHalCancel() throws Exception { 1073 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 1074 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 1075 false /* requireConfirmation */, null /* authenticators */); 1076 1077 mBiometricService.mAuthSession.mSensorReceiver.onError( 1078 SENSOR_ID_FACE, 1079 getCookieForCurrentSession(mBiometricService.mAuthSession), 1080 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT, 1081 0 /* vendorCode */); 1082 mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed( 1083 BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */); 1084 waitForIdle(); 1085 1086 verify(mBiometricService.mSensors.get(0).impl) 1087 .cancelAuthenticationFromService(any(), any(), anyLong()); 1088 } 1089 1090 @Test testDismissedReasonUserCancel_whenPendingConfirmation()1091 public void testDismissedReasonUserCancel_whenPendingConfirmation() throws Exception { 1092 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 1093 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 1094 true /* requireConfirmation */, null /* authenticators */); 1095 1096 mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationSucceeded( 1097 SENSOR_ID_FACE, 1098 new byte[69] /* HAT */); 1099 mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed( 1100 BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */); 1101 waitForIdle(); 1102 1103 verify(mBiometricService.mSensors.get(0).impl) 1104 .cancelAuthenticationFromService(any(), any(), anyLong()); 1105 verify(mReceiver1).onError( 1106 eq(BiometricAuthenticator.TYPE_FACE), 1107 eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED), 1108 eq(0 /* vendorCode */)); 1109 verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class)); 1110 assertNull(mBiometricService.mAuthSession); 1111 } 1112 1113 @Test testAcquire_whenAuthenticating_sentToSystemUI()1114 public void testAcquire_whenAuthenticating_sentToSystemUI() throws Exception { 1115 when(mContext.getResources().getString(anyInt())).thenReturn("test string"); 1116 1117 final int modality = TYPE_FINGERPRINT; 1118 setupAuthForOnly(modality, Authenticators.BIOMETRIC_STRONG); 1119 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 1120 false /* requireConfirmation */, null /* authenticators */); 1121 1122 mBiometricService.mAuthSession.mSensorReceiver.onAcquired( 1123 SENSOR_ID_FINGERPRINT, 1124 FingerprintManager.FINGERPRINT_ACQUIRED_IMAGER_DIRTY, 1125 0 /* vendorCode */); 1126 waitForIdle(); 1127 1128 // Sends to SysUI and stays in authenticating state. We don't test that the correct 1129 // string is retrieved for now, but it's also very unlikely to break anyway. 1130 verify(mBiometricService.mStatusBarService) 1131 .onBiometricHelp(eq(modality), anyString()); 1132 assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState()); 1133 } 1134 1135 @Test testCancel_whenAuthenticating()1136 public void testCancel_whenAuthenticating() throws Exception { 1137 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 1138 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 1139 false /* requireConfirmation */, null /* authenticators */); 1140 1141 mBiometricService.mImpl.cancelAuthentication(mBiometricService.mAuthSession.mToken, 1142 TEST_PACKAGE_NAME, TEST_REQUEST_ID); 1143 waitForIdle(); 1144 1145 // Pretend that the HAL has responded to cancel with ERROR_CANCELED 1146 mBiometricService.mAuthSession.mSensorReceiver.onError( 1147 SENSOR_ID_FINGERPRINT, 1148 getCookieForCurrentSession(mBiometricService.mAuthSession), 1149 BiometricConstants.BIOMETRIC_ERROR_CANCELED, 1150 0 /* vendorCode */); 1151 waitForIdle(); 1152 1153 // Hides system dialog and invokes the onError callback 1154 verify(mReceiver1).onError(eq(TYPE_FINGERPRINT), 1155 eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED), 1156 eq(0 /* vendorCode */)); 1157 verify(mBiometricService.mStatusBarService).hideAuthenticationDialog(eq(TEST_REQUEST_ID)); 1158 } 1159 1160 @Test testCanAuthenticate_whenDeviceHasRequestedBiometricStrength()1161 public void testCanAuthenticate_whenDeviceHasRequestedBiometricStrength() throws Exception { 1162 // When only biometric is requested, and sensor is strong enough 1163 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 1164 1165 assertEquals(BiometricManager.BIOMETRIC_SUCCESS, 1166 invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG)); 1167 } 1168 1169 @Test testCanAuthenticate_whenDeviceDoesNotHaveRequestedBiometricStrength()1170 public void testCanAuthenticate_whenDeviceDoesNotHaveRequestedBiometricStrength() 1171 throws Exception { 1172 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_WEAK); 1173 1174 // When only biometric is requested, and sensor is not strong enough 1175 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) 1176 .thenReturn(false); 1177 int authenticators = Authenticators.BIOMETRIC_STRONG; 1178 assertEquals(BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE, 1179 invokeCanAuthenticate(mBiometricService, authenticators)); 1180 1181 // When credential and biometric are requested, and sensor is not strong enough 1182 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) 1183 .thenReturn(true); 1184 authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL; 1185 assertEquals(BiometricManager.BIOMETRIC_SUCCESS, 1186 invokeCanAuthenticate(mBiometricService, authenticators)); 1187 } 1188 1189 @Test testCanAuthenticate_onlyCredentialRequested()1190 public void testCanAuthenticate_onlyCredentialRequested() throws Exception { 1191 mBiometricService = new BiometricService(mContext, mInjector); 1192 mBiometricService.onStart(); 1193 1194 // Credential requested but not set up 1195 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) 1196 .thenReturn(false); 1197 assertEquals(BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED, 1198 invokeCanAuthenticate(mBiometricService, Authenticators.DEVICE_CREDENTIAL)); 1199 1200 // Credential requested and set up 1201 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) 1202 .thenReturn(true); 1203 assertEquals(BiometricManager.BIOMETRIC_SUCCESS, 1204 invokeCanAuthenticate(mBiometricService, Authenticators.DEVICE_CREDENTIAL)); 1205 } 1206 1207 @Test testCanAuthenticate_whenNoBiometricsEnrolled()1208 public void testCanAuthenticate_whenNoBiometricsEnrolled() throws Exception { 1209 // With credential set up, test the following. 1210 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())).thenReturn(true); 1211 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG, 1212 false /* enrolled */); 1213 1214 // When only biometric is requested 1215 int authenticators = Authenticators.BIOMETRIC_STRONG; 1216 assertEquals(BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED, 1217 invokeCanAuthenticate(mBiometricService, authenticators)); 1218 1219 // When credential and biometric are requested 1220 authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL; 1221 assertEquals(BiometricManager.BIOMETRIC_SUCCESS, 1222 invokeCanAuthenticate(mBiometricService, authenticators)); 1223 } 1224 1225 @Test testCanAuthenticate_whenBiometricsNotEnabledForApps()1226 public void testCanAuthenticate_whenBiometricsNotEnabledForApps() throws Exception { 1227 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 1228 when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false); 1229 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) 1230 .thenReturn(true); 1231 1232 // When only biometric is requested 1233 int authenticators = Authenticators.BIOMETRIC_STRONG; 1234 assertEquals(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE, 1235 invokeCanAuthenticate(mBiometricService, authenticators)); 1236 1237 // When credential and biometric are requested 1238 authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL; 1239 assertEquals(BiometricManager.BIOMETRIC_SUCCESS, 1240 invokeCanAuthenticate(mBiometricService, authenticators)); 1241 } 1242 1243 @Test testCanAuthenticate_whenNoBiometricSensor()1244 public void testCanAuthenticate_whenNoBiometricSensor() throws Exception { 1245 mBiometricService = new BiometricService(mContext, mInjector); 1246 mBiometricService.onStart(); 1247 1248 // When only biometric is requested 1249 int authenticators = Authenticators.BIOMETRIC_STRONG; 1250 assertEquals(BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE, 1251 invokeCanAuthenticate(mBiometricService, authenticators)); 1252 1253 // When credential and biometric are requested, and credential is not set up 1254 authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL; 1255 assertEquals(BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED, 1256 invokeCanAuthenticate(mBiometricService, authenticators)); 1257 1258 // When credential and biometric are requested, and credential is set up 1259 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) 1260 .thenReturn(true); 1261 assertEquals(BiometricManager.BIOMETRIC_SUCCESS, 1262 invokeCanAuthenticate(mBiometricService, authenticators)); 1263 } 1264 1265 @Test testCanAuthenticate_whenLockoutTimed()1266 public void testCanAuthenticate_whenLockoutTimed() throws Exception { 1267 testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_TIMED); 1268 } 1269 1270 @Test testCanAuthenticate_whenLockoutPermanent()1271 public void testCanAuthenticate_whenLockoutPermanent() throws Exception { 1272 testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_PERMANENT); 1273 } 1274 testCanAuthenticate_whenLockedOut(@ockoutTracker.LockoutMode int lockoutMode)1275 private void testCanAuthenticate_whenLockedOut(@LockoutTracker.LockoutMode int lockoutMode) 1276 throws Exception { 1277 // When only biometric is requested, and sensor is strong enough 1278 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 1279 1280 when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt())) 1281 .thenReturn(lockoutMode); 1282 1283 // Lockout is not considered an error for BiometricManager#canAuthenticate 1284 assertEquals(BiometricManager.BIOMETRIC_SUCCESS, 1285 invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG)); 1286 } 1287 1288 @Test testAuthenticatorActualStrength()1289 public void testAuthenticatorActualStrength() { 1290 // Tuple of OEM config, updatedStrength, and expectedStrength 1291 final int[][] testCases = { 1292 // Downgrades to the specified strength 1293 {Authenticators.BIOMETRIC_STRONG, Authenticators.BIOMETRIC_WEAK, 1294 Authenticators.BIOMETRIC_WEAK}, 1295 1296 // Cannot be upgraded 1297 {Authenticators.BIOMETRIC_WEAK, Authenticators.BIOMETRIC_STRONG, 1298 Authenticators.BIOMETRIC_WEAK}, 1299 1300 // Downgrades to convenience 1301 {Authenticators.BIOMETRIC_WEAK, Authenticators.BIOMETRIC_CONVENIENCE, 1302 Authenticators.BIOMETRIC_CONVENIENCE}, 1303 1304 // EMPTY_SET does not modify specified strength 1305 {Authenticators.BIOMETRIC_WEAK, Authenticators.EMPTY_SET, 1306 Authenticators.BIOMETRIC_WEAK}, 1307 }; 1308 1309 for (int i = 0; i < testCases.length; i++) { 1310 final BiometricSensor sensor = 1311 new BiometricSensor(mContext, 0 /* id */, 1312 TYPE_FINGERPRINT, 1313 testCases[i][0], 1314 mock(IBiometricAuthenticator.class)) { 1315 @Override 1316 boolean confirmationAlwaysRequired(int userId) { 1317 return false; 1318 } 1319 1320 @Override 1321 boolean confirmationSupported() { 1322 return false; 1323 } 1324 }; 1325 sensor.updateStrength(testCases[i][1]); 1326 assertEquals(testCases[i][2], sensor.getCurrentStrength()); 1327 } 1328 } 1329 1330 @Test testRegisterAuthenticator_updatesStrengths()1331 public void testRegisterAuthenticator_updatesStrengths() throws Exception { 1332 mBiometricService = new BiometricService(mContext, mInjector); 1333 mBiometricService.onStart(); 1334 1335 verify(mBiometricService.mBiometricStrengthController).startListening(); 1336 verify(mBiometricService.mBiometricStrengthController, never()).updateStrengths(); 1337 1338 when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any())) 1339 .thenReturn(true); 1340 when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true); 1341 mBiometricService.mImpl.registerAuthenticator(0 /* testId */, 1342 TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG, 1343 mFingerprintAuthenticator); 1344 1345 verify(mBiometricService.mBiometricStrengthController).updateStrengths(); 1346 } 1347 1348 @Test testWithDowngradedAuthenticator()1349 public void testWithDowngradedAuthenticator() throws Exception { 1350 mBiometricService = new BiometricService(mContext, mInjector); 1351 mBiometricService.onStart(); 1352 1353 final int testId = 0; 1354 1355 when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true); 1356 1357 when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any())) 1358 .thenReturn(true); 1359 when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true); 1360 mBiometricService.mImpl.registerAuthenticator(testId /* id */, 1361 TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG, 1362 mFingerprintAuthenticator); 1363 1364 // Downgrade the authenticator 1365 for (BiometricSensor sensor : mBiometricService.mSensors) { 1366 if (sensor.id == testId) { 1367 sensor.updateStrength(Authenticators.BIOMETRIC_WEAK); 1368 } 1369 } 1370 1371 // STRONG-only auth is not available 1372 int authenticators = Authenticators.BIOMETRIC_STRONG; 1373 assertEquals(BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED, 1374 invokeCanAuthenticate(mBiometricService, authenticators)); 1375 long requestId = invokeAuthenticate(mBiometricService.mImpl, mReceiver1, 1376 false /* requireConfirmation */, authenticators); 1377 waitForIdle(); 1378 verify(mReceiver1).onError( 1379 eq(TYPE_FINGERPRINT), 1380 eq(BiometricPrompt.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED), 1381 eq(0) /* vendorCode */); 1382 1383 // Request for weak auth works 1384 resetReceivers(); 1385 authenticators = Authenticators.BIOMETRIC_WEAK; 1386 assertEquals(BiometricManager.BIOMETRIC_SUCCESS, 1387 invokeCanAuthenticate(mBiometricService, authenticators)); 1388 requestId = invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 1389 false /* requireConfirmation */, 1390 authenticators); 1391 waitForIdle(); 1392 verify(mBiometricService.mStatusBarService).showAuthenticationDialog( 1393 eq(mBiometricService.mAuthSession.mPromptInfo), 1394 any(IBiometricSysuiReceiver.class), 1395 AdditionalMatchers.aryEq(new int[] {testId}), 1396 eq(false) /* credentialAllowed */, 1397 anyBoolean() /* requireConfirmation */, 1398 anyInt() /* userId */, 1399 anyLong() /* operationId */, 1400 eq(TEST_PACKAGE_NAME), 1401 eq(requestId), 1402 eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); 1403 1404 // Requesting strong and credential, when credential is setup 1405 resetReceivers(); 1406 authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL; 1407 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) 1408 .thenReturn(true); 1409 assertEquals(BiometricManager.BIOMETRIC_SUCCESS, 1410 invokeCanAuthenticate(mBiometricService, authenticators)); 1411 requestId = invokeAuthenticate(mBiometricService.mImpl, mReceiver1, 1412 false /* requireConfirmation */, 1413 authenticators); 1414 waitForIdle(); 1415 assertTrue(Utils.isCredentialRequested(mBiometricService.mAuthSession.mPromptInfo)); 1416 verify(mBiometricService.mStatusBarService).showAuthenticationDialog( 1417 eq(mBiometricService.mAuthSession.mPromptInfo), 1418 any(IBiometricSysuiReceiver.class), 1419 AdditionalMatchers.aryEq(new int[0]) /* sensorIds */, 1420 eq(true) /* credentialAllowed */, 1421 anyBoolean() /* requireConfirmation */, 1422 anyInt() /* userId */, 1423 anyLong() /* operationId */, 1424 eq(TEST_PACKAGE_NAME), 1425 eq(requestId), 1426 eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); 1427 1428 // Un-downgrading the authenticator allows successful strong auth 1429 for (BiometricSensor sensor : mBiometricService.mSensors) { 1430 if (sensor.id == testId) { 1431 sensor.updateStrength(Authenticators.BIOMETRIC_STRONG); 1432 } 1433 } 1434 1435 resetReceivers(); 1436 authenticators = Authenticators.BIOMETRIC_STRONG; 1437 assertEquals(BiometricManager.BIOMETRIC_SUCCESS, 1438 invokeCanAuthenticate(mBiometricService, authenticators)); 1439 requestId = invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 1440 false /* requireConfirmation */, authenticators); 1441 waitForIdle(); 1442 verify(mBiometricService.mStatusBarService).showAuthenticationDialog( 1443 eq(mBiometricService.mAuthSession.mPromptInfo), 1444 any(IBiometricSysuiReceiver.class), 1445 AdditionalMatchers.aryEq(new int[] {testId}) /* sensorIds */, 1446 eq(false) /* credentialAllowed */, 1447 anyBoolean() /* requireConfirmation */, 1448 anyInt() /* userId */, 1449 anyLong() /* operationId */, 1450 eq(TEST_PACKAGE_NAME), 1451 eq(requestId), 1452 eq(BIOMETRIC_MULTI_SENSOR_DEFAULT)); 1453 } 1454 1455 @Test(expected = IllegalStateException.class) testRegistrationWithDuplicateId_throwsIllegalStateException()1456 public void testRegistrationWithDuplicateId_throwsIllegalStateException() throws Exception { 1457 mBiometricService = new BiometricService(mContext, mInjector); 1458 mBiometricService.onStart(); 1459 1460 mBiometricService.mImpl.registerAuthenticator( 1461 0 /* id */, 2 /* modality */, 15 /* strength */, 1462 mFingerprintAuthenticator); 1463 mBiometricService.mImpl.registerAuthenticator( 1464 0 /* id */, 2 /* modality */, 15 /* strength */, 1465 mFingerprintAuthenticator); 1466 } 1467 1468 @Test(expected = IllegalArgumentException.class) testRegistrationWithNullAuthenticator_throwsIllegalArgumentException()1469 public void testRegistrationWithNullAuthenticator_throwsIllegalArgumentException() 1470 throws Exception { 1471 mBiometricService = new BiometricService(mContext, mInjector); 1472 mBiometricService.onStart(); 1473 1474 mBiometricService.mImpl.registerAuthenticator( 1475 0 /* id */, 2 /* modality */, 1476 Authenticators.BIOMETRIC_STRONG /* strength */, 1477 null /* authenticator */); 1478 } 1479 1480 @Test testRegistrationHappyPath_isOk()1481 public void testRegistrationHappyPath_isOk() throws Exception { 1482 // This is being tested in many of the other cases, but here's the base case. 1483 mBiometricService = new BiometricService(mContext, mInjector); 1484 mBiometricService.onStart(); 1485 1486 for (String s : mInjector.getConfiguration(null)) { 1487 SensorConfig config = new SensorConfig(s); 1488 mBiometricService.mImpl.registerAuthenticator(config.id, config.modality, 1489 config.strength, mFingerprintAuthenticator); 1490 } 1491 } 1492 1493 @Test testWorkAuthentication_fingerprintWorksIfNotDisabledByDevicePolicyManager()1494 public void testWorkAuthentication_fingerprintWorksIfNotDisabledByDevicePolicyManager() 1495 throws Exception { 1496 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 1497 when(mDevicePolicyManager 1498 .getKeyguardDisabledFeatures(any() /* admin */, anyInt() /* userHandle */)) 1499 .thenReturn(~DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT); 1500 invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1, 1501 Authenticators.BIOMETRIC_STRONG); 1502 waitForIdle(); 1503 assertEquals(STATE_AUTH_CALLED, mBiometricService.mAuthSession.getState()); 1504 startPendingAuthSession(mBiometricService); 1505 waitForIdle(); 1506 assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState()); 1507 } 1508 1509 @Test testAuthentication_normalAppIgnoresDevicePolicy()1510 public void testAuthentication_normalAppIgnoresDevicePolicy() throws Exception { 1511 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 1512 when(mDevicePolicyManager 1513 .getKeyguardDisabledFeatures(any() /* admin */, anyInt() /* userHandle */)) 1514 .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT); 1515 invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1, 1516 false /* requireConfirmation */, Authenticators.BIOMETRIC_STRONG); 1517 waitForIdle(); 1518 assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState()); 1519 } 1520 1521 @Test testWorkAuthentication_faceWorksIfNotDisabledByDevicePolicyManager()1522 public void testWorkAuthentication_faceWorksIfNotDisabledByDevicePolicyManager() 1523 throws Exception { 1524 setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); 1525 when(mDevicePolicyManager 1526 .getKeyguardDisabledFeatures(any() /* admin*/, anyInt() /* userHandle */)) 1527 .thenReturn(~DevicePolicyManager.KEYGUARD_DISABLE_FACE); 1528 invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1, 1529 Authenticators.BIOMETRIC_STRONG); 1530 waitForIdle(); 1531 assertEquals(STATE_AUTH_CALLED, mBiometricService.mAuthSession.getState()); 1532 startPendingAuthSession(mBiometricService); 1533 waitForIdle(); 1534 assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState()); 1535 } 1536 1537 @Test testWorkAuthentication_fingerprintFailsIfDisabledByDevicePolicyManager()1538 public void testWorkAuthentication_fingerprintFailsIfDisabledByDevicePolicyManager() 1539 throws Exception { 1540 setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); 1541 when(mTrustManager.isDeviceSecure(anyInt(), anyInt())).thenReturn(true); 1542 when(mDevicePolicyManager 1543 .getKeyguardDisabledFeatures(any() /* admin */, anyInt() /* userHandle */)) 1544 .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT); 1545 1546 invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1, 1547 Authenticators.BIOMETRIC_STRONG); 1548 waitForIdle(); 1549 verify(mReceiver1).onError(eq(BiometricAuthenticator.TYPE_NONE), 1550 eq(BiometricPrompt.BIOMETRIC_ERROR_HW_UNAVAILABLE), eq(0) /* vendorCode */); 1551 1552 invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver2, 1553 Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL); 1554 waitForIdle(); 1555 assertNotNull(mBiometricService.mAuthSession); 1556 assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL, 1557 mBiometricService.mAuthSession.getState()); 1558 verify(mReceiver2, never()).onError(anyInt(), anyInt(), anyInt()); 1559 } 1560 1561 // Helper methods 1562 invokeCanAuthenticate(BiometricService service, int authenticators)1563 private int invokeCanAuthenticate(BiometricService service, int authenticators) 1564 throws Exception { 1565 return service.mImpl.canAuthenticate( 1566 TEST_PACKAGE_NAME, 0 /* userId */, 0 /* callingUserId */, authenticators); 1567 } 1568 setupAuthForOnly(int modality, int strength)1569 private void setupAuthForOnly(int modality, int strength) throws Exception { 1570 setupAuthForOnly(modality, strength, true /* enrolled */); 1571 } 1572 1573 // TODO: Reconcile the registration strength with the injector setupAuthForOnly(int modality, int strength, boolean enrolled)1574 private void setupAuthForOnly(int modality, int strength, boolean enrolled) throws Exception { 1575 mBiometricService = new BiometricService(mContext, mInjector); 1576 mBiometricService.onStart(); 1577 1578 when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true); 1579 1580 if ((modality & TYPE_FINGERPRINT) != 0) { 1581 when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any())) 1582 .thenReturn(enrolled); 1583 when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true); 1584 when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt())) 1585 .thenReturn(LockoutTracker.LOCKOUT_NONE); 1586 mBiometricService.mImpl.registerAuthenticator(SENSOR_ID_FINGERPRINT, modality, strength, 1587 mFingerprintAuthenticator); 1588 } 1589 1590 if ((modality & BiometricAuthenticator.TYPE_FACE) != 0) { 1591 when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(enrolled); 1592 when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true); 1593 when(mFaceAuthenticator.getLockoutModeForUser(anyInt())) 1594 .thenReturn(LockoutTracker.LOCKOUT_NONE); 1595 mBiometricService.mImpl.registerAuthenticator(SENSOR_ID_FACE, modality, strength, 1596 mFaceAuthenticator); 1597 } 1598 } 1599 1600 // TODO: Reduce duplicated code, currently we cannot start the BiometricService in setUp() for 1601 // all tests. setupAuthForMultiple(int[] modalities, int[] strengths)1602 private void setupAuthForMultiple(int[] modalities, int[] strengths) throws RemoteException { 1603 mBiometricService = new BiometricService(mContext, mInjector); 1604 mBiometricService.onStart(); 1605 1606 when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true); 1607 1608 assertEquals(modalities.length, strengths.length); 1609 1610 for (int i = 0; i < modalities.length; i++) { 1611 final int modality = modalities[i]; 1612 final int strength = strengths[i]; 1613 1614 if ((modality & TYPE_FINGERPRINT) != 0) { 1615 when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any())) 1616 .thenReturn(true); 1617 when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true); 1618 mBiometricService.mImpl.registerAuthenticator(SENSOR_ID_FINGERPRINT, modality, 1619 strength, mFingerprintAuthenticator); 1620 } 1621 1622 if ((modality & BiometricAuthenticator.TYPE_FACE) != 0) { 1623 when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); 1624 when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true); 1625 mBiometricService.mImpl.registerAuthenticator(SENSOR_ID_FACE, modality, 1626 strength, mFaceAuthenticator); 1627 } 1628 } 1629 } 1630 resetReceivers()1631 private void resetReceivers() { 1632 mReceiver1 = mock(IBiometricServiceReceiver.class); 1633 mReceiver2 = mock(IBiometricServiceReceiver.class); 1634 1635 when(mReceiver1.asBinder()).thenReturn(mock(Binder.class)); 1636 when(mReceiver2.asBinder()).thenReturn(mock(Binder.class)); 1637 } 1638 resetStatusBar()1639 private void resetStatusBar() { 1640 mBiometricService.mStatusBarService = mock(IStatusBarService.class); 1641 } 1642 invokeAuthenticateAndStart(IBiometricService.Stub service, IBiometricServiceReceiver receiver, boolean requireConfirmation, Integer authenticators)1643 private long invokeAuthenticateAndStart(IBiometricService.Stub service, 1644 IBiometricServiceReceiver receiver, boolean requireConfirmation, 1645 Integer authenticators) throws Exception { 1646 // Request auth, creates a pending session 1647 final long requestId = invokeAuthenticate( 1648 service, receiver, requireConfirmation, authenticators); 1649 waitForIdle(); 1650 1651 startPendingAuthSession(mBiometricService); 1652 waitForIdle(); 1653 1654 assertNotNull(mBiometricService.mAuthSession); 1655 assertEquals(TEST_REQUEST_ID, mBiometricService.mAuthSession.getRequestId()); 1656 assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState()); 1657 1658 return requestId; 1659 } 1660 startPendingAuthSession(BiometricService service)1661 private static void startPendingAuthSession(BiometricService service) throws Exception { 1662 // Get the cookie so we can pretend the hardware is ready to authenticate 1663 // Currently we only support single modality per auth 1664 final PreAuthInfo preAuthInfo = service.mAuthSession.mPreAuthInfo; 1665 assertEquals(preAuthInfo.eligibleSensors.size(), 1); 1666 assertEquals(preAuthInfo.numSensorsWaitingForCookie(), 1); 1667 1668 final int cookie = preAuthInfo.eligibleSensors.get(0).getCookie(); 1669 assertNotEquals(cookie, 0); 1670 1671 service.mImpl.onReadyForAuthentication(TEST_REQUEST_ID, cookie); 1672 } 1673 invokeAuthenticate(IBiometricService.Stub service, IBiometricServiceReceiver receiver, boolean requireConfirmation, Integer authenticators)1674 private static long invokeAuthenticate(IBiometricService.Stub service, 1675 IBiometricServiceReceiver receiver, boolean requireConfirmation, 1676 Integer authenticators) throws Exception { 1677 return service.authenticate( 1678 new Binder() /* token */, 1679 0 /* operationId */, 1680 0 /* userId */, 1681 receiver, 1682 TEST_PACKAGE_NAME /* packageName */, 1683 createTestPromptInfo(requireConfirmation, authenticators, 1684 false /* checkDevicePolicy */)); 1685 } 1686 invokeAuthenticateForWorkApp(IBiometricService.Stub service, IBiometricServiceReceiver receiver, Integer authenticators)1687 private static long invokeAuthenticateForWorkApp(IBiometricService.Stub service, 1688 IBiometricServiceReceiver receiver, Integer authenticators) throws Exception { 1689 return service.authenticate( 1690 new Binder() /* token */, 1691 0 /* operationId */, 1692 0 /* userId */, 1693 receiver, 1694 TEST_PACKAGE_NAME /* packageName */, 1695 createTestPromptInfo(false /* requireConfirmation */, authenticators, 1696 true /* checkDevicePolicy */)); 1697 } 1698 createTestPromptInfo( boolean requireConfirmation, Integer authenticators, boolean checkDevicePolicy)1699 private static PromptInfo createTestPromptInfo( 1700 boolean requireConfirmation, 1701 Integer authenticators, 1702 boolean checkDevicePolicy) { 1703 final PromptInfo promptInfo = new PromptInfo(); 1704 promptInfo.setConfirmationRequested(requireConfirmation); 1705 1706 if (authenticators != null) { 1707 promptInfo.setAuthenticators(authenticators); 1708 } 1709 if (checkDevicePolicy) { 1710 promptInfo.setDisallowBiometricsIfPolicyExists(checkDevicePolicy); 1711 } 1712 return promptInfo; 1713 } 1714 getCookieForCurrentSession(AuthSession session)1715 private static int getCookieForCurrentSession(AuthSession session) { 1716 // Currently only tests authentication with a single sensor 1717 final PreAuthInfo preAuthInfo = session.mPreAuthInfo; 1718 1719 assertEquals(preAuthInfo.eligibleSensors.size(), 1); 1720 return preAuthInfo.eligibleSensors.get(0).getCookie(); 1721 } 1722 getCookieForPendingSession(AuthSession session)1723 private static int getCookieForPendingSession(AuthSession session) { 1724 // Currently only tests authentication with a single sensor 1725 final PreAuthInfo requestWrapper = session.mPreAuthInfo; 1726 1727 assertEquals(requestWrapper.eligibleSensors.size(), 1); 1728 assertEquals(requestWrapper.eligibleSensors.get(0).getSensorState(), 1729 BiometricSensor.STATE_WAITING_FOR_COOKIE); 1730 return requestWrapper.eligibleSensors.get(0).getCookie(); 1731 } 1732 waitForIdle()1733 private static void waitForIdle() { 1734 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 1735 } 1736 generateRandomHAT()1737 private byte[] generateRandomHAT() { 1738 byte[] HAT = new byte[69]; 1739 Random random = new Random(); 1740 random.nextBytes(HAT); 1741 return HAT; 1742 } 1743 } 1744