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