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