1 /* 2 * Copyright (C) 2018 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.Manifest.permission.USE_BIOMETRIC_INTERNAL; 20 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; 21 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; 22 import static android.hardware.biometrics.BiometricManager.Authenticators; 23 24 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_IDLE; 25 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.app.ActivityManager; 29 import android.app.IActivityManager; 30 import android.app.UserSwitchObserver; 31 import android.app.admin.DevicePolicyManager; 32 import android.app.trust.ITrustManager; 33 import android.content.ContentResolver; 34 import android.content.Context; 35 import android.content.pm.PackageManager; 36 import android.content.pm.UserInfo; 37 import android.database.ContentObserver; 38 import android.hardware.SensorPrivacyManager; 39 import android.hardware.biometrics.BiometricAuthenticator; 40 import android.hardware.biometrics.BiometricConstants; 41 import android.hardware.biometrics.BiometricPrompt; 42 import android.hardware.biometrics.IBiometricAuthenticator; 43 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; 44 import android.hardware.biometrics.IBiometricSensorReceiver; 45 import android.hardware.biometrics.IBiometricService; 46 import android.hardware.biometrics.IBiometricServiceReceiver; 47 import android.hardware.biometrics.IBiometricSysuiReceiver; 48 import android.hardware.biometrics.IInvalidationCallback; 49 import android.hardware.biometrics.ITestSession; 50 import android.hardware.biometrics.ITestSessionCallback; 51 import android.hardware.biometrics.PromptInfo; 52 import android.hardware.biometrics.SensorPropertiesInternal; 53 import android.hardware.camera2.CameraManager; 54 import android.hardware.fingerprint.FingerprintManager; 55 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; 56 import android.net.Uri; 57 import android.os.Binder; 58 import android.os.Build; 59 import android.os.DeadObjectException; 60 import android.os.Handler; 61 import android.os.IBinder; 62 import android.os.Looper; 63 import android.os.RemoteException; 64 import android.os.ServiceManager; 65 import android.os.UserHandle; 66 import android.os.UserManager; 67 import android.provider.Settings; 68 import android.security.KeyStore; 69 import android.text.TextUtils; 70 import android.util.ArraySet; 71 import android.util.Pair; 72 import android.util.Slog; 73 import android.util.proto.ProtoOutputStream; 74 75 import com.android.internal.R; 76 import com.android.internal.annotations.VisibleForTesting; 77 import com.android.internal.os.SomeArgs; 78 import com.android.internal.statusbar.IStatusBarService; 79 import com.android.internal.util.DumpUtils; 80 import com.android.server.SystemService; 81 import com.android.server.biometrics.log.BiometricContext; 82 83 import java.io.FileDescriptor; 84 import java.io.PrintWriter; 85 import java.util.ArrayList; 86 import java.util.HashMap; 87 import java.util.List; 88 import java.util.Map; 89 import java.util.Random; 90 import java.util.Set; 91 import java.util.concurrent.atomic.AtomicLong; 92 import java.util.function.Supplier; 93 94 /** 95 * System service that arbitrates the modality for BiometricPrompt to use. 96 */ 97 public class BiometricService extends SystemService { 98 99 static final String TAG = "BiometricService"; 100 101 private final Injector mInjector; 102 private final DevicePolicyManager mDevicePolicyManager; 103 @VisibleForTesting 104 final IBiometricService.Stub mImpl; 105 @VisibleForTesting 106 final SettingObserver mSettingObserver; 107 private final List<EnabledOnKeyguardCallback> mEnabledOnKeyguardCallbacks; 108 private final Random mRandom = new Random(); 109 @NonNull private final Supplier<Long> mRequestCounter; 110 @NonNull private final BiometricContext mBiometricContext; 111 private final UserManager mUserManager; 112 113 @VisibleForTesting 114 IStatusBarService mStatusBarService; 115 @VisibleForTesting 116 KeyStore mKeyStore; 117 @VisibleForTesting 118 ITrustManager mTrustManager; 119 120 // Get and cache the available biometric authenticators and their associated info. 121 final ArrayList<BiometricSensor> mSensors = new ArrayList<>(); 122 123 @VisibleForTesting 124 BiometricStrengthController mBiometricStrengthController; 125 126 // The current authentication session, null if idle/done. 127 @VisibleForTesting 128 AuthSession mAuthSession; 129 private final Handler mHandler = new Handler(Looper.getMainLooper()); 130 131 private final BiometricCameraManager mBiometricCameraManager; 132 133 /** 134 * Tracks authenticatorId invalidation. For more details, see 135 * {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}. 136 */ 137 @VisibleForTesting 138 static class InvalidationTracker { 139 @NonNull private final IInvalidationCallback mClientCallback; 140 @NonNull private final Set<Integer> mSensorsPendingInvalidation; 141 start(@onNull Context context, @NonNull ArrayList<BiometricSensor> sensors, int userId, int fromSensorId, @NonNull IInvalidationCallback clientCallback)142 public static InvalidationTracker start(@NonNull Context context, 143 @NonNull ArrayList<BiometricSensor> sensors, 144 int userId, int fromSensorId, @NonNull IInvalidationCallback clientCallback) { 145 return new InvalidationTracker(context, sensors, userId, fromSensorId, clientCallback); 146 } 147 InvalidationTracker(@onNull Context context, @NonNull ArrayList<BiometricSensor> sensors, int userId, int fromSensorId, @NonNull IInvalidationCallback clientCallback)148 private InvalidationTracker(@NonNull Context context, 149 @NonNull ArrayList<BiometricSensor> sensors, int userId, 150 int fromSensorId, @NonNull IInvalidationCallback clientCallback) { 151 mClientCallback = clientCallback; 152 mSensorsPendingInvalidation = new ArraySet<>(); 153 154 for (BiometricSensor sensor : sensors) { 155 if (sensor.id == fromSensorId) { 156 continue; 157 } 158 159 if (!Utils.isAtLeastStrength(sensor.oemStrength, Authenticators.BIOMETRIC_STRONG)) { 160 continue; 161 } 162 163 try { 164 if (!sensor.impl.hasEnrolledTemplates(userId, context.getOpPackageName())) { 165 continue; 166 } 167 } catch (RemoteException e) { 168 Slog.e(TAG, "Remote Exception", e); 169 } 170 171 Slog.d(TAG, "Requesting authenticatorId invalidation for sensor: " + sensor.id); 172 173 synchronized (this) { 174 mSensorsPendingInvalidation.add(sensor.id); 175 } 176 177 try { 178 sensor.impl.invalidateAuthenticatorId(userId, new IInvalidationCallback.Stub() { 179 @Override 180 public void onCompleted() { 181 onInvalidated(sensor.id); 182 } 183 }); 184 } catch (RemoteException e) { 185 Slog.d(TAG, "RemoteException", e); 186 } 187 } 188 189 synchronized (this) { 190 if (mSensorsPendingInvalidation.isEmpty()) { 191 try { 192 Slog.d(TAG, "No sensors require invalidation"); 193 mClientCallback.onCompleted(); 194 } catch (RemoteException e) { 195 Slog.e(TAG, "Remote Exception", e); 196 } 197 } 198 } 199 } 200 201 @VisibleForTesting onInvalidated(int sensorId)202 void onInvalidated(int sensorId) { 203 synchronized (this) { 204 mSensorsPendingInvalidation.remove(sensorId); 205 206 Slog.d(TAG, "Sensor " + sensorId + " invalidated, remaining size: " 207 + mSensorsPendingInvalidation.size()); 208 209 if (mSensorsPendingInvalidation.isEmpty()) { 210 try { 211 mClientCallback.onCompleted(); 212 } catch (RemoteException e) { 213 Slog.e(TAG, "Remote Exception", e); 214 } 215 } 216 } 217 } 218 } 219 220 @VisibleForTesting 221 public static class SettingObserver extends ContentObserver { 222 223 private static final boolean DEFAULT_KEYGUARD_ENABLED = true; 224 private static final boolean DEFAULT_APP_ENABLED = true; 225 private static final boolean DEFAULT_ALWAYS_REQUIRE_CONFIRMATION = false; 226 227 // Some devices that shipped before S already have face-specific settings. Instead of 228 // migrating, which is complicated, let's just keep using the existing settings. 229 private final boolean mUseLegacyFaceOnlySettings; 230 231 // Only used for legacy face-only devices 232 private final Uri FACE_UNLOCK_KEYGUARD_ENABLED = 233 Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED); 234 private final Uri FACE_UNLOCK_APP_ENABLED = 235 Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_APP_ENABLED); 236 237 // Continues to be used, even though it's face-specific. 238 private final Uri FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION = 239 Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION); 240 241 // Used for all devices other than legacy face-only devices 242 private final Uri BIOMETRIC_KEYGUARD_ENABLED = 243 Settings.Secure.getUriFor(Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED); 244 private final Uri BIOMETRIC_APP_ENABLED = 245 Settings.Secure.getUriFor(Settings.Secure.BIOMETRIC_APP_ENABLED); 246 247 private final ContentResolver mContentResolver; 248 private final List<BiometricService.EnabledOnKeyguardCallback> mCallbacks; 249 250 private final Map<Integer, Boolean> mBiometricEnabledOnKeyguard = new HashMap<>(); 251 private final Map<Integer, Boolean> mBiometricEnabledForApps = new HashMap<>(); 252 private final Map<Integer, Boolean> mFaceAlwaysRequireConfirmation = new HashMap<>(); 253 254 /** 255 * Creates a content observer. 256 * 257 * @param handler The handler to run {@link #onChange} on, or null if none. 258 */ SettingObserver(Context context, Handler handler, List<BiometricService.EnabledOnKeyguardCallback> callbacks)259 public SettingObserver(Context context, Handler handler, 260 List<BiometricService.EnabledOnKeyguardCallback> callbacks) { 261 super(handler); 262 mContentResolver = context.getContentResolver(); 263 mCallbacks = callbacks; 264 265 final boolean hasFingerprint = context.getPackageManager() 266 .hasSystemFeature(PackageManager.FEATURE_FINGERPRINT); 267 final boolean hasFace = context.getPackageManager() 268 .hasSystemFeature(PackageManager.FEATURE_FACE); 269 270 // Use the legacy setting on face-only devices that shipped on or before Q 271 mUseLegacyFaceOnlySettings = 272 Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.Q 273 && hasFace && !hasFingerprint; 274 275 updateContentObserver(); 276 } 277 updateContentObserver()278 public void updateContentObserver() { 279 mContentResolver.unregisterContentObserver(this); 280 281 if (mUseLegacyFaceOnlySettings) { 282 mContentResolver.registerContentObserver(FACE_UNLOCK_KEYGUARD_ENABLED, 283 false /* notifyForDescendants */, 284 this /* observer */, 285 UserHandle.USER_ALL); 286 mContentResolver.registerContentObserver(FACE_UNLOCK_APP_ENABLED, 287 false /* notifyForDescendants */, 288 this /* observer */, 289 UserHandle.USER_ALL); 290 } else { 291 mContentResolver.registerContentObserver(BIOMETRIC_KEYGUARD_ENABLED, 292 false /* notifyForDescendants */, 293 this /* observer */, 294 UserHandle.USER_ALL); 295 mContentResolver.registerContentObserver(BIOMETRIC_APP_ENABLED, 296 false /* notifyForDescendants */, 297 this /* observer */, 298 UserHandle.USER_ALL); 299 } 300 mContentResolver.registerContentObserver(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, 301 false /* notifyForDescendants */, 302 this /* observer */, 303 UserHandle.USER_ALL); 304 } 305 306 @Override onChange(boolean selfChange, Uri uri, int userId)307 public void onChange(boolean selfChange, Uri uri, int userId) { 308 if (FACE_UNLOCK_KEYGUARD_ENABLED.equals(uri)) { 309 mBiometricEnabledOnKeyguard.put(userId, Settings.Secure.getIntForUser( 310 mContentResolver, 311 Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED, 312 DEFAULT_KEYGUARD_ENABLED ? 1 : 0 /* default */, 313 userId) != 0); 314 315 if (userId == ActivityManager.getCurrentUser() && !selfChange) { 316 notifyEnabledOnKeyguardCallbacks(userId); 317 } 318 } else if (FACE_UNLOCK_APP_ENABLED.equals(uri)) { 319 mBiometricEnabledForApps.put(userId, Settings.Secure.getIntForUser( 320 mContentResolver, 321 Settings.Secure.FACE_UNLOCK_APP_ENABLED, 322 DEFAULT_APP_ENABLED ? 1 : 0 /* default */, 323 userId) != 0); 324 } else if (FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION.equals(uri)) { 325 mFaceAlwaysRequireConfirmation.put(userId, Settings.Secure.getIntForUser( 326 mContentResolver, 327 Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, 328 DEFAULT_ALWAYS_REQUIRE_CONFIRMATION ? 1 : 0 /* default */, 329 userId) != 0); 330 } else if (BIOMETRIC_KEYGUARD_ENABLED.equals(uri)) { 331 mBiometricEnabledOnKeyguard.put(userId, Settings.Secure.getIntForUser( 332 mContentResolver, 333 Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED, 334 DEFAULT_KEYGUARD_ENABLED ? 1 : 0 /* default */, 335 userId) != 0); 336 337 if (userId == ActivityManager.getCurrentUser() && !selfChange) { 338 notifyEnabledOnKeyguardCallbacks(userId); 339 } 340 } else if (BIOMETRIC_APP_ENABLED.equals(uri)) { 341 mBiometricEnabledForApps.put(userId, Settings.Secure.getIntForUser( 342 mContentResolver, 343 Settings.Secure.BIOMETRIC_APP_ENABLED, 344 DEFAULT_APP_ENABLED ? 1 : 0 /* default */, 345 userId) != 0); 346 } 347 } 348 getEnabledOnKeyguard(int userId)349 public boolean getEnabledOnKeyguard(int userId) { 350 if (!mBiometricEnabledOnKeyguard.containsKey(userId)) { 351 if (mUseLegacyFaceOnlySettings) { 352 onChange(true /* selfChange */, FACE_UNLOCK_KEYGUARD_ENABLED, userId); 353 } else { 354 onChange(true /* selfChange */, BIOMETRIC_KEYGUARD_ENABLED, userId); 355 } 356 } 357 return mBiometricEnabledOnKeyguard.get(userId); 358 } 359 getEnabledForApps(int userId)360 public boolean getEnabledForApps(int userId) { 361 if (!mBiometricEnabledForApps.containsKey(userId)) { 362 if (mUseLegacyFaceOnlySettings) { 363 onChange(true /* selfChange */, FACE_UNLOCK_APP_ENABLED, userId); 364 } else { 365 onChange(true /* selfChange */, BIOMETRIC_APP_ENABLED, userId); 366 } 367 } 368 return mBiometricEnabledForApps.getOrDefault(userId, DEFAULT_APP_ENABLED); 369 } 370 getConfirmationAlwaysRequired(@iometricAuthenticator.Modality int modality, int userId)371 public boolean getConfirmationAlwaysRequired(@BiometricAuthenticator.Modality int modality, 372 int userId) { 373 switch (modality) { 374 case TYPE_FACE: 375 if (!mFaceAlwaysRequireConfirmation.containsKey(userId)) { 376 onChange(true /* selfChange */, 377 FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, 378 userId); 379 } 380 return mFaceAlwaysRequireConfirmation.get(userId); 381 382 default: 383 return false; 384 } 385 } 386 notifyEnabledOnKeyguardCallbacks(int userId)387 void notifyEnabledOnKeyguardCallbacks(int userId) { 388 List<EnabledOnKeyguardCallback> callbacks = mCallbacks; 389 for (int i = 0; i < callbacks.size(); i++) { 390 callbacks.get(i).notify( 391 mBiometricEnabledOnKeyguard.getOrDefault(userId, DEFAULT_KEYGUARD_ENABLED), 392 userId); 393 } 394 } 395 } 396 397 final class EnabledOnKeyguardCallback implements IBinder.DeathRecipient { 398 399 private final IBiometricEnabledOnKeyguardCallback mCallback; 400 EnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback)401 EnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback) { 402 mCallback = callback; 403 try { 404 mCallback.asBinder().linkToDeath(EnabledOnKeyguardCallback.this, 0); 405 } catch (RemoteException e) { 406 Slog.w(TAG, "Unable to linkToDeath", e); 407 } 408 } 409 notify(boolean enabled, int userId)410 void notify(boolean enabled, int userId) { 411 try { 412 mCallback.onChanged(enabled, userId); 413 } catch (DeadObjectException e) { 414 Slog.w(TAG, "Death while invoking notify", e); 415 mEnabledOnKeyguardCallbacks.remove(this); 416 } catch (RemoteException e) { 417 Slog.w(TAG, "Failed to invoke onChanged", e); 418 } 419 } 420 421 @Override binderDied()422 public void binderDied() { 423 Slog.e(TAG, "Enabled callback binder died"); 424 mEnabledOnKeyguardCallbacks.remove(this); 425 } 426 } 427 428 // Receives events from individual biometric sensors. createBiometricSensorReceiver(final long requestId)429 private IBiometricSensorReceiver createBiometricSensorReceiver(final long requestId) { 430 return new IBiometricSensorReceiver.Stub() { 431 @Override 432 public void onAuthenticationSucceeded(int sensorId, byte[] token) { 433 mHandler.post(() -> handleAuthenticationSucceeded(requestId, sensorId, token)); 434 } 435 436 @Override 437 public void onAuthenticationFailed(int sensorId) { 438 Slog.v(TAG, "onAuthenticationFailed"); 439 mHandler.post(() -> handleAuthenticationRejected(requestId, sensorId)); 440 } 441 442 @Override 443 public void onError(int sensorId, int cookie, @BiometricConstants.Errors int error, 444 int vendorCode) { 445 // Determine if error is hard or soft error. Certain errors (such as TIMEOUT) are 446 // soft errors and we should allow the user to try authenticating again instead of 447 // dismissing BiometricPrompt. 448 if (error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT) { 449 mHandler.post(() -> handleAuthenticationTimedOut( 450 requestId, sensorId, cookie, error, vendorCode)); 451 } else { 452 mHandler.post(() -> handleOnError( 453 requestId, sensorId, cookie, error, vendorCode)); 454 } 455 } 456 457 @Override 458 public void onAcquired(int sensorId, int acquiredInfo, int vendorCode) { 459 mHandler.post(() -> handleOnAcquired( 460 requestId, sensorId, acquiredInfo, vendorCode)); 461 } 462 }; 463 } 464 465 private IBiometricSysuiReceiver createSysuiReceiver(final long requestId) { 466 return new IBiometricSysuiReceiver.Stub() { 467 @Override 468 public void onDialogDismissed(@BiometricPrompt.DismissedReason int reason, 469 @Nullable byte[] credentialAttestation) { 470 mHandler.post(() -> handleOnDismissed(requestId, reason, credentialAttestation)); 471 } 472 473 @Override 474 public void onTryAgainPressed() { 475 mHandler.post(() -> handleOnTryAgainPressed(requestId)); 476 } 477 478 @Override 479 public void onDeviceCredentialPressed() { 480 mHandler.post(() -> handleOnDeviceCredentialPressed(requestId)); 481 } 482 483 @Override 484 public void onSystemEvent(int event) { 485 mHandler.post(() -> handleOnSystemEvent(requestId, event)); 486 } 487 488 @Override 489 public void onDialogAnimatedIn(boolean startFingerprintNow) { 490 mHandler.post(() -> handleOnDialogAnimatedIn(requestId, startFingerprintNow)); 491 } 492 493 @Override 494 public void onStartFingerprintNow() { 495 mHandler.post(() -> handleOnStartFingerprintNow(requestId)); 496 } 497 }; 498 } 499 500 private AuthSession.ClientDeathReceiver createClientDeathReceiver(final long requestId) { 501 return () -> mHandler.post(() -> handleClientDied(requestId)); 502 }; 503 504 /** 505 * Implementation of the BiometricPrompt/BiometricManager APIs. Handles client requests, 506 * sensor arbitration, threading, etc. 507 */ 508 private final class BiometricServiceWrapper extends IBiometricService.Stub { 509 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 510 @Override // Binder call 511 public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback, 512 @NonNull String opPackageName) throws RemoteException { 513 514 super.createTestSession_enforcePermission(); 515 516 for (BiometricSensor sensor : mSensors) { 517 if (sensor.id == sensorId) { 518 return sensor.impl.createTestSession(callback, opPackageName); 519 } 520 } 521 522 Slog.e(TAG, "Unknown sensor for createTestSession: " + sensorId); 523 return null; 524 } 525 526 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 527 @Override // Binder call 528 public List<SensorPropertiesInternal> getSensorProperties(String opPackageName) 529 throws RemoteException { 530 531 super.getSensorProperties_enforcePermission(); 532 533 final List<SensorPropertiesInternal> sensors = new ArrayList<>(); 534 for (BiometricSensor sensor : mSensors) { 535 // Explicitly re-create as the super class, since AIDL doesn't play nicely with 536 // "List<? extends SensorPropertiesInternal> ... 537 final SensorPropertiesInternal prop = SensorPropertiesInternal 538 .from(sensor.impl.getSensorProperties(opPackageName)); 539 sensors.add(prop); 540 } 541 542 return sensors; 543 } 544 545 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 546 @Override // Binder call 547 public void onReadyForAuthentication(long requestId, int cookie) { 548 549 super.onReadyForAuthentication_enforcePermission(); 550 551 mHandler.post(() -> handleOnReadyForAuthentication(requestId, cookie)); 552 } 553 554 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 555 @Override // Binder call 556 public long authenticate(IBinder token, long operationId, int userId, 557 IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo) { 558 559 super.authenticate_enforcePermission(); 560 561 if (token == null || receiver == null || opPackageName == null || promptInfo == null) { 562 Slog.e(TAG, "Unable to authenticate, one or more null arguments"); 563 return -1; 564 } 565 566 if (!Utils.isValidAuthenticatorConfig(promptInfo)) { 567 throw new SecurityException("Invalid authenticator configuration"); 568 } 569 570 Utils.combineAuthenticatorBundles(promptInfo); 571 572 final long requestId = mRequestCounter.get(); 573 mHandler.post(() -> handleAuthenticate( 574 token, requestId, operationId, userId, receiver, opPackageName, promptInfo)); 575 576 return requestId; 577 } 578 579 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 580 @Override // Binder call 581 public void cancelAuthentication(IBinder token, String opPackageName, long requestId) { 582 583 super.cancelAuthentication_enforcePermission(); 584 585 SomeArgs args = SomeArgs.obtain(); 586 args.arg1 = token; 587 args.arg2 = opPackageName; 588 args.arg3 = requestId; 589 590 mHandler.post(() -> handleCancelAuthentication(requestId)); 591 } 592 593 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 594 @Override // Binder call 595 public int canAuthenticate(String opPackageName, int userId, int callingUserId, 596 @Authenticators.Types int authenticators) { 597 598 super.canAuthenticate_enforcePermission(); 599 600 Slog.d(TAG, "canAuthenticate: User=" + userId 601 + ", Caller=" + callingUserId 602 + ", Authenticators=" + authenticators); 603 604 if (!Utils.isValidAuthenticatorConfig(authenticators)) { 605 throw new SecurityException("Invalid authenticator configuration"); 606 } 607 608 try { 609 final PreAuthInfo preAuthInfo = 610 createPreAuthInfo(opPackageName, userId, authenticators); 611 return preAuthInfo.getCanAuthenticateResult(); 612 } catch (RemoteException e) { 613 Slog.e(TAG, "Remote exception", e); 614 return BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE; 615 } 616 } 617 618 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 619 @Override 620 public boolean hasEnrolledBiometrics(int userId, String opPackageName) { 621 622 super.hasEnrolledBiometrics_enforcePermission(); 623 624 try { 625 for (BiometricSensor sensor : mSensors) { 626 if (sensor.impl.hasEnrolledTemplates(userId, opPackageName)) { 627 return true; 628 } 629 } 630 } catch (RemoteException e) { 631 Slog.e(TAG, "Remote exception", e); 632 } 633 634 return false; 635 } 636 637 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 638 @Override 639 public synchronized void registerAuthenticator(int id, int modality, 640 @Authenticators.Types int strength, 641 @NonNull IBiometricAuthenticator authenticator) { 642 643 super.registerAuthenticator_enforcePermission(); 644 645 Slog.d(TAG, "Registering ID: " + id 646 + " Modality: " + modality 647 + " Strength: " + strength); 648 649 if (authenticator == null) { 650 throw new IllegalArgumentException("Authenticator must not be null." 651 + " Did you forget to modify the core/res/res/values/xml overlay for" 652 + " config_biometric_sensors?"); 653 } 654 655 // Note that we allow BIOMETRIC_CONVENIENCE to register because BiometricService 656 // also does / will do other things such as keep track of lock screen timeout, etc. 657 // Just because a biometric is registered does not mean it can participate in 658 // the android.hardware.biometrics APIs. 659 if (strength != Authenticators.BIOMETRIC_STRONG 660 && strength != Authenticators.BIOMETRIC_WEAK 661 && strength != Authenticators.BIOMETRIC_CONVENIENCE) { 662 throw new IllegalStateException("Unsupported strength"); 663 } 664 665 for (BiometricSensor sensor : mSensors) { 666 if (sensor.id == id) { 667 throw new IllegalStateException("Cannot register duplicate authenticator"); 668 } 669 } 670 671 mSensors.add(new BiometricSensor(getContext(), id, modality, strength, authenticator) { 672 @Override 673 boolean confirmationAlwaysRequired(int userId) { 674 return mSettingObserver.getConfirmationAlwaysRequired(modality, userId); 675 } 676 677 @Override 678 boolean confirmationSupported() { 679 return Utils.isConfirmationSupported(modality); 680 } 681 }); 682 683 mBiometricStrengthController.updateStrengths(); 684 } 685 686 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 687 @Override // Binder call 688 public void registerEnabledOnKeyguardCallback( 689 IBiometricEnabledOnKeyguardCallback callback) { 690 691 super.registerEnabledOnKeyguardCallback_enforcePermission(); 692 693 mEnabledOnKeyguardCallbacks.add(new EnabledOnKeyguardCallback(callback)); 694 final List<UserInfo> aliveUsers = mUserManager.getAliveUsers(); 695 try { 696 for (UserInfo userInfo: aliveUsers) { 697 final int userId = userInfo.id; 698 callback.onChanged(mSettingObserver.getEnabledOnKeyguard(userId), 699 userId); 700 } 701 } catch (RemoteException e) { 702 Slog.w(TAG, "Remote exception", e); 703 } 704 } 705 706 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 707 @Override // Binder call 708 public void invalidateAuthenticatorIds(int userId, int fromSensorId, 709 IInvalidationCallback callback) { 710 711 super.invalidateAuthenticatorIds_enforcePermission(); 712 713 InvalidationTracker.start(getContext(), mSensors, userId, fromSensorId, callback); 714 } 715 716 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 717 @Override // Binder call 718 public long[] getAuthenticatorIds(int callingUserId) { 719 720 super.getAuthenticatorIds_enforcePermission(); 721 722 final List<Long> authenticatorIds = new ArrayList<>(); 723 for (BiometricSensor sensor : mSensors) { 724 try { 725 final boolean hasEnrollments = sensor.impl.hasEnrolledTemplates(callingUserId, 726 getContext().getOpPackageName()); 727 final long authenticatorId = sensor.impl.getAuthenticatorId(callingUserId); 728 if (hasEnrollments && Utils.isAtLeastStrength(sensor.getCurrentStrength(), 729 Authenticators.BIOMETRIC_STRONG)) { 730 authenticatorIds.add(authenticatorId); 731 } else { 732 Slog.d(TAG, "Sensor " + sensor + ", sensorId " + sensor.id 733 + ", hasEnrollments: " + hasEnrollments 734 + " cannot participate in Keystore operations"); 735 } 736 } catch (RemoteException e) { 737 Slog.e(TAG, "RemoteException", e); 738 } 739 } 740 741 long[] result = new long[authenticatorIds.size()]; 742 for (int i = 0; i < authenticatorIds.size(); i++) { 743 result[i] = authenticatorIds.get(i); 744 } 745 return result; 746 } 747 748 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 749 @Override // Binder call 750 public void resetLockoutTimeBound(IBinder token, String opPackageName, int fromSensorId, 751 int userId, byte[] hardwareAuthToken) { 752 753 // Check originating strength 754 super.resetLockoutTimeBound_enforcePermission(); 755 756 if (!Utils.isAtLeastStrength(getSensorForId(fromSensorId).getCurrentStrength(), 757 Authenticators.BIOMETRIC_STRONG)) { 758 Slog.w(TAG, "Sensor: " + fromSensorId + " is does not meet the required strength to" 759 + " request resetLockout"); 760 return; 761 } 762 763 // Request resetLockout for applicable sensors 764 for (BiometricSensor sensor : mSensors) { 765 if (sensor.id == fromSensorId) { 766 continue; 767 } 768 try { 769 final SensorPropertiesInternal props = sensor.impl 770 .getSensorProperties(getContext().getOpPackageName()); 771 final boolean supportsChallengelessHat = 772 props.resetLockoutRequiresHardwareAuthToken 773 && !props.resetLockoutRequiresChallenge; 774 final boolean doesNotRequireHat = !props.resetLockoutRequiresHardwareAuthToken; 775 776 if (supportsChallengelessHat || doesNotRequireHat) { 777 Slog.d(TAG, "resetLockout from: " + fromSensorId 778 + ", for: " + sensor.id 779 + ", userId: " + userId); 780 sensor.impl.resetLockout(token, opPackageName, userId, 781 hardwareAuthToken); 782 } 783 } catch (RemoteException e) { 784 Slog.e(TAG, "Remote exception", e); 785 } 786 } 787 } 788 789 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 790 @Override // Binder call 791 public void resetLockout( 792 int userId, byte[] hardwareAuthToken) { 793 super.resetLockout_enforcePermission(); 794 795 Slog.d(TAG, "resetLockout(userId=" + userId 796 + ", hat=" + (hardwareAuthToken == null ? "null " : "present") + ")"); 797 mBiometricContext.getAuthSessionCoordinator() 798 .resetLockoutFor(userId, Authenticators.BIOMETRIC_STRONG, -1); 799 } 800 801 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 802 @Override // Binder call 803 public int getCurrentStrength(int sensorId) { 804 805 super.getCurrentStrength_enforcePermission(); 806 807 for (BiometricSensor sensor : mSensors) { 808 if (sensor.id == sensorId) { 809 return sensor.getCurrentStrength(); 810 } 811 } 812 Slog.e(TAG, "Unknown sensorId: " + sensorId); 813 return Authenticators.EMPTY_SET; 814 } 815 816 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 817 @Override // Binder call 818 public int getCurrentModality( 819 String opPackageName, 820 int userId, 821 int callingUserId, 822 @Authenticators.Types int authenticators) { 823 824 825 super.getCurrentModality_enforcePermission(); 826 827 Slog.d(TAG, "getCurrentModality: User=" + userId 828 + ", Caller=" + callingUserId 829 + ", Authenticators=" + authenticators); 830 831 if (!Utils.isValidAuthenticatorConfig(authenticators)) { 832 throw new SecurityException("Invalid authenticator configuration"); 833 } 834 835 try { 836 final PreAuthInfo preAuthInfo = 837 createPreAuthInfo(opPackageName, userId, authenticators); 838 return preAuthInfo.getPreAuthenticateStatus().first; 839 } catch (RemoteException e) { 840 Slog.e(TAG, "Remote exception", e); 841 return BiometricAuthenticator.TYPE_NONE; 842 } 843 } 844 845 @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) 846 @Override // Binder call 847 public int getSupportedModalities(@Authenticators.Types int authenticators) { 848 849 super.getSupportedModalities_enforcePermission(); 850 851 Slog.d(TAG, "getSupportedModalities: Authenticators=" + authenticators); 852 853 if (!Utils.isValidAuthenticatorConfig(authenticators)) { 854 throw new SecurityException("Invalid authenticator configuration"); 855 } 856 857 @BiometricAuthenticator.Modality int modality = 858 Utils.isCredentialRequested(authenticators) 859 ? BiometricAuthenticator.TYPE_CREDENTIAL 860 : BiometricAuthenticator.TYPE_NONE; 861 862 if (Utils.isBiometricRequested(authenticators)) { 863 @Authenticators.Types final int requestedStrength = 864 Utils.getPublicBiometricStrength(authenticators); 865 866 // Add modalities of all biometric sensors that meet the authenticator requirements. 867 for (final BiometricSensor sensor : mSensors) { 868 @Authenticators.Types final int sensorStrength = sensor.getCurrentStrength(); 869 if (Utils.isAtLeastStrength(sensorStrength, requestedStrength)) { 870 modality |= sensor.modality; 871 } 872 } 873 } 874 875 return modality; 876 } 877 878 @Override 879 protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, String[] args) { 880 if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) { 881 return; 882 } 883 884 final long ident = Binder.clearCallingIdentity(); 885 try { 886 if (args.length > 0 && "--proto".equals(args[0])) { 887 final boolean clearSchedulerBuffer = args.length > 1 888 && "--clear-scheduler-buffer".equals(args[1]); 889 Slog.d(TAG, "ClearSchedulerBuffer: " + clearSchedulerBuffer); 890 final ProtoOutputStream proto = new ProtoOutputStream(fd); 891 proto.write(BiometricServiceStateProto.AUTH_SESSION_STATE, 892 mAuthSession != null ? mAuthSession.getState() : STATE_AUTH_IDLE); 893 for (BiometricSensor sensor : mSensors) { 894 byte[] serviceState = sensor.impl 895 .dumpSensorServiceStateProto(clearSchedulerBuffer); 896 proto.write(BiometricServiceStateProto.SENSOR_SERVICE_STATES, serviceState); 897 } 898 proto.flush(); 899 } else { 900 dumpInternal(pw); 901 } 902 } catch (RemoteException e) { 903 Slog.e(TAG, "Remote exception", e); 904 } finally { 905 Binder.restoreCallingIdentity(ident); 906 } 907 } 908 } 909 910 private void checkInternalPermission() { 911 getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL, 912 "Must have USE_BIOMETRIC_INTERNAL permission"); 913 } 914 915 @NonNull 916 private PreAuthInfo createPreAuthInfo( 917 @NonNull String opPackageName, 918 int userId, 919 @Authenticators.Types int authenticators) throws RemoteException { 920 921 final PromptInfo promptInfo = new PromptInfo(); 922 promptInfo.setAuthenticators(authenticators); 923 924 return PreAuthInfo.create(mTrustManager, mDevicePolicyManager, mSettingObserver, mSensors, 925 userId, promptInfo, opPackageName, false /* checkDevicePolicyManager */, 926 getContext(), mBiometricCameraManager); 927 } 928 929 /** 930 * Class for injecting dependencies into BiometricService. 931 * TODO(b/141025588): Replace with a dependency injection framework (e.g. Guice, Dagger). 932 */ 933 @VisibleForTesting 934 public static class Injector { 935 936 public IActivityManager getActivityManagerService() { 937 return ActivityManager.getService(); 938 } 939 940 public ITrustManager getTrustManager() { 941 return ITrustManager.Stub.asInterface(ServiceManager.getService(Context.TRUST_SERVICE)); 942 } 943 944 public IStatusBarService getStatusBarService() { 945 return IStatusBarService.Stub.asInterface( 946 ServiceManager.getService(Context.STATUS_BAR_SERVICE)); 947 } 948 949 /** 950 * Allows to mock SettingObserver for testing. 951 */ 952 public SettingObserver getSettingObserver(Context context, Handler handler, 953 List<EnabledOnKeyguardCallback> callbacks) { 954 return new SettingObserver(context, handler, callbacks); 955 } 956 957 public KeyStore getKeyStore() { 958 return KeyStore.getInstance(); 959 } 960 961 /** 962 * Allows to enable/disable debug logs. 963 */ 964 public boolean isDebugEnabled(Context context, int userId) { 965 return Utils.isDebugEnabled(context, userId); 966 } 967 968 /** 969 * Allows to stub publishBinderService(...) for testing. 970 */ 971 public void publishBinderService(BiometricService service, IBiometricService.Stub impl) { 972 service.publishBinderService(Context.BIOMETRIC_SERVICE, impl); 973 } 974 975 /** 976 * Allows to mock BiometricStrengthController for testing. 977 */ 978 public BiometricStrengthController getBiometricStrengthController( 979 BiometricService service) { 980 return new BiometricStrengthController(service); 981 } 982 983 /** 984 * Allows to test with various device sensor configurations. 985 * @param context System Server context 986 * @return the sensor configuration from core/res/res/values/config.xml 987 */ 988 public String[] getConfiguration(Context context) { 989 return context.getResources().getStringArray(R.array.config_biometric_sensors); 990 } 991 992 public DevicePolicyManager getDevicePolicyManager(Context context) { 993 return context.getSystemService(DevicePolicyManager.class); 994 } 995 996 public List<FingerprintSensorPropertiesInternal> getFingerprintSensorProperties( 997 Context context) { 998 if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 999 final FingerprintManager fpm = context.getSystemService(FingerprintManager.class); 1000 if (fpm != null) { 1001 return fpm.getSensorPropertiesInternal(); 1002 } 1003 } 1004 return new ArrayList<>(); 1005 } 1006 1007 public Supplier<Long> getRequestGenerator() { 1008 final AtomicLong generator = new AtomicLong(0); 1009 return () -> generator.incrementAndGet(); 1010 } 1011 1012 public BiometricContext getBiometricContext(Context context) { 1013 return BiometricContext.getInstance(context); 1014 } 1015 1016 public UserManager getUserManager(Context context) { 1017 return context.getSystemService(UserManager.class); 1018 } 1019 1020 public BiometricCameraManager getBiometricCameraManager(Context context) { 1021 return new BiometricCameraManagerImpl(context.getSystemService(CameraManager.class), 1022 context.getSystemService(SensorPrivacyManager.class)); 1023 } 1024 } 1025 1026 /** 1027 * Initializes the system service. 1028 * <p> 1029 * Subclasses must define a single argument constructor that accepts the context 1030 * and passes it to super. 1031 * </p> 1032 * 1033 * @param context The system server context. 1034 */ 1035 public BiometricService(Context context) { 1036 this(context, new Injector()); 1037 } 1038 1039 @VisibleForTesting 1040 BiometricService(Context context, Injector injector) { 1041 super(context); 1042 1043 mInjector = injector; 1044 mDevicePolicyManager = mInjector.getDevicePolicyManager(context); 1045 mImpl = new BiometricServiceWrapper(); 1046 mEnabledOnKeyguardCallbacks = new ArrayList<>(); 1047 mSettingObserver = mInjector.getSettingObserver(context, mHandler, 1048 mEnabledOnKeyguardCallbacks); 1049 mRequestCounter = mInjector.getRequestGenerator(); 1050 mBiometricContext = injector.getBiometricContext(context); 1051 mUserManager = injector.getUserManager(context); 1052 mBiometricCameraManager = injector.getBiometricCameraManager(context); 1053 1054 try { 1055 injector.getActivityManagerService().registerUserSwitchObserver( 1056 new UserSwitchObserver() { 1057 @Override 1058 public void onUserSwitchComplete(int newUserId) { 1059 mSettingObserver.updateContentObserver(); 1060 mSettingObserver.notifyEnabledOnKeyguardCallbacks(newUserId); 1061 } 1062 }, BiometricService.class.getName() 1063 ); 1064 } catch (RemoteException e) { 1065 Slog.e(TAG, "Failed to register user switch observer", e); 1066 } 1067 } 1068 1069 @Override 1070 public void onStart() { 1071 mKeyStore = mInjector.getKeyStore(); 1072 mStatusBarService = mInjector.getStatusBarService(); 1073 mTrustManager = mInjector.getTrustManager(); 1074 mInjector.publishBinderService(this, mImpl); 1075 mBiometricStrengthController = mInjector.getBiometricStrengthController(this); 1076 mBiometricStrengthController.startListening(); 1077 } 1078 1079 private boolean isStrongBiometric(int id) { 1080 for (BiometricSensor sensor : mSensors) { 1081 if (sensor.id == id) { 1082 return Utils.isAtLeastStrength(sensor.getCurrentStrength(), 1083 Authenticators.BIOMETRIC_STRONG); 1084 } 1085 } 1086 Slog.e(TAG, "Unknown sensorId: " + id); 1087 return false; 1088 } 1089 1090 @Nullable 1091 private AuthSession getAuthSessionIfCurrent(long requestId) { 1092 final AuthSession session = mAuthSession; 1093 if (session != null && session.getRequestId() == requestId) { 1094 return session; 1095 } 1096 return null; 1097 } 1098 1099 private void handleAuthenticationSucceeded(long requestId, int sensorId, byte[] token) { 1100 Slog.v(TAG, "handleAuthenticationSucceeded(), sensorId: " + sensorId); 1101 // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded 1102 // after user dismissed/canceled dialog). 1103 final AuthSession session = getAuthSessionIfCurrent(requestId); 1104 if (session == null) { 1105 Slog.e(TAG, "handleAuthenticationSucceeded: AuthSession is null"); 1106 return; 1107 } 1108 1109 session.onAuthenticationSucceeded(sensorId, isStrongBiometric(sensorId), token); 1110 } 1111 1112 private void handleAuthenticationRejected(long requestId, int sensorId) { 1113 Slog.v(TAG, "handleAuthenticationRejected()"); 1114 1115 // Should never happen, log this to catch bad HAL behavior (e.g. auth rejected 1116 // after user dismissed/canceled dialog). 1117 final AuthSession session = getAuthSessionIfCurrent(requestId); 1118 if (session == null) { 1119 Slog.w(TAG, "handleAuthenticationRejected: AuthSession is not current"); 1120 return; 1121 } 1122 1123 session.onAuthenticationRejected(sensorId); 1124 } 1125 1126 private void handleAuthenticationTimedOut(long requestId, int sensorId, int cookie, int error, 1127 int vendorCode) { 1128 Slog.v(TAG, "handleAuthenticationTimedOut(), sensorId: " + sensorId 1129 + ", cookie: " + cookie 1130 + ", error: " + error 1131 + ", vendorCode: " + vendorCode); 1132 // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded 1133 // after user dismissed/canceled dialog). 1134 final AuthSession session = getAuthSessionIfCurrent(requestId); 1135 if (session == null) { 1136 Slog.w(TAG, "handleAuthenticationTimedOut: AuthSession is not current"); 1137 return; 1138 } 1139 1140 session.onAuthenticationTimedOut(sensorId, cookie, error, vendorCode); 1141 } 1142 1143 private void handleOnError(long requestId, int sensorId, int cookie, 1144 @BiometricConstants.Errors int error, int vendorCode) { 1145 Slog.d(TAG, "handleOnError() sensorId: " + sensorId 1146 + ", cookie: " + cookie 1147 + ", error: " + error 1148 + ", vendorCode: " + vendorCode); 1149 1150 final AuthSession session = getAuthSessionIfCurrent(requestId); 1151 if (session == null) { 1152 Slog.w(TAG, "handleOnError: AuthSession is not current"); 1153 return; 1154 } 1155 1156 try { 1157 final boolean finished = session.onErrorReceived(sensorId, cookie, error, vendorCode); 1158 if (finished) { 1159 Slog.d(TAG, "handleOnError: AuthSession finished"); 1160 mAuthSession = null; 1161 } 1162 } catch (RemoteException e) { 1163 Slog.e(TAG, "RemoteException", e); 1164 } 1165 } 1166 1167 private void handleOnAcquired(long requestId, int sensorId, int acquiredInfo, int vendorCode) { 1168 // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded 1169 // after user dismissed/canceled dialog). 1170 final AuthSession session = getAuthSessionIfCurrent(requestId); 1171 if (session == null) { 1172 Slog.w(TAG, "onAcquired: AuthSession is not current"); 1173 return; 1174 } 1175 1176 session.onAcquired(sensorId, acquiredInfo, vendorCode); 1177 } 1178 1179 private void handleOnDismissed(long requestId, @BiometricPrompt.DismissedReason int reason, 1180 @Nullable byte[] credentialAttestation) { 1181 final AuthSession session = getAuthSessionIfCurrent(requestId); 1182 if (session == null) { 1183 Slog.e(TAG, "onDismissed: " + reason + ", AuthSession is not current"); 1184 return; 1185 } 1186 1187 session.onDialogDismissed(reason, credentialAttestation); 1188 mAuthSession = null; 1189 } 1190 1191 private void handleOnTryAgainPressed(long requestId) { 1192 Slog.d(TAG, "onTryAgainPressed"); 1193 // No need to check permission, since it can only be invoked by SystemUI 1194 // (or system server itself). 1195 final AuthSession session = getAuthSessionIfCurrent(requestId); 1196 if (session == null) { 1197 Slog.w(TAG, "handleOnTryAgainPressed: AuthSession is not current"); 1198 return; 1199 } 1200 1201 session.onTryAgainPressed(); 1202 } 1203 1204 private void handleOnDeviceCredentialPressed(long requestId) { 1205 Slog.d(TAG, "onDeviceCredentialPressed"); 1206 final AuthSession session = getAuthSessionIfCurrent(requestId); 1207 if (session == null) { 1208 Slog.w(TAG, "handleOnDeviceCredentialPressed: AuthSession is not current"); 1209 return; 1210 } 1211 1212 session.onDeviceCredentialPressed(); 1213 } 1214 1215 private void handleOnSystemEvent(long requestId, int event) { 1216 Slog.d(TAG, "onSystemEvent: " + event); 1217 1218 final AuthSession session = getAuthSessionIfCurrent(requestId); 1219 if (session == null) { 1220 Slog.w(TAG, "handleOnSystemEvent: AuthSession is not current"); 1221 return; 1222 } 1223 1224 session.onSystemEvent(event); 1225 } 1226 1227 private void handleClientDied(long requestId) { 1228 final AuthSession session = getAuthSessionIfCurrent(requestId); 1229 if (session == null) { 1230 Slog.w(TAG, "handleClientDied: AuthSession is not current"); 1231 return; 1232 } 1233 1234 Slog.e(TAG, "Session: " + session); 1235 final boolean finished = session.onClientDied(); 1236 if (finished) { 1237 mAuthSession = null; 1238 } 1239 } 1240 1241 private void handleOnDialogAnimatedIn(long requestId, boolean startFingerprintNow) { 1242 Slog.d(TAG, "handleOnDialogAnimatedIn"); 1243 1244 final AuthSession session = getAuthSessionIfCurrent(requestId); 1245 if (session == null) { 1246 Slog.w(TAG, "handleOnDialogAnimatedIn: AuthSession is not current"); 1247 return; 1248 } 1249 1250 session.onDialogAnimatedIn(startFingerprintNow); 1251 } 1252 1253 private void handleOnStartFingerprintNow(long requestId) { 1254 Slog.d(TAG, "handleOnStartFingerprintNow"); 1255 1256 final AuthSession session = getAuthSessionIfCurrent(requestId); 1257 if (session == null) { 1258 Slog.w(TAG, "handleOnStartFingerprintNow: AuthSession is not current"); 1259 return; 1260 } 1261 1262 session.onStartFingerprint(); 1263 } 1264 1265 /** 1266 * Invoked when each service has notified that its client is ready to be started. When 1267 * all biometrics are ready, this invokes the SystemUI dialog through StatusBar. 1268 */ 1269 private void handleOnReadyForAuthentication(long requestId, int cookie) { 1270 final AuthSession session = getAuthSessionIfCurrent(requestId); 1271 if (session == null) { 1272 // Only should happen if a biometric was locked out when authenticate() was invoked. 1273 // In that case, if device credentials are allowed, the UI is already showing. If not 1274 // allowed, the error has already been returned to the caller. 1275 Slog.w(TAG, "handleOnReadyForAuthentication: AuthSession is not current"); 1276 return; 1277 } 1278 1279 session.onCookieReceived(cookie); 1280 } 1281 1282 private void handleAuthenticate(IBinder token, long requestId, long operationId, int userId, 1283 IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo) { 1284 mHandler.post(() -> { 1285 try { 1286 final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, 1287 mDevicePolicyManager, mSettingObserver, mSensors, userId, promptInfo, 1288 opPackageName, promptInfo.isDisallowBiometricsIfPolicyExists(), 1289 getContext(), mBiometricCameraManager); 1290 1291 // Set the default title if necessary. 1292 if (promptInfo.isUseDefaultTitle()) { 1293 if (TextUtils.isEmpty(promptInfo.getTitle())) { 1294 promptInfo.setTitle(getContext() 1295 .getString(R.string.biometric_dialog_default_title)); 1296 } 1297 } 1298 1299 final int eligible = preAuthInfo.getEligibleModalities(); 1300 final boolean hasEligibleFingerprintSensor = 1301 (eligible & TYPE_FINGERPRINT) == TYPE_FINGERPRINT; 1302 final boolean hasEligibleFaceSensor = (eligible & TYPE_FACE) == TYPE_FACE; 1303 1304 // Set the subtitle according to the modality. 1305 if (promptInfo.isUseDefaultSubtitle()) { 1306 if (hasEligibleFingerprintSensor && hasEligibleFaceSensor) { 1307 promptInfo.setSubtitle(getContext() 1308 .getString(R.string.biometric_dialog_default_subtitle)); 1309 } else if (hasEligibleFingerprintSensor) { 1310 promptInfo.setSubtitle(getContext() 1311 .getString(R.string.fingerprint_dialog_default_subtitle)); 1312 } else if (hasEligibleFaceSensor) { 1313 promptInfo.setSubtitle(getContext() 1314 .getString(R.string.face_dialog_default_subtitle)); 1315 } else { 1316 promptInfo.setSubtitle(getContext() 1317 .getString(R.string.screen_lock_dialog_default_subtitle)); 1318 } 1319 } 1320 1321 final Pair<Integer, Integer> preAuthStatus = preAuthInfo.getPreAuthenticateStatus(); 1322 1323 Slog.d(TAG, "handleAuthenticate: modality(" + preAuthStatus.first 1324 + "), status(" + preAuthStatus.second + "), preAuthInfo: " + preAuthInfo 1325 + " requestId: " + requestId + " promptInfo.isIgnoreEnrollmentState: " 1326 + promptInfo.isIgnoreEnrollmentState()); 1327 // BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED is added so that BiometricPrompt can 1328 // be shown for this case. 1329 if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS) { 1330 // If BIOMETRIC_WEAK or BIOMETRIC_STRONG are allowed, but not enrolled, but 1331 // CREDENTIAL is requested and available, set the bundle to only request 1332 // CREDENTIAL. 1333 // TODO: We should clean this up, as well as the interface with SystemUI 1334 if (preAuthInfo.credentialRequested && preAuthInfo.credentialAvailable 1335 && preAuthInfo.eligibleSensors.isEmpty()) { 1336 promptInfo.setAuthenticators(Authenticators.DEVICE_CREDENTIAL); 1337 } 1338 1339 authenticateInternal(token, requestId, operationId, userId, receiver, 1340 opPackageName, promptInfo, preAuthInfo); 1341 } else { 1342 receiver.onError(preAuthStatus.first /* modality */, 1343 preAuthStatus.second /* errorCode */, 1344 0 /* vendorCode */); 1345 } 1346 } catch (RemoteException e) { 1347 Slog.e(TAG, "Remote exception", e); 1348 } 1349 }); 1350 } 1351 1352 /** 1353 * handleAuthenticate() (above) which is called from BiometricPrompt determines which 1354 * modality/modalities to start authenticating with. authenticateInternal() should only be 1355 * used for preparing <Biometric>Services for authentication when BiometricPrompt#authenticate 1356 * is invoked, shortly after which BiometricPrompt is shown and authentication starts. 1357 * 1358 * Note that this path is NOT invoked when the BiometricPrompt "Try again" button is pressed. 1359 * In that case, see {@link #handleOnTryAgainPressed()}. 1360 */ 1361 private void authenticateInternal(IBinder token, long requestId, long operationId, int userId, 1362 IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo, 1363 PreAuthInfo preAuthInfo) { 1364 Slog.d(TAG, "Creating authSession with authRequest: " + preAuthInfo); 1365 1366 // No need to dismiss dialog / send error yet if we're continuing authentication, e.g. 1367 // "Try again" is showing due to something like ERROR_TIMEOUT. 1368 if (mAuthSession != null) { 1369 // Forcefully cancel authentication. Dismiss the UI, and immediately send 1370 // ERROR_CANCELED to the client. Note that we should/will ignore HAL ERROR_CANCELED. 1371 // Expect to see some harmless "unknown cookie" errors. 1372 Slog.w(TAG, "Existing AuthSession: " + mAuthSession); 1373 mAuthSession.onCancelAuthSession(true /* force */); 1374 mAuthSession = null; 1375 } 1376 1377 final boolean debugEnabled = mInjector.isDebugEnabled(getContext(), userId); 1378 mAuthSession = new AuthSession(getContext(), mBiometricContext, mStatusBarService, 1379 createSysuiReceiver(requestId), mKeyStore, mRandom, 1380 createClientDeathReceiver(requestId), preAuthInfo, token, requestId, 1381 operationId, userId, createBiometricSensorReceiver(requestId), receiver, 1382 opPackageName, promptInfo, debugEnabled, 1383 mInjector.getFingerprintSensorProperties(getContext())); 1384 try { 1385 mAuthSession.goToInitialState(); 1386 } catch (RemoteException e) { 1387 Slog.e(TAG, "RemoteException", e); 1388 } 1389 } 1390 1391 private void handleCancelAuthentication(long requestId) { 1392 final AuthSession session = getAuthSessionIfCurrent(requestId); 1393 if (session == null) { 1394 Slog.w(TAG, "handleCancelAuthentication: AuthSession is not current"); 1395 // TODO: actually cancel the operation? 1396 return; 1397 } 1398 1399 final boolean finished = session.onCancelAuthSession(false /* force */); 1400 if (finished) { 1401 Slog.d(TAG, "handleCancelAuthentication: AuthSession finished"); 1402 mAuthSession = null; 1403 } 1404 } 1405 1406 @Nullable 1407 private BiometricSensor getSensorForId(int sensorId) { 1408 for (BiometricSensor sensor : mSensors) { 1409 if (sensor.id == sensorId) { 1410 return sensor; 1411 } 1412 } 1413 return null; 1414 } 1415 1416 private void dumpInternal(PrintWriter pw) { 1417 pw.println("Legacy Settings: " + mSettingObserver.mUseLegacyFaceOnlySettings); 1418 pw.println(); 1419 1420 pw.println("Sensors:"); 1421 for (BiometricSensor sensor : mSensors) { 1422 pw.println(" " + sensor); 1423 } 1424 pw.println(); 1425 pw.println("CurrentSession: " + mAuthSession); 1426 pw.println(); 1427 } 1428 } 1429