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