1 /* 2 * Copyright (C) 2020 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_FACE; 20 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; 21 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CONTENT_VIEW_MORE_OPTIONS_BUTTON; 22 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON; 23 import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED; 24 import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED; 25 import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS; 26 import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_NEGATIVE; 27 import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_USER_CANCEL; 28 29 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_CALLED; 30 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_PAUSED; 31 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED; 32 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED_UI_SHOWING; 33 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_ERROR_PENDING_SYSUI; 34 35 import static com.google.common.truth.Truth.assertThat; 36 37 import static junit.framework.Assert.assertEquals; 38 import static junit.framework.Assert.assertFalse; 39 import static junit.framework.Assert.assertTrue; 40 41 import static org.mockito.ArgumentMatchers.any; 42 import static org.mockito.ArgumentMatchers.anyBoolean; 43 import static org.mockito.ArgumentMatchers.anyInt; 44 import static org.mockito.ArgumentMatchers.anyLong; 45 import static org.mockito.ArgumentMatchers.eq; 46 import static org.mockito.Mockito.mock; 47 import static org.mockito.Mockito.never; 48 import static org.mockito.Mockito.times; 49 import static org.mockito.Mockito.verify; 50 import static org.mockito.Mockito.when; 51 52 import android.annotation.NonNull; 53 import android.app.admin.DevicePolicyManager; 54 import android.app.trust.ITrustManager; 55 import android.content.res.Resources; 56 import android.hardware.biometrics.BiometricConstants; 57 import android.hardware.biometrics.BiometricManager; 58 import android.hardware.biometrics.BiometricManager.Authenticators; 59 import android.hardware.biometrics.BiometricsProtoEnums; 60 import android.hardware.biometrics.ComponentInfoInternal; 61 import android.hardware.biometrics.IBiometricAuthenticator; 62 import android.hardware.biometrics.IBiometricSensorReceiver; 63 import android.hardware.biometrics.IBiometricServiceReceiver; 64 import android.hardware.biometrics.IBiometricSysuiReceiver; 65 import android.hardware.biometrics.PromptInfo; 66 import android.hardware.biometrics.SensorProperties; 67 import android.hardware.fingerprint.FingerprintManager; 68 import android.hardware.fingerprint.FingerprintSensorProperties; 69 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; 70 import android.os.Binder; 71 import android.os.IBinder; 72 import android.os.RemoteException; 73 import android.os.UserManager; 74 import android.platform.test.annotations.Presubmit; 75 import android.security.KeyStoreAuthorization; 76 import android.testing.TestableContext; 77 78 import androidx.test.filters.SmallTest; 79 import androidx.test.platform.app.InstrumentationRegistry; 80 81 import com.android.internal.R; 82 import com.android.internal.statusbar.IStatusBarService; 83 import com.android.internal.util.FrameworkStatsLog; 84 import com.android.server.biometrics.log.BiometricContext; 85 import com.android.server.biometrics.log.BiometricFrameworkStatsLogger; 86 import com.android.server.biometrics.log.OperationContextExt; 87 88 import org.junit.Before; 89 import org.junit.Rule; 90 import org.junit.Test; 91 import org.mockito.Mock; 92 import org.mockito.MockitoAnnotations; 93 94 import java.util.ArrayList; 95 import java.util.List; 96 import java.util.Random; 97 import java.util.function.Consumer; 98 99 @Presubmit 100 @SmallTest 101 public class AuthSessionTest { 102 103 private static final String TEST_PACKAGE = "test_package"; 104 private static final long TEST_REQUEST_ID = 22; 105 private static final String ACQUIRED_STRING = "test_acquired_info_callback"; 106 private static final String ACQUIRED_STRING_VENDOR = "test_acquired_info_callback_vendor"; 107 108 @Rule 109 public final TestableContext mContext = new TestableContext( 110 InstrumentationRegistry.getInstrumentation().getTargetContext(), null); 111 @Mock private Resources mResources; 112 @Mock private BiometricContext mBiometricContext; 113 @Mock private ITrustManager mTrustManager; 114 @Mock private DevicePolicyManager mDevicePolicyManager; 115 @Mock private BiometricService.SettingObserver mSettingObserver; 116 @Mock private IBiometricSensorReceiver mSensorReceiver; 117 @Mock private IBiometricServiceReceiver mClientReceiver; 118 @Mock private IStatusBarService mStatusBarService; 119 @Mock private IBiometricSysuiReceiver mSysuiReceiver; 120 @Mock private KeyStoreAuthorization mKeyStoreAuthorization; 121 @Mock private AuthSession.ClientDeathReceiver mClientDeathReceiver; 122 @Mock private BiometricFrameworkStatsLogger mBiometricFrameworkStatsLogger; 123 @Mock private BiometricCameraManager mBiometricCameraManager; 124 @Mock private UserManager mUserManager; 125 @Mock private BiometricManager mBiometricManager; 126 127 private Random mRandom; 128 private IBinder mToken; 129 130 // Assume all tests can be done with the same set of sensors for now. 131 @NonNull private List<BiometricSensor> mSensors; 132 @NonNull private List<FingerprintSensorPropertiesInternal> mFingerprintSensorProps; 133 134 @Before setUp()135 public void setUp() throws Exception { 136 MockitoAnnotations.initMocks(this); 137 mContext.addMockSystemService(BiometricManager.class, mBiometricManager); 138 mContext.getOrCreateTestableResources().addOverride(R.string.fingerprint_acquired_partial, 139 ACQUIRED_STRING); 140 mContext.getOrCreateTestableResources().addOverride(R.array.fingerprint_acquired_vendor, 141 new String[]{ACQUIRED_STRING_VENDOR}); 142 when(mClientReceiver.asBinder()).thenReturn(mock(Binder.class)); 143 when(mBiometricContext.updateContext(any(), anyBoolean())) 144 .thenAnswer(invocation -> invocation.getArgument(0)); 145 mRandom = new Random(); 146 mToken = new Binder(); 147 mSensors = new ArrayList<>(); 148 mFingerprintSensorProps = new ArrayList<>(); 149 } 150 151 @Test testNewAuthSession_eligibleSensorsSetToStateUnknown()152 public void testNewAuthSession_eligibleSensorsSetToStateUnknown() throws RemoteException { 153 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_REAR); 154 setupFace(1 /* id */, false /* confirmationAlwaysRequired */, 155 mock(IBiometricAuthenticator.class)); 156 157 final AuthSession session = createAuthSession(mSensors, 158 false /* checkDevicePolicyManager */, 159 Authenticators.BIOMETRIC_STRONG, 160 TEST_REQUEST_ID, 161 0 /* operationId */, 162 0 /* userId */); 163 164 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 165 assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState()); 166 } 167 } 168 169 @Test testStartNewAuthSession()170 public void testStartNewAuthSession() throws RemoteException { 171 setupFace(0 /* id */, false /* confirmationAlwaysRequired */, 172 mock(IBiometricAuthenticator.class)); 173 setupFingerprint(1 /* id */, FingerprintSensorProperties.TYPE_REAR); 174 175 final boolean requireConfirmation = true; 176 final long operationId = 123; 177 final int userId = 10; 178 179 final AuthSession session = createAuthSession(mSensors, 180 false /* checkDevicePolicyManager */, 181 Authenticators.BIOMETRIC_STRONG, 182 TEST_REQUEST_ID, 183 operationId, 184 userId); 185 assertEquals(mSensors.size(), session.mPreAuthInfo.eligibleSensors.size()); 186 187 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 188 assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState()); 189 assertEquals(0, sensor.getCookie()); 190 } 191 192 session.goToInitialState(); 193 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 194 assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState()); 195 assertTrue("Cookie must be >0", sensor.getCookie() > 0); 196 verify(sensor.impl).prepareForAuthentication( 197 eq(sensor.confirmationSupported() && requireConfirmation), 198 eq(mToken), 199 eq(operationId), 200 eq(userId), 201 eq(mSensorReceiver), 202 eq(TEST_PACKAGE), 203 eq(TEST_REQUEST_ID), 204 eq(sensor.getCookie()), 205 anyBoolean() /* allowBackgroundAuthentication */, 206 anyBoolean() /* isForLegacyFingerprintManager */, 207 eq(false) /* isMandatoryBiometrics */); 208 } 209 210 final int cookie1 = session.mPreAuthInfo.eligibleSensors.get(0).getCookie(); 211 session.onCookieReceived(cookie1); 212 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 213 if (cookie1 == sensor.getCookie()) { 214 assertEquals(BiometricSensor.STATE_COOKIE_RETURNED, sensor.getSensorState()); 215 } else { 216 assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState()); 217 } 218 } 219 assertFalse(session.allCookiesReceived()); 220 221 final int cookie2 = session.mPreAuthInfo.eligibleSensors.get(1).getCookie(); 222 session.onCookieReceived(cookie2); 223 assertTrue(session.allCookiesReceived()); 224 225 226 // for multi-sensor face then fingerprint is the default policy 227 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 228 if (sensor.modality == TYPE_FACE) { 229 verify(sensor.impl).startPreparedClient(eq(sensor.getCookie())); 230 assertEquals(BiometricSensor.STATE_AUTHENTICATING, sensor.getSensorState()); 231 } else if (sensor.modality == TYPE_FINGERPRINT) { 232 assertEquals(BiometricSensor.STATE_COOKIE_RETURNED, sensor.getSensorState()); 233 } 234 } 235 } 236 237 @Test testOnErrorReceived_lockoutError()238 public void testOnErrorReceived_lockoutError() throws RemoteException { 239 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_REAR); 240 setupFace(1 /* id */, false /* confirmationAlwaysRequired */, 241 mock(IBiometricAuthenticator.class)); 242 final AuthSession session = createAuthSession(mSensors, 243 false /* checkDevicePolicyManager */, 244 Authenticators.BIOMETRIC_STRONG, 245 TEST_REQUEST_ID, 246 0 /* operationId */, 247 0 /* userId */); 248 session.goToInitialState(); 249 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 250 assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState()); 251 session.onCookieReceived( 252 session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie()); 253 } 254 assertTrue(session.allCookiesReceived()); 255 assertEquals(STATE_AUTH_STARTED, session.getState()); 256 257 // Either of strong sensor's lockout should cancel both sensors. 258 final int cookie1 = session.mPreAuthInfo.eligibleSensors.get(0).getCookie(); 259 session.onErrorReceived(0, cookie1, BiometricConstants.BIOMETRIC_ERROR_LOCKOUT, 0); 260 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 261 assertEquals(BiometricSensor.STATE_CANCELING, sensor.getSensorState()); 262 } 263 assertEquals(STATE_ERROR_PENDING_SYSUI, session.getState()); 264 265 // If the sensor is STATE_CANCELING, delayed onAuthenticationRejected() shouldn't change the 266 // session state to STATE_AUTH_PAUSED. 267 session.onAuthenticationRejected(1); 268 assertEquals(STATE_ERROR_PENDING_SYSUI, session.getState()); 269 } 270 271 @Test testOnErrorReceivedBeforeOnDialogAnimatedIn()272 public void testOnErrorReceivedBeforeOnDialogAnimatedIn() throws RemoteException { 273 final int fingerprintId = 0; 274 final int faceId = 1; 275 setupFingerprint(fingerprintId, FingerprintSensorProperties.TYPE_REAR); 276 setupFace(faceId, true /* confirmationAlwaysRequired */, 277 mock(IBiometricAuthenticator.class)); 278 final AuthSession session = createAuthSession(mSensors, 279 false /* checkDevicePolicyManager */, 280 Authenticators.BIOMETRIC_STRONG, 281 TEST_REQUEST_ID, 282 0 /* operationId */, 283 0 /* userId */); 284 session.goToInitialState(); 285 286 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 287 assertThat(sensor.getSensorState()).isEqualTo(BiometricSensor.STATE_WAITING_FOR_COOKIE); 288 session.onCookieReceived( 289 session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie()); 290 } 291 assertThat(session.allCookiesReceived()).isTrue(); 292 assertThat(session.getState()).isEqualTo(STATE_AUTH_STARTED); 293 294 final BiometricSensor faceSensor = session.mPreAuthInfo.eligibleSensors.get(faceId); 295 final BiometricSensor fingerprintSensor = session.mPreAuthInfo.eligibleSensors.get( 296 fingerprintId); 297 final int cookie = faceSensor.getCookie(); 298 session.onErrorReceived(0, cookie, BiometricConstants.BIOMETRIC_ERROR_RE_ENROLL, 0); 299 300 assertThat(faceSensor.getSensorState()).isEqualTo(BiometricSensor.STATE_STOPPED); 301 assertThat(session.getState()).isEqualTo(STATE_ERROR_PENDING_SYSUI); 302 303 session.onDialogAnimatedIn(true); 304 305 assertThat(session.getState()).isEqualTo(STATE_AUTH_STARTED_UI_SHOWING); 306 assertThat(fingerprintSensor.getSensorState()).isEqualTo( 307 BiometricSensor.STATE_AUTHENTICATING); 308 } 309 310 @Test testOnRejectionReceivedBeforeOnDialogAnimatedIn()311 public void testOnRejectionReceivedBeforeOnDialogAnimatedIn() throws RemoteException { 312 final int fingerprintId = 0; 313 final int faceId = 1; 314 setupFingerprint(fingerprintId, FingerprintSensorProperties.TYPE_REAR); 315 setupFace(faceId, false /* confirmationAlwaysRequired */, 316 mock(IBiometricAuthenticator.class)); 317 final AuthSession session = createAuthSession(mSensors, 318 false /* checkDevicePolicyManager */, 319 Authenticators.BIOMETRIC_STRONG, 320 TEST_REQUEST_ID, 321 0 /* operationId */, 322 0 /* userId */); 323 session.goToInitialState(); 324 325 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 326 assertThat(sensor.getSensorState()).isEqualTo(BiometricSensor.STATE_WAITING_FOR_COOKIE); 327 session.onCookieReceived( 328 session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie()); 329 } 330 assertThat(session.allCookiesReceived()).isTrue(); 331 assertThat(session.getState()).isEqualTo(STATE_AUTH_STARTED); 332 333 final BiometricSensor faceSensor = session.mPreAuthInfo.eligibleSensors.get(faceId); 334 final BiometricSensor fingerprintSensor = session.mPreAuthInfo.eligibleSensors.get( 335 fingerprintId); 336 session.onAuthenticationRejected(faceId); 337 338 assertThat(faceSensor.getSensorState()).isEqualTo(BiometricSensor.STATE_CANCELING); 339 assertThat(session.getState()).isEqualTo(STATE_AUTH_PAUSED); 340 341 session.onDialogAnimatedIn(true); 342 343 assertThat(session.getState()).isEqualTo(STATE_AUTH_STARTED_UI_SHOWING); 344 assertThat(fingerprintSensor.getSensorState()).isEqualTo( 345 BiometricSensor.STATE_AUTHENTICATING); 346 } 347 348 @Test testCancelReducesAppetiteForCookies()349 public void testCancelReducesAppetiteForCookies() throws Exception { 350 setupFace(0 /* id */, false /* confirmationAlwaysRequired */, 351 mock(IBiometricAuthenticator.class)); 352 setupFingerprint(1 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); 353 354 final AuthSession session = createAuthSession(mSensors, 355 false /* checkDevicePolicyManager */, 356 Authenticators.BIOMETRIC_STRONG, 357 TEST_REQUEST_ID, 358 44 /* operationId */, 359 2 /* userId */); 360 361 session.goToInitialState(); 362 363 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 364 assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState()); 365 } 366 367 session.onCancelAuthSession(false /* force */); 368 369 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 370 session.onCookieReceived(sensor.getCookie()); 371 assertEquals(BiometricSensor.STATE_CANCELING, sensor.getSensorState()); 372 } 373 } 374 375 @Test testMultiAuth_singleSensor_fingerprintSensorStartsAfterDialogAnimationCompletes()376 public void testMultiAuth_singleSensor_fingerprintSensorStartsAfterDialogAnimationCompletes() 377 throws Exception { 378 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); 379 testMultiAuth_fingerprintSensorStartsAfterUINotifies(true /* startFingerprintNow */); 380 } 381 382 @Test testMultiAuth_singleSensor_fingerprintSensorDoesNotStartAfterDialogAnimationCompletes()383 public void testMultiAuth_singleSensor_fingerprintSensorDoesNotStartAfterDialogAnimationCompletes() 384 throws Exception { 385 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); 386 testMultiAuth_fingerprintSensorStartsAfterUINotifies(false /* startFingerprintNow */); 387 } 388 389 @Test testMultiAuth_fingerprintSensorStartsAfterDialogAnimationCompletes()390 public void testMultiAuth_fingerprintSensorStartsAfterDialogAnimationCompletes() 391 throws Exception { 392 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); 393 setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class)); 394 testMultiAuth_fingerprintSensorStartsAfterUINotifies(true /* startFingerprintNow */); 395 } 396 397 @Test testMultiAuth_fingerprintSensorDoesNotStartAfterDialogAnimationCompletes()398 public void testMultiAuth_fingerprintSensorDoesNotStartAfterDialogAnimationCompletes() 399 throws Exception { 400 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); 401 setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class)); 402 testMultiAuth_fingerprintSensorStartsAfterUINotifies(false /* startFingerprintNow */); 403 } 404 testMultiAuth_fingerprintSensorStartsAfterUINotifies(boolean startFingerprintNow)405 public void testMultiAuth_fingerprintSensorStartsAfterUINotifies(boolean startFingerprintNow) 406 throws Exception { 407 final long operationId = 123; 408 final int userId = 10; 409 final int fingerprintSensorId = mSensors.stream() 410 .filter(s -> s.modality == TYPE_FINGERPRINT) 411 .map(s -> s.id) 412 .findFirst() 413 .orElse(-1); 414 415 final AuthSession session = createAuthSession(mSensors, 416 false /* checkDevicePolicyManager */, 417 Authenticators.BIOMETRIC_STRONG, 418 TEST_REQUEST_ID, 419 operationId, 420 userId); 421 assertEquals(mSensors.size(), session.mPreAuthInfo.eligibleSensors.size()); 422 423 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 424 assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState()); 425 assertEquals(0, sensor.getCookie()); 426 } 427 428 session.goToInitialState(); 429 430 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 431 assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState()); 432 session.onCookieReceived( 433 session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie()); 434 if (fingerprintSensorId == sensor.id) { 435 assertEquals(BiometricSensor.STATE_COOKIE_RETURNED, sensor.getSensorState()); 436 } else { 437 assertEquals(BiometricSensor.STATE_AUTHENTICATING, sensor.getSensorState()); 438 } 439 } 440 assertTrue(session.allCookiesReceived()); 441 442 // fingerprint sensor does not start even if all cookies are received 443 assertEquals(STATE_AUTH_STARTED, session.getState()); 444 verify(mStatusBarService).showAuthenticationDialog(any(), any(), any(), 445 anyBoolean(), anyBoolean(), anyInt(), anyLong(), any(), anyLong()); 446 447 // Notify AuthSession that the UI is shown. Then, fingerprint sensor should be started. 448 session.onDialogAnimatedIn(startFingerprintNow); 449 assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState()); 450 assertEquals(startFingerprintNow ? BiometricSensor.STATE_AUTHENTICATING 451 : BiometricSensor.STATE_COOKIE_RETURNED, 452 session.mPreAuthInfo.eligibleSensors.get(fingerprintSensorId).getSensorState()); 453 verify(mBiometricContext).updateContext((OperationContextExt) any(), 454 eq(session.isCrypto())); 455 456 // start fingerprint sensor if it was delayed 457 if (!startFingerprintNow) { 458 session.onStartFingerprint(); 459 assertEquals(BiometricSensor.STATE_AUTHENTICATING, 460 session.mPreAuthInfo.eligibleSensors.get(fingerprintSensorId).getSensorState()); 461 } 462 } 463 464 @Test testOnDialogAnimatedInDoesNothingDuringInvalidState()465 public void testOnDialogAnimatedInDoesNothingDuringInvalidState() throws Exception { 466 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); 467 final long operationId = 123; 468 final int userId = 10; 469 470 final AuthSession session = createAuthSession(mSensors, 471 false /* checkDevicePolicyManager */, 472 Authenticators.BIOMETRIC_STRONG, 473 TEST_REQUEST_ID, 474 operationId, 475 userId); 476 final IBiometricAuthenticator impl = session.mPreAuthInfo.eligibleSensors.get(0).impl; 477 478 session.goToInitialState(); 479 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 480 assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState()); 481 session.onCookieReceived( 482 session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie()); 483 } 484 assertTrue(session.allCookiesReceived()); 485 assertEquals(STATE_AUTH_STARTED, session.getState()); 486 verify(impl, never()).startPreparedClient(anyInt()); 487 488 // First invocation should start the client monitor. 489 session.onDialogAnimatedIn(true /* startFingerprintNow */); 490 assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState()); 491 verify(impl).startPreparedClient(anyInt()); 492 493 // Subsequent invocations should not start the client monitor again. 494 session.onDialogAnimatedIn(true /* startFingerprintNow */); 495 session.onDialogAnimatedIn(false /* startFingerprintNow */); 496 session.onDialogAnimatedIn(true /* startFingerprintNow */); 497 assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState()); 498 verify(impl, times(1)).startPreparedClient(anyInt()); 499 } 500 501 @Test testCancelAuthentication_whenStateAuthCalled_invokesCancel()502 public void testCancelAuthentication_whenStateAuthCalled_invokesCancel() 503 throws RemoteException { 504 testInvokesCancel(session -> session.onCancelAuthSession(false /* force */)); 505 } 506 507 @Test testCancelAuthentication_whenStateAuthForcedCalled_invokesCancel()508 public void testCancelAuthentication_whenStateAuthForcedCalled_invokesCancel() 509 throws RemoteException { 510 testInvokesCancel(session -> session.onCancelAuthSession(true /* force */)); 511 } 512 513 @Test testCancelAuthentication_whenDialogDismissed()514 public void testCancelAuthentication_whenDialogDismissed() throws RemoteException { 515 testInvokesCancel(session -> session.onDialogDismissed(DISMISSED_REASON_NEGATIVE, null)); 516 } 517 518 @Test testCallbackOnAcquired()519 public void testCallbackOnAcquired() throws RemoteException { 520 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_REAR); 521 522 final AuthSession session = createAuthSession(mSensors, 523 false /* checkDevicePolicyManager */, 524 Authenticators.BIOMETRIC_STRONG, 525 TEST_REQUEST_ID, 526 0 /* operationId */, 527 0 /* userId */); 528 529 session.onAcquired(0, FingerprintManager.FINGERPRINT_ACQUIRED_PARTIAL, 0); 530 verify(mStatusBarService).onBiometricHelp(anyInt(), eq(ACQUIRED_STRING)); 531 verify(mClientReceiver).onAcquired(eq(1), eq(ACQUIRED_STRING)); 532 533 session.onAcquired(0, FingerprintManager.FINGERPRINT_ACQUIRED_VENDOR, 0); 534 verify(mStatusBarService).onBiometricHelp(anyInt(), eq(ACQUIRED_STRING_VENDOR)); 535 verify(mClientReceiver).onAcquired( 536 eq(FingerprintManager.FINGERPRINT_ACQUIRED_VENDOR_BASE), 537 eq(ACQUIRED_STRING_VENDOR)); 538 } 539 540 @Test testLogOnDialogDismissed_authenticatedWithConfirmation()541 public void testLogOnDialogDismissed_authenticatedWithConfirmation() throws RemoteException { 542 final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class); 543 544 setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator); 545 final AuthSession session = createAuthSession(mSensors, 546 false /* checkDevicePolicyManager */, 547 Authenticators.BIOMETRIC_STRONG, 548 TEST_REQUEST_ID, 549 0 /* operationId */, 550 0 /* userId */); 551 session.goToInitialState(); 552 assertEquals(STATE_AUTH_CALLED, session.getState()); 553 554 session.onDialogDismissed(DISMISSED_REASON_BIOMETRIC_CONFIRMED, null); 555 verify(mBiometricFrameworkStatsLogger, times(1)).authenticate( 556 (OperationContextExt) any(), 557 eq(BiometricsProtoEnums.MODALITY_FACE), 558 eq(BiometricsProtoEnums.ACTION_UNKNOWN), 559 eq(BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT), 560 eq(false), /* debugEnabled */ 561 anyLong(), /* latency */ 562 eq(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED), 563 eq(true), /* confirmationRequired */ 564 eq(0) /* userId */, 565 eq(-1f) /* ambientLightLux */); 566 } 567 568 @Test testLogOnDialogDismissed_authenticatedWithoutConfirmation()569 public void testLogOnDialogDismissed_authenticatedWithoutConfirmation() throws RemoteException { 570 final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class); 571 572 setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator); 573 final AuthSession session = createAuthSession(mSensors, 574 false /* checkDevicePolicyManager */, 575 Authenticators.BIOMETRIC_STRONG, 576 TEST_REQUEST_ID, 577 0 /* operationId */, 578 0 /* userId */); 579 session.goToInitialState(); 580 assertEquals(STATE_AUTH_CALLED, session.getState()); 581 582 session.onDialogDismissed(DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED, null); 583 verify(mBiometricFrameworkStatsLogger, never()).authenticate( 584 any(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyLong(), anyInt(), 585 anyBoolean(), anyInt(), eq(-1f)); 586 verify(mBiometricFrameworkStatsLogger, never()).error( 587 any(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyLong(), anyInt(), 588 anyInt(), anyInt()); 589 } 590 591 @Test testLogOnDialogDismissed_negativeButton()592 public void testLogOnDialogDismissed_negativeButton() throws RemoteException { 593 final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class); 594 595 setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator); 596 final AuthSession session = createAuthSession(mSensors, 597 false /* checkDevicePolicyManager */, 598 Authenticators.BIOMETRIC_STRONG, 599 TEST_REQUEST_ID, 600 0 /* operationId */, 601 0 /* userId */); 602 session.goToInitialState(); 603 assertEquals(STATE_AUTH_CALLED, session.getState()); 604 605 session.onDialogDismissed(DISMISSED_REASON_NEGATIVE, null); 606 verify(mBiometricFrameworkStatsLogger, times(1)).error( 607 (OperationContextExt) any(), 608 eq(BiometricsProtoEnums.MODALITY_FACE), 609 eq(BiometricsProtoEnums.ACTION_AUTHENTICATE), 610 eq(BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT), 611 eq(false), 612 anyLong(), 613 eq(BIOMETRIC_ERROR_NEGATIVE_BUTTON), 614 eq(0) /* vendorCode */, 615 eq(0) /* userId */); 616 } 617 618 @Test testLogOnDialogDismissed_contentViewMoreOptionsButton()619 public void testLogOnDialogDismissed_contentViewMoreOptionsButton() throws RemoteException { 620 final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class); 621 622 setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator); 623 final AuthSession session = createAuthSession(mSensors, 624 false /* checkDevicePolicyManager */, 625 Authenticators.BIOMETRIC_STRONG, 626 TEST_REQUEST_ID, 627 0 /* operationId */, 628 0 /* userId */); 629 session.goToInitialState(); 630 assertEquals(STATE_AUTH_CALLED, session.getState()); 631 632 session.onDialogDismissed(DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS, null); 633 verify(mBiometricFrameworkStatsLogger, times(1)).error( 634 (OperationContextExt) any(), 635 eq(BiometricsProtoEnums.MODALITY_FACE), 636 eq(BiometricsProtoEnums.ACTION_AUTHENTICATE), 637 eq(BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT), 638 eq(false), 639 anyLong(), 640 eq(BIOMETRIC_ERROR_CONTENT_VIEW_MORE_OPTIONS_BUTTON), 641 eq(0) /* vendorCode */, 642 eq(0) /* userId */); 643 } 644 645 @Test onErrorReceivedAfterOnTryAgainPressedWhenSensorsAuthenticating()646 public void onErrorReceivedAfterOnTryAgainPressedWhenSensorsAuthenticating() throws Exception { 647 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); 648 setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class)); 649 final long operationId = 123; 650 final int userId = 10; 651 final AuthSession session = createAuthSession(mSensors, 652 false /* checkDevicePolicyManager */, 653 Authenticators.BIOMETRIC_STRONG, 654 TEST_REQUEST_ID, 655 operationId, 656 userId); 657 session.goToInitialState(); 658 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 659 session.onCookieReceived( 660 session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie()); 661 } 662 session.onDialogAnimatedIn(true /* startFingerprintNow */); 663 664 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 665 assertEquals(BiometricSensor.STATE_AUTHENTICATING, sensor.getSensorState()); 666 } 667 session.onTryAgainPressed(); 668 session.onErrorReceived(0 /* sensorId */, 669 session.mPreAuthInfo.eligibleSensors.get(0 /* sensorId */).getCookie(), 670 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT, 0); 671 672 verify(mStatusBarService).onBiometricError(anyInt(), anyInt(), anyInt()); 673 } 674 675 @Test onErrorReceivedAfterOnTryAgainPressedWhenSensorStopped()676 public void onErrorReceivedAfterOnTryAgainPressedWhenSensorStopped() throws Exception { 677 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); 678 setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class)); 679 final long operationId = 123; 680 final int userId = 10; 681 final AuthSession session = createAuthSession(mSensors, 682 false /* checkDevicePolicyManager */, 683 Authenticators.BIOMETRIC_STRONG, 684 TEST_REQUEST_ID, 685 operationId, 686 userId); 687 session.goToInitialState(); 688 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 689 session.onCookieReceived( 690 session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie()); 691 } 692 session.onDialogAnimatedIn(true /* startFingerprintNow */); 693 694 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 695 sensor.goToStoppedStateIfCookieMatches(sensor.getCookie(), 696 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT); 697 assertEquals(BiometricSensor.STATE_STOPPED, sensor.getSensorState()); 698 } 699 700 session.onTryAgainPressed(); 701 session.onErrorReceived(0 /* sensorId */, 702 session.mPreAuthInfo.eligibleSensors.get(0 /* sensorId */).getCookie(), 703 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT, 0); 704 705 verify(mStatusBarService, never()).onBiometricError(anyInt(), anyInt(), anyInt()); 706 } 707 708 @Test onAuthReceivedWhileWaitingForConfirmation_SFPS()709 public void onAuthReceivedWhileWaitingForConfirmation_SFPS() throws Exception { 710 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_POWER_BUTTON); 711 setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class)); 712 final long operationId = 123; 713 final int userId = 10; 714 final AuthSession session = createAuthSession(mSensors, 715 false /* checkDevicePolicyManager */, 716 Authenticators.BIOMETRIC_STRONG, 717 TEST_REQUEST_ID, 718 operationId, 719 userId); 720 session.goToInitialState(); 721 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 722 session.onCookieReceived( 723 session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie()); 724 } 725 session.onDialogAnimatedIn(true /* startFingerprintNow */); 726 727 // Face succeeds 728 session.onAuthenticationSucceeded(1, true, null); 729 verify(mStatusBarService).onBiometricAuthenticated(TYPE_FACE); 730 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 731 if (sensor.modality == FingerprintSensorProperties.TYPE_POWER_BUTTON) { 732 assertEquals(BiometricSensor.STATE_AUTHENTICATING, sensor.getSensorState()); 733 } 734 } 735 736 // SFPS succeeds 737 session.onAuthenticationSucceeded(0, true, null); 738 verify(mStatusBarService).onBiometricAuthenticated(TYPE_FINGERPRINT); 739 } 740 741 @Test onDialogDismissedResetLockout_Confirmed()742 public void onDialogDismissedResetLockout_Confirmed() throws Exception { 743 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_POWER_BUTTON); 744 setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class)); 745 final long operationId = 123; 746 final int userId = 10; 747 final AuthSession session = createAuthSession(mSensors, 748 false /* checkDevicePolicyManager */, 749 Authenticators.BIOMETRIC_STRONG, 750 TEST_REQUEST_ID, 751 operationId, 752 userId); 753 session.goToInitialState(); 754 session.onDialogAnimatedIn(true /* startFingerprintNow */); 755 756 // Face succeeds 757 session.onAuthenticationSucceeded(1, true, new byte[1]); 758 759 // Dismiss through confirmation 760 session.onDialogDismissed(DISMISSED_REASON_BIOMETRIC_CONFIRMED, null); 761 762 verify(mBiometricManager).resetLockoutTimeBound(any(), any(), anyInt(), anyInt(), any()); 763 } 764 765 @Test onDialogDismissedResetLockout_Cancelled()766 public void onDialogDismissedResetLockout_Cancelled() throws Exception { 767 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_POWER_BUTTON); 768 setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class)); 769 final long operationId = 123; 770 final int userId = 10; 771 final AuthSession session = createAuthSession(mSensors, 772 false /* checkDevicePolicyManager */, 773 Authenticators.BIOMETRIC_STRONG, 774 TEST_REQUEST_ID, 775 operationId, 776 userId); 777 session.goToInitialState(); 778 session.onDialogAnimatedIn(true /* startFingerprintNow */); 779 780 // Face succeeds 781 session.onAuthenticationSucceeded(1, true, new byte[1]); 782 783 // User cancel after success 784 session.onDialogDismissed(DISMISSED_REASON_USER_CANCEL, null); 785 786 verify(mBiometricManager).resetLockoutTimeBound(any(), any(), anyInt(), anyInt(), any()); 787 } 788 789 // TODO (b/208484275) : Enable these tests 790 // @Test 791 // public void testPreAuth_canAuthAndPrivacyDisabled() throws Exception { 792 // SensorPrivacyManager manager = ExtendedMockito.mock(SensorPrivacyManager.class); 793 // when(manager 794 // .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, anyInt())) 795 // .thenReturn(false); 796 // when(mContext.getSystemService(SensorPrivacyManager.class)) 797 // .thenReturn(manager); 798 // setupFace(1 /* id */, false /* confirmationAlwaysRequired */, 799 // mock(IBiometricAuthenticator.class)); 800 // final PromptInfo promptInfo = createPromptInfo(Authenticators.BIOMETRIC_STRONG); 801 // final PreAuthInfo preAuthInfo = createPreAuthInfo(mSensors, 0, promptInfo, false); 802 // assertEquals(BiometricManager.BIOMETRIC_SUCCESS, preAuthInfo.getCanAuthenticateResult()); 803 // for (BiometricSensor sensor : preAuthInfo.eligibleSensors) { 804 // assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState()); 805 // } 806 // } 807 808 // @Test 809 // public void testPreAuth_cannotAuthAndPrivacyEnabled() throws Exception { 810 // SensorPrivacyManager manager = ExtendedMockito.mock(SensorPrivacyManager.class); 811 // when(manager 812 // .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, anyInt())) 813 // .thenReturn(true); 814 // when(mContext.getSystemService(SensorPrivacyManager.class)) 815 // .thenReturn(manager); 816 // setupFace(1 /* id */, false /* confirmationAlwaysRequired */, 817 // mock(IBiometricAuthenticator.class)); 818 // final PromptInfo promptInfo = createPromptInfo(Authenticators.BIOMETRIC_STRONG); 819 // final PreAuthInfo preAuthInfo = createPreAuthInfo(mSensors, 0, promptInfo, false); 820 // assertEquals(BiometricManager.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED, 821 // preAuthInfo.getCanAuthenticateResult()); 822 // // Even though canAuth returns privacy enabled, we should still be able to authenticate. 823 // for (BiometricSensor sensor : preAuthInfo.eligibleSensors) { 824 // assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState()); 825 // } 826 // } 827 828 // @Test 829 // public void testPreAuth_canAuthAndPrivacyEnabledCredentialEnabled() throws Exception { 830 // SensorPrivacyManager manager = ExtendedMockito.mock(SensorPrivacyManager.class); 831 // when(manager 832 // .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, anyInt())) 833 // .thenReturn(true); 834 // when(mContext.getSystemService(SensorPrivacyManager.class)) 835 // .thenReturn(manager); 836 // setupFace(1 /* id */, false /* confirmationAlwaysRequired */, 837 // mock(IBiometricAuthenticator.class)); 838 // final PromptInfo promptInfo = 839 // createPromptInfo(Authenticators.BIOMETRIC_STRONG 840 // | Authenticators. DEVICE_CREDENTIAL); 841 // final PreAuthInfo preAuthInfo = createPreAuthInfo(mSensors, 0, promptInfo, false); 842 // assertEquals(BiometricManager.BIOMETRIC_SUCCESS, preAuthInfo.getCanAuthenticateResult()); 843 // for (BiometricSensor sensor : preAuthInfo.eligibleSensors) { 844 // assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState()); 845 // } 846 // } 847 testInvokesCancel(Consumer<AuthSession> sessionConsumer)848 private void testInvokesCancel(Consumer<AuthSession> sessionConsumer) throws RemoteException { 849 final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class); 850 851 setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator); 852 final AuthSession session = createAuthSession(mSensors, 853 false /* checkDevicePolicyManager */, 854 Authenticators.BIOMETRIC_STRONG, 855 TEST_REQUEST_ID, 856 0 /* operationId */, 857 0 /* userId */); 858 859 session.goToInitialState(); 860 assertEquals(STATE_AUTH_CALLED, session.getState()); 861 862 sessionConsumer.accept(session); 863 864 verify(faceAuthenticator).cancelAuthenticationFromService( 865 eq(mToken), eq(TEST_PACKAGE), eq(TEST_REQUEST_ID)); 866 } 867 createPreAuthInfo(List<BiometricSensor> sensors, int userId, PromptInfo promptInfo, boolean checkDevicePolicyManager)868 private PreAuthInfo createPreAuthInfo(List<BiometricSensor> sensors, int userId, 869 PromptInfo promptInfo, boolean checkDevicePolicyManager) throws RemoteException { 870 return PreAuthInfo.create(mTrustManager, 871 mDevicePolicyManager, 872 mSettingObserver, 873 sensors, 874 userId, 875 promptInfo, 876 TEST_PACKAGE, 877 checkDevicePolicyManager, 878 mContext, 879 mBiometricCameraManager, 880 mUserManager); 881 } 882 createAuthSession(List<BiometricSensor> sensors, boolean checkDevicePolicyManager, @Authenticators.Types int authenticators, long requestId, long operationId, int userId)883 private AuthSession createAuthSession(List<BiometricSensor> sensors, 884 boolean checkDevicePolicyManager, @Authenticators.Types int authenticators, 885 long requestId, long operationId, int userId) throws RemoteException { 886 887 final PromptInfo promptInfo = createPromptInfo(authenticators); 888 889 final PreAuthInfo preAuthInfo = createPreAuthInfo(sensors, userId, promptInfo, 890 checkDevicePolicyManager); 891 return new AuthSession(mContext, mBiometricContext, mStatusBarService, mSysuiReceiver, 892 mKeyStoreAuthorization, mRandom, mClientDeathReceiver, preAuthInfo, mToken, 893 requestId, operationId, userId, mSensorReceiver, mClientReceiver, TEST_PACKAGE, 894 promptInfo, false /* debugEnabled */, mFingerprintSensorProps, 895 mBiometricFrameworkStatsLogger); 896 } 897 createPromptInfo(@uthenticators.Types int authenticators)898 private PromptInfo createPromptInfo(@Authenticators.Types int authenticators) { 899 PromptInfo promptInfo = new PromptInfo(); 900 promptInfo.setAuthenticators(authenticators); 901 return promptInfo; 902 } 903 setupFingerprint(int id, @FingerprintSensorProperties.SensorType int type)904 private void setupFingerprint(int id, @FingerprintSensorProperties.SensorType int type) 905 throws RemoteException { 906 IBiometricAuthenticator fingerprintAuthenticator = mock(IBiometricAuthenticator.class); 907 when(fingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true); 908 when(fingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); 909 mSensors.add(new BiometricSensor(mContext, id, 910 TYPE_FINGERPRINT /* modality */, 911 Authenticators.BIOMETRIC_STRONG /* strength */, 912 fingerprintAuthenticator) { 913 @Override 914 boolean confirmationAlwaysRequired(int userId) { 915 return false; // no-op / unsupported 916 } 917 918 @Override 919 boolean confirmationSupported() { 920 return false; // fingerprint does not support confirmation 921 } 922 }); 923 924 final List<ComponentInfoInternal> componentInfo = new ArrayList<>(); 925 componentInfo.add(new ComponentInfoInternal("faceSensor" /* componentId */, 926 "vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */, 927 "00000001" /* serialNumber */, "" /* softwareVersion */)); 928 componentInfo.add(new ComponentInfoInternal("matchingAlgorithm" /* componentId */, 929 "" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */, 930 "vendor/version/revision" /* softwareVersion */)); 931 932 mFingerprintSensorProps.add(new FingerprintSensorPropertiesInternal(id, 933 SensorProperties.STRENGTH_STRONG, 934 5 /* maxEnrollmentsPerUser */, 935 componentInfo, 936 type, 937 false /* resetLockoutRequiresHardwareAuthToken */)); 938 939 when(mSettingObserver.getEnabledForApps(anyInt(), anyInt())).thenReturn(true); 940 } 941 setupFace(int id, boolean confirmationAlwaysRequired, IBiometricAuthenticator authenticator)942 private void setupFace(int id, boolean confirmationAlwaysRequired, 943 IBiometricAuthenticator authenticator) throws RemoteException { 944 when(authenticator.isHardwareDetected(any())).thenReturn(true); 945 when(authenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); 946 mSensors.add(new BiometricSensor(mContext, id, 947 TYPE_FACE /* modality */, 948 Authenticators.BIOMETRIC_STRONG /* strength */, 949 authenticator) { 950 @Override 951 boolean confirmationAlwaysRequired(int userId) { 952 return confirmationAlwaysRequired; 953 } 954 955 @Override 956 boolean confirmationSupported() { 957 return true; 958 } 959 }); 960 961 when(mSettingObserver.getEnabledForApps(anyInt(), anyInt())).thenReturn(true); 962 } 963 } 964