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