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