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