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