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.BiometricPrompt.DISMISSED_REASON_NEGATIVE; 22 23 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_CALLED; 24 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED; 25 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED_UI_SHOWING; 26 27 import static junit.framework.Assert.assertEquals; 28 import static junit.framework.Assert.assertFalse; 29 import static junit.framework.Assert.assertTrue; 30 31 import static org.mockito.ArgumentMatchers.any; 32 import static org.mockito.ArgumentMatchers.anyBoolean; 33 import static org.mockito.ArgumentMatchers.anyInt; 34 import static org.mockito.ArgumentMatchers.anyLong; 35 import static org.mockito.ArgumentMatchers.eq; 36 import static org.mockito.Mockito.mock; 37 import static org.mockito.Mockito.never; 38 import static org.mockito.Mockito.times; 39 import static org.mockito.Mockito.verify; 40 import static org.mockito.Mockito.when; 41 42 import android.annotation.NonNull; 43 import android.app.admin.DevicePolicyManager; 44 import android.app.trust.ITrustManager; 45 import android.content.Context; 46 import android.hardware.biometrics.BiometricManager.Authenticators; 47 import android.hardware.biometrics.ComponentInfoInternal; 48 import android.hardware.biometrics.IBiometricAuthenticator; 49 import android.hardware.biometrics.IBiometricSensorReceiver; 50 import android.hardware.biometrics.IBiometricServiceReceiver; 51 import android.hardware.biometrics.IBiometricSysuiReceiver; 52 import android.hardware.biometrics.PromptInfo; 53 import android.hardware.biometrics.SensorProperties; 54 import android.hardware.fingerprint.FingerprintSensorProperties; 55 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; 56 import android.os.Binder; 57 import android.os.IBinder; 58 import android.os.RemoteException; 59 import android.platform.test.annotations.Presubmit; 60 import android.security.KeyStore; 61 62 import androidx.test.filters.SmallTest; 63 64 import com.android.internal.statusbar.IStatusBarService; 65 66 import org.junit.Before; 67 import org.junit.Test; 68 import org.mockito.Mock; 69 import org.mockito.MockitoAnnotations; 70 71 import java.util.ArrayList; 72 import java.util.List; 73 import java.util.Random; 74 import java.util.function.Consumer; 75 76 @Presubmit 77 @SmallTest 78 public class AuthSessionTest { 79 80 private static final String TEST_PACKAGE = "test_package"; 81 private static final long TEST_REQUEST_ID = 22; 82 83 @Mock private Context mContext; 84 @Mock private ITrustManager mTrustManager; 85 @Mock private DevicePolicyManager mDevicePolicyManager; 86 @Mock private BiometricService.SettingObserver mSettingObserver; 87 @Mock private IBiometricSensorReceiver mSensorReceiver; 88 @Mock private IBiometricServiceReceiver mClientReceiver; 89 @Mock private IStatusBarService mStatusBarService; 90 @Mock private IBiometricSysuiReceiver mSysuiReceiver; 91 @Mock private KeyStore mKeyStore; 92 @Mock private AuthSession.ClientDeathReceiver mClientDeathReceiver; 93 94 private Random mRandom; 95 private IBinder mToken; 96 97 // Assume all tests can be done with the same set of sensors for now. 98 @NonNull private List<BiometricSensor> mSensors; 99 @NonNull private List<FingerprintSensorPropertiesInternal> mFingerprintSensorProps; 100 101 @Before setUp()102 public void setUp() throws Exception { 103 MockitoAnnotations.initMocks(this); 104 when(mClientReceiver.asBinder()).thenReturn(mock(Binder.class)); 105 mRandom = new Random(); 106 mToken = new Binder(); 107 mSensors = new ArrayList<>(); 108 mFingerprintSensorProps = new ArrayList<>(); 109 } 110 111 @Test testNewAuthSession_eligibleSensorsSetToStateUnknown()112 public void testNewAuthSession_eligibleSensorsSetToStateUnknown() throws RemoteException { 113 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_REAR); 114 setupFace(1 /* id */, false /* confirmationAlwaysRequired */, 115 mock(IBiometricAuthenticator.class)); 116 117 final AuthSession session = createAuthSession(mSensors, 118 false /* checkDevicePolicyManager */, 119 Authenticators.BIOMETRIC_STRONG, 120 TEST_REQUEST_ID, 121 0 /* operationId */, 122 0 /* userId */); 123 124 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 125 assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState()); 126 } 127 } 128 129 @Test testStartNewAuthSession()130 public void testStartNewAuthSession() throws RemoteException { 131 setupFace(0 /* id */, false /* confirmationAlwaysRequired */, 132 mock(IBiometricAuthenticator.class)); 133 setupFingerprint(1 /* id */, FingerprintSensorProperties.TYPE_REAR); 134 135 final boolean requireConfirmation = true; 136 final long operationId = 123; 137 final int userId = 10; 138 139 final AuthSession session = createAuthSession(mSensors, 140 false /* checkDevicePolicyManager */, 141 Authenticators.BIOMETRIC_STRONG, 142 TEST_REQUEST_ID, 143 operationId, 144 userId); 145 assertEquals(mSensors.size(), session.mPreAuthInfo.eligibleSensors.size()); 146 147 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 148 assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState()); 149 assertEquals(0, sensor.getCookie()); 150 } 151 152 session.goToInitialState(); 153 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 154 assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState()); 155 assertTrue("Cookie must be >0", sensor.getCookie() > 0); 156 verify(sensor.impl).prepareForAuthentication( 157 eq(sensor.confirmationSupported() && requireConfirmation), 158 eq(mToken), 159 eq(operationId), 160 eq(userId), 161 eq(mSensorReceiver), 162 eq(TEST_PACKAGE), 163 eq(TEST_REQUEST_ID), 164 eq(sensor.getCookie()), 165 anyBoolean() /* allowBackgroundAuthentication */); 166 } 167 168 final int cookie1 = session.mPreAuthInfo.eligibleSensors.get(0).getCookie(); 169 session.onCookieReceived(cookie1); 170 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 171 if (cookie1 == sensor.getCookie()) { 172 assertEquals(BiometricSensor.STATE_COOKIE_RETURNED, sensor.getSensorState()); 173 } else { 174 assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState()); 175 } 176 } 177 assertFalse(session.allCookiesReceived()); 178 179 final int cookie2 = session.mPreAuthInfo.eligibleSensors.get(1).getCookie(); 180 session.onCookieReceived(cookie2); 181 assertTrue(session.allCookiesReceived()); 182 183 184 // for multi-sensor face then fingerprint is the default policy 185 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 186 if (sensor.modality == TYPE_FACE) { 187 verify(sensor.impl).startPreparedClient(eq(sensor.getCookie())); 188 assertEquals(BiometricSensor.STATE_AUTHENTICATING, sensor.getSensorState()); 189 } else if (sensor.modality == TYPE_FINGERPRINT) { 190 assertEquals(BiometricSensor.STATE_COOKIE_RETURNED, sensor.getSensorState()); 191 } 192 } 193 } 194 195 @Test testCancelReducesAppetiteForCookies()196 public void testCancelReducesAppetiteForCookies() throws Exception { 197 setupFace(0 /* id */, false /* confirmationAlwaysRequired */, 198 mock(IBiometricAuthenticator.class)); 199 setupFingerprint(1 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); 200 201 final AuthSession session = createAuthSession(mSensors, 202 false /* checkDevicePolicyManager */, 203 Authenticators.BIOMETRIC_STRONG, 204 TEST_REQUEST_ID, 205 44 /* operationId */, 206 2 /* userId */); 207 208 session.goToInitialState(); 209 210 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 211 assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState()); 212 } 213 214 session.onCancelAuthSession(false /* force */); 215 216 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 217 session.onCookieReceived(sensor.getCookie()); 218 assertEquals(BiometricSensor.STATE_CANCELING, sensor.getSensorState()); 219 } 220 } 221 222 @Test testMultiAuth_singleSensor_fingerprintSensorStartsAfterDialogAnimationCompletes()223 public void testMultiAuth_singleSensor_fingerprintSensorStartsAfterDialogAnimationCompletes() 224 throws Exception { 225 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); 226 testMultiAuth_fingerprintSensorStartsAfterUINotifies(); 227 } 228 229 @Test testMultiAuth_fingerprintSensorStartsAfterDialogAnimationCompletes()230 public void testMultiAuth_fingerprintSensorStartsAfterDialogAnimationCompletes() 231 throws Exception { 232 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); 233 setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class)); 234 testMultiAuth_fingerprintSensorStartsAfterUINotifies(); 235 } 236 testMultiAuth_fingerprintSensorStartsAfterUINotifies()237 public void testMultiAuth_fingerprintSensorStartsAfterUINotifies() 238 throws Exception { 239 final long operationId = 123; 240 final int userId = 10; 241 final int fingerprintSensorId = mSensors.stream() 242 .filter(s -> s.modality == TYPE_FINGERPRINT) 243 .map(s -> s.id) 244 .findFirst() 245 .orElse(-1); 246 247 final AuthSession session = createAuthSession(mSensors, 248 false /* checkDevicePolicyManager */, 249 Authenticators.BIOMETRIC_STRONG, 250 TEST_REQUEST_ID, 251 operationId, 252 userId); 253 assertEquals(mSensors.size(), session.mPreAuthInfo.eligibleSensors.size()); 254 255 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 256 assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState()); 257 assertEquals(0, sensor.getCookie()); 258 } 259 260 session.goToInitialState(); 261 262 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 263 assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState()); 264 session.onCookieReceived( 265 session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie()); 266 if (fingerprintSensorId == sensor.id) { 267 assertEquals(BiometricSensor.STATE_COOKIE_RETURNED, sensor.getSensorState()); 268 } else { 269 assertEquals(BiometricSensor.STATE_AUTHENTICATING, sensor.getSensorState()); 270 } 271 } 272 assertTrue(session.allCookiesReceived()); 273 274 // fingerprint sensor does not start even if all cookies are received 275 assertEquals(STATE_AUTH_STARTED, session.getState()); 276 verify(mStatusBarService).showAuthenticationDialog(any(), any(), any(), 277 anyBoolean(), anyBoolean(), anyInt(), anyLong(), any(), anyLong(), anyInt()); 278 279 // Notify AuthSession that the UI is shown. Then, fingerprint sensor should be started. 280 session.onDialogAnimatedIn(); 281 assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState()); 282 assertEquals(BiometricSensor.STATE_AUTHENTICATING, 283 session.mPreAuthInfo.eligibleSensors.get(fingerprintSensorId).getSensorState()); 284 } 285 286 @Test testOnDialogAnimatedInDoesNothingDuringInvalidState()287 public void testOnDialogAnimatedInDoesNothingDuringInvalidState() throws Exception { 288 setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL); 289 final long operationId = 123; 290 final int userId = 10; 291 292 final AuthSession session = createAuthSession(mSensors, 293 false /* checkDevicePolicyManager */, 294 Authenticators.BIOMETRIC_STRONG, 295 TEST_REQUEST_ID, 296 operationId, 297 userId); 298 final IBiometricAuthenticator impl = session.mPreAuthInfo.eligibleSensors.get(0).impl; 299 300 session.goToInitialState(); 301 for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) { 302 assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState()); 303 session.onCookieReceived( 304 session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie()); 305 } 306 assertTrue(session.allCookiesReceived()); 307 assertEquals(STATE_AUTH_STARTED, session.getState()); 308 verify(impl, never()).startPreparedClient(anyInt()); 309 310 // First invocation should start the client monitor. 311 session.onDialogAnimatedIn(); 312 assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState()); 313 verify(impl).startPreparedClient(anyInt()); 314 315 // Subsequent invocations should not start the client monitor again. 316 session.onDialogAnimatedIn(); 317 session.onDialogAnimatedIn(); 318 session.onDialogAnimatedIn(); 319 assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState()); 320 verify(impl, times(1)).startPreparedClient(anyInt()); 321 } 322 323 @Test testCancelAuthentication_whenStateAuthCalled_invokesCancel()324 public void testCancelAuthentication_whenStateAuthCalled_invokesCancel() 325 throws RemoteException { 326 testInvokesCancel(session -> session.onCancelAuthSession(false /* force */)); 327 } 328 329 @Test testCancelAuthentication_whenStateAuthForcedCalled_invokesCancel()330 public void testCancelAuthentication_whenStateAuthForcedCalled_invokesCancel() 331 throws RemoteException { 332 testInvokesCancel(session -> session.onCancelAuthSession(true /* force */)); 333 } 334 335 @Test testCancelAuthentication_whenDialogDismissed()336 public void testCancelAuthentication_whenDialogDismissed() throws RemoteException { 337 testInvokesCancel(session -> session.onDialogDismissed(DISMISSED_REASON_NEGATIVE, null)); 338 } 339 340 // TODO (b/208484275) : Enable these tests 341 // @Test 342 // public void testPreAuth_canAuthAndPrivacyDisabled() throws Exception { 343 // SensorPrivacyManager manager = ExtendedMockito.mock(SensorPrivacyManager.class); 344 // when(manager 345 // .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, anyInt())) 346 // .thenReturn(false); 347 // when(mContext.getSystemService(SensorPrivacyManager.class)) 348 // .thenReturn(manager); 349 // setupFace(1 /* id */, false /* confirmationAlwaysRequired */, 350 // mock(IBiometricAuthenticator.class)); 351 // final PromptInfo promptInfo = createPromptInfo(Authenticators.BIOMETRIC_STRONG); 352 // final PreAuthInfo preAuthInfo = createPreAuthInfo(mSensors, 0, promptInfo, false); 353 // assertEquals(BiometricManager.BIOMETRIC_SUCCESS, preAuthInfo.getCanAuthenticateResult()); 354 // for (BiometricSensor sensor : preAuthInfo.eligibleSensors) { 355 // assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState()); 356 // } 357 // } 358 359 // @Test 360 // public void testPreAuth_cannotAuthAndPrivacyEnabled() throws Exception { 361 // SensorPrivacyManager manager = ExtendedMockito.mock(SensorPrivacyManager.class); 362 // when(manager 363 // .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, anyInt())) 364 // .thenReturn(true); 365 // when(mContext.getSystemService(SensorPrivacyManager.class)) 366 // .thenReturn(manager); 367 // setupFace(1 /* id */, false /* confirmationAlwaysRequired */, 368 // mock(IBiometricAuthenticator.class)); 369 // final PromptInfo promptInfo = createPromptInfo(Authenticators.BIOMETRIC_STRONG); 370 // final PreAuthInfo preAuthInfo = createPreAuthInfo(mSensors, 0, promptInfo, false); 371 // assertEquals(BiometricManager.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED, 372 // preAuthInfo.getCanAuthenticateResult()); 373 // // Even though canAuth returns privacy enabled, we should still be able to authenticate. 374 // for (BiometricSensor sensor : preAuthInfo.eligibleSensors) { 375 // assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState()); 376 // } 377 // } 378 379 // @Test 380 // public void testPreAuth_canAuthAndPrivacyEnabledCredentialEnabled() throws Exception { 381 // SensorPrivacyManager manager = ExtendedMockito.mock(SensorPrivacyManager.class); 382 // when(manager 383 // .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, anyInt())) 384 // .thenReturn(true); 385 // when(mContext.getSystemService(SensorPrivacyManager.class)) 386 // .thenReturn(manager); 387 // setupFace(1 /* id */, false /* confirmationAlwaysRequired */, 388 // mock(IBiometricAuthenticator.class)); 389 // final PromptInfo promptInfo = 390 // createPromptInfo(Authenticators.BIOMETRIC_STRONG 391 // | Authenticators. DEVICE_CREDENTIAL); 392 // final PreAuthInfo preAuthInfo = createPreAuthInfo(mSensors, 0, promptInfo, false); 393 // assertEquals(BiometricManager.BIOMETRIC_SUCCESS, preAuthInfo.getCanAuthenticateResult()); 394 // for (BiometricSensor sensor : preAuthInfo.eligibleSensors) { 395 // assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState()); 396 // } 397 // } 398 testInvokesCancel(Consumer<AuthSession> sessionConsumer)399 private void testInvokesCancel(Consumer<AuthSession> sessionConsumer) throws RemoteException { 400 final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class); 401 402 setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator); 403 final AuthSession session = createAuthSession(mSensors, 404 false /* checkDevicePolicyManager */, 405 Authenticators.BIOMETRIC_STRONG, 406 TEST_REQUEST_ID, 407 0 /* operationId */, 408 0 /* userId */); 409 410 session.goToInitialState(); 411 assertEquals(STATE_AUTH_CALLED, session.getState()); 412 413 sessionConsumer.accept(session); 414 415 verify(faceAuthenticator).cancelAuthenticationFromService( 416 eq(mToken), eq(TEST_PACKAGE), eq(TEST_REQUEST_ID)); 417 } 418 createPreAuthInfo(List<BiometricSensor> sensors, int userId, PromptInfo promptInfo, boolean checkDevicePolicyManager)419 private PreAuthInfo createPreAuthInfo(List<BiometricSensor> sensors, int userId, 420 PromptInfo promptInfo, boolean checkDevicePolicyManager) throws RemoteException { 421 return PreAuthInfo.create(mTrustManager, 422 mDevicePolicyManager, 423 mSettingObserver, 424 sensors, 425 userId, 426 promptInfo, 427 TEST_PACKAGE, 428 checkDevicePolicyManager, 429 mContext); 430 } 431 createAuthSession(List<BiometricSensor> sensors, boolean checkDevicePolicyManager, @Authenticators.Types int authenticators, long requestId, long operationId, int userId)432 private AuthSession createAuthSession(List<BiometricSensor> sensors, 433 boolean checkDevicePolicyManager, @Authenticators.Types int authenticators, 434 long requestId, long operationId, int userId) throws RemoteException { 435 436 final PromptInfo promptInfo = createPromptInfo(authenticators); 437 438 final PreAuthInfo preAuthInfo = createPreAuthInfo(sensors, userId, promptInfo, 439 checkDevicePolicyManager); 440 return new AuthSession(mContext, mStatusBarService, mSysuiReceiver, mKeyStore, 441 mRandom, mClientDeathReceiver, preAuthInfo, mToken, requestId, operationId, userId, 442 mSensorReceiver, mClientReceiver, TEST_PACKAGE, promptInfo, 443 false /* debugEnabled */, mFingerprintSensorProps); 444 } 445 createPromptInfo(@uthenticators.Types int authenticators)446 private PromptInfo createPromptInfo(@Authenticators.Types int authenticators) { 447 PromptInfo promptInfo = new PromptInfo(); 448 promptInfo.setAuthenticators(authenticators); 449 return promptInfo; 450 } 451 setupFingerprint(int id, @FingerprintSensorProperties.SensorType int type)452 private void setupFingerprint(int id, @FingerprintSensorProperties.SensorType int type) 453 throws RemoteException { 454 IBiometricAuthenticator fingerprintAuthenticator = mock(IBiometricAuthenticator.class); 455 when(fingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true); 456 when(fingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); 457 mSensors.add(new BiometricSensor(mContext, id, 458 TYPE_FINGERPRINT /* modality */, 459 Authenticators.BIOMETRIC_STRONG /* strength */, 460 fingerprintAuthenticator) { 461 @Override 462 boolean confirmationAlwaysRequired(int userId) { 463 return false; // no-op / unsupported 464 } 465 466 @Override 467 boolean confirmationSupported() { 468 return false; // fingerprint does not support confirmation 469 } 470 }); 471 472 final List<ComponentInfoInternal> componentInfo = new ArrayList<>(); 473 componentInfo.add(new ComponentInfoInternal("faceSensor" /* componentId */, 474 "vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */, 475 "00000001" /* serialNumber */, "" /* softwareVersion */)); 476 componentInfo.add(new ComponentInfoInternal("matchingAlgorithm" /* componentId */, 477 "" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */, 478 "vendor/version/revision" /* softwareVersion */)); 479 480 mFingerprintSensorProps.add(new FingerprintSensorPropertiesInternal(id, 481 SensorProperties.STRENGTH_STRONG, 482 5 /* maxEnrollmentsPerUser */, 483 componentInfo, 484 type, 485 false /* resetLockoutRequiresHardwareAuthToken */)); 486 487 when(mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true); 488 } 489 setupFace(int id, boolean confirmationAlwaysRequired, IBiometricAuthenticator authenticator)490 private void setupFace(int id, boolean confirmationAlwaysRequired, 491 IBiometricAuthenticator authenticator) throws RemoteException { 492 when(authenticator.isHardwareDetected(any())).thenReturn(true); 493 when(authenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); 494 mSensors.add(new BiometricSensor(mContext, id, 495 TYPE_FACE /* modality */, 496 Authenticators.BIOMETRIC_STRONG /* strength */, 497 authenticator) { 498 @Override 499 boolean confirmationAlwaysRequired(int userId) { 500 return confirmationAlwaysRequired; 501 } 502 503 @Override 504 boolean confirmationSupported() { 505 return true; 506 } 507 }); 508 509 when(mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true); 510 } 511 } 512