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