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; 20 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; 21 import static android.Manifest.permission.USE_FINGERPRINT; 22 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; 23 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; 24 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS; 25 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE; 26 27 import android.app.ActivityManager; 28 import android.app.ActivityTaskManager; 29 import android.app.AppOpsManager; 30 import android.app.IActivityTaskManager; 31 import android.app.KeyguardManager; 32 import android.app.TaskStackListener; 33 import android.app.UserSwitchObserver; 34 import android.content.ContentResolver; 35 import android.content.Context; 36 import android.content.Intent; 37 import android.content.pm.PackageManager; 38 import android.database.ContentObserver; 39 import android.hardware.biometrics.BiometricAuthenticator; 40 import android.hardware.biometrics.BiometricConstants; 41 import android.hardware.biometrics.BiometricPrompt; 42 import android.hardware.biometrics.BiometricSourceType; 43 import android.hardware.biometrics.BiometricsProtoEnums; 44 import android.hardware.biometrics.IBiometricConfirmDeviceCredentialCallback; 45 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; 46 import android.hardware.biometrics.IBiometricService; 47 import android.hardware.biometrics.IBiometricServiceReceiver; 48 import android.hardware.biometrics.IBiometricServiceReceiverInternal; 49 import android.hardware.face.FaceManager; 50 import android.hardware.face.IFaceService; 51 import android.hardware.fingerprint.FingerprintManager; 52 import android.hardware.fingerprint.IFingerprintService; 53 import android.net.Uri; 54 import android.os.Binder; 55 import android.os.Bundle; 56 import android.os.DeadObjectException; 57 import android.os.Handler; 58 import android.os.IBinder; 59 import android.os.Looper; 60 import android.os.Message; 61 import android.os.RemoteException; 62 import android.os.ServiceManager; 63 import android.os.UserHandle; 64 import android.provider.Settings; 65 import android.security.KeyStore; 66 import android.text.TextUtils; 67 import android.util.Pair; 68 import android.util.Slog; 69 import android.util.StatsLog; 70 71 import com.android.internal.R; 72 import com.android.internal.os.SomeArgs; 73 import com.android.internal.statusbar.IStatusBarService; 74 import com.android.server.SystemService; 75 76 import java.util.ArrayList; 77 import java.util.HashMap; 78 import java.util.Iterator; 79 import java.util.List; 80 import java.util.Map; 81 import java.util.Random; 82 83 /** 84 * System service that arbitrates the modality for BiometricPrompt to use. 85 */ 86 public class BiometricService extends SystemService { 87 88 private static final String TAG = "BiometricService"; 89 private static final boolean DEBUG = true; 90 91 private static final int MSG_ON_TASK_STACK_CHANGED = 1; 92 private static final int MSG_ON_AUTHENTICATION_SUCCEEDED = 2; 93 private static final int MSG_ON_AUTHENTICATION_FAILED = 3; 94 private static final int MSG_ON_ERROR = 4; 95 private static final int MSG_ON_ACQUIRED = 5; 96 private static final int MSG_ON_DISMISSED = 6; 97 private static final int MSG_ON_TRY_AGAIN_PRESSED = 7; 98 private static final int MSG_ON_READY_FOR_AUTHENTICATION = 8; 99 private static final int MSG_AUTHENTICATE = 9; 100 private static final int MSG_CANCEL_AUTHENTICATION = 10; 101 private static final int MSG_ON_CONFIRM_DEVICE_CREDENTIAL_SUCCESS = 11; 102 private static final int MSG_ON_CONFIRM_DEVICE_CREDENTIAL_ERROR = 12; 103 private static final int MSG_REGISTER_CANCELLATION_CALLBACK = 13; 104 105 private static final int[] FEATURE_ID = { 106 TYPE_FINGERPRINT, 107 TYPE_IRIS, 108 TYPE_FACE 109 }; 110 111 /** 112 * Authentication either just called and we have not transitioned to the CALLED state, or 113 * authentication terminated (success or error). 114 */ 115 private static final int STATE_AUTH_IDLE = 0; 116 /** 117 * Authentication was called and we are waiting for the <Biometric>Services to return their 118 * cookies before starting the hardware and showing the BiometricPrompt. 119 */ 120 private static final int STATE_AUTH_CALLED = 1; 121 /** 122 * Authentication started, BiometricPrompt is showing and the hardware is authenticating. 123 */ 124 private static final int STATE_AUTH_STARTED = 2; 125 /** 126 * Authentication is paused, waiting for the user to press "try again" button. Only 127 * passive modalities such as Face or Iris should have this state. Note that for passive 128 * modalities, the HAL enters the idle state after onAuthenticated(false) which differs from 129 * fingerprint. 130 */ 131 private static final int STATE_AUTH_PAUSED = 3; 132 /** 133 * Authentication is successful, but we're waiting for the user to press "confirm" button. 134 */ 135 private static final int STATE_AUTH_PENDING_CONFIRM = 5; 136 /** 137 * Biometric authentication was canceled, but the device is now showing ConfirmDeviceCredential 138 */ 139 private static final int STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC = 6; 140 141 private final class AuthSession implements IBinder.DeathRecipient { 142 // Map of Authenticator/Cookie pairs. We expect to receive the cookies back from 143 // <Biometric>Services before we can start authenticating. Pairs that have been returned 144 // are moved to mModalitiesMatched. 145 final HashMap<Integer, Integer> mModalitiesWaiting; 146 // Pairs that have been matched. 147 final HashMap<Integer, Integer> mModalitiesMatched = new HashMap<>(); 148 149 // The following variables are passed to authenticateInternal, which initiates the 150 // appropriate <Biometric>Services. 151 final IBinder mToken; 152 final long mSessionId; 153 final int mUserId; 154 // Original receiver from BiometricPrompt. 155 final IBiometricServiceReceiver mClientReceiver; 156 final String mOpPackageName; 157 // Info to be shown on BiometricDialog when all cookies are returned. 158 final Bundle mBundle; 159 final int mCallingUid; 160 final int mCallingPid; 161 final int mCallingUserId; 162 // Continue authentication with the same modality/modalities after "try again" is 163 // pressed 164 final int mModality; 165 final boolean mRequireConfirmation; 166 167 // The current state, which can be either idle, called, or started 168 private int mState = STATE_AUTH_IDLE; 169 // For explicit confirmation, do not send to keystore until the user has confirmed 170 // the authentication. 171 byte[] mTokenEscrow; 172 173 // Timestamp when hardware authentication occurred 174 private long mAuthenticatedTimeMs; 175 176 // TODO(b/123378871): Remove when moved. 177 private IBiometricConfirmDeviceCredentialCallback mConfirmDeviceCredentialCallback; 178 AuthSession(HashMap<Integer, Integer> modalities, IBinder token, long sessionId, int userId, IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle, int callingUid, int callingPid, int callingUserId, int modality, boolean requireConfirmation, IBiometricConfirmDeviceCredentialCallback callback)179 AuthSession(HashMap<Integer, Integer> modalities, IBinder token, long sessionId, 180 int userId, IBiometricServiceReceiver receiver, String opPackageName, 181 Bundle bundle, int callingUid, int callingPid, int callingUserId, 182 int modality, boolean requireConfirmation, 183 IBiometricConfirmDeviceCredentialCallback callback) { 184 mModalitiesWaiting = modalities; 185 mToken = token; 186 mSessionId = sessionId; 187 mUserId = userId; 188 mClientReceiver = receiver; 189 mOpPackageName = opPackageName; 190 mBundle = bundle; 191 mCallingUid = callingUid; 192 mCallingPid = callingPid; 193 mCallingUserId = callingUserId; 194 mModality = modality; 195 mRequireConfirmation = requireConfirmation; 196 mConfirmDeviceCredentialCallback = callback; 197 198 if (isFromConfirmDeviceCredential()) { 199 try { 200 token.linkToDeath(this, 0 /* flags */); 201 } catch (RemoteException e) { 202 Slog.e(TAG, "Unable to link to death", e); 203 } 204 } 205 } 206 isCrypto()207 boolean isCrypto() { 208 return mSessionId != 0; 209 } 210 isFromConfirmDeviceCredential()211 boolean isFromConfirmDeviceCredential() { 212 return mBundle.getBoolean(BiometricPrompt.KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, false); 213 } 214 containsCookie(int cookie)215 boolean containsCookie(int cookie) { 216 if (mModalitiesWaiting != null && mModalitiesWaiting.containsValue(cookie)) { 217 return true; 218 } 219 if (mModalitiesMatched != null && mModalitiesMatched.containsValue(cookie)) { 220 return true; 221 } 222 return false; 223 } 224 225 // TODO(b/123378871): Remove when moved. 226 @Override binderDied()227 public void binderDied() { 228 mHandler.post(() -> { 229 Slog.e(TAG, "Binder died, killing ConfirmDeviceCredential"); 230 if (mConfirmDeviceCredentialCallback == null) { 231 Slog.e(TAG, "Callback is null"); 232 return; 233 } 234 235 try { 236 mConfirmDeviceCredentialCallback.cancel(); 237 mConfirmDeviceCredentialCallback = null; 238 } catch (RemoteException e) { 239 Slog.e(TAG, "Unable to send cancel", e); 240 } 241 }); 242 } 243 } 244 245 private final class BiometricTaskStackListener extends TaskStackListener { 246 @Override onTaskStackChanged()247 public void onTaskStackChanged() { 248 mHandler.sendEmptyMessage(MSG_ON_TASK_STACK_CHANGED); 249 } 250 } 251 252 private final AppOpsManager mAppOps; 253 private final boolean mHasFeatureFingerprint; 254 private final boolean mHasFeatureIris; 255 private final boolean mHasFeatureFace; 256 private final SettingObserver mSettingObserver; 257 private final List<EnabledOnKeyguardCallback> mEnabledOnKeyguardCallbacks; 258 private final BiometricTaskStackListener mTaskStackListener = new BiometricTaskStackListener(); 259 private final Random mRandom = new Random(); 260 261 private IFingerprintService mFingerprintService; 262 private IFaceService mFaceService; 263 private IActivityTaskManager mActivityTaskManager; 264 private IStatusBarService mStatusBarService; 265 266 // Get and cache the available authenticator (manager) classes. Used since aidl doesn't support 267 // polymorphism :/ 268 final ArrayList<Authenticator> mAuthenticators = new ArrayList<>(); 269 270 // Cache the current service that's being used. This is the service which 271 // cancelAuthentication() must be forwarded to. This is just a cache, and the actual 272 // check (is caller the current client) is done in the <Biometric>Service. 273 // Since Settings/System (not application) is responsible for changing preference, this 274 // should be safe. 275 private int mCurrentModality; 276 277 // The current authentication session, null if idle/done. We need to track both the current 278 // and pending sessions since errors may be sent to either. 279 private AuthSession mCurrentAuthSession; 280 private AuthSession mPendingAuthSession; 281 282 // TODO(b/123378871): Remove when moved. 283 // When BiometricPrompt#setAllowDeviceCredentials is set to true, we need to store the 284 // client (app) receiver. BiometricService internally launches CDCA which invokes 285 // BiometricService to start authentication (normal path). When auth is success/rejected, 286 // CDCA will use an aidl method to poke BiometricService - the result will then be forwarded 287 // to this receiver. 288 private IBiometricServiceReceiver mConfirmDeviceCredentialReceiver; 289 290 private final Handler mHandler = new Handler(Looper.getMainLooper()) { 291 @Override 292 public void handleMessage(Message msg) { 293 switch (msg.what) { 294 case MSG_ON_TASK_STACK_CHANGED: { 295 handleTaskStackChanged(); 296 break; 297 } 298 299 case MSG_ON_AUTHENTICATION_SUCCEEDED: { 300 SomeArgs args = (SomeArgs) msg.obj; 301 handleAuthenticationSucceeded( 302 (boolean) args.arg1 /* requireConfirmation */, 303 (byte[]) args.arg2 /* token */); 304 args.recycle(); 305 break; 306 } 307 308 case MSG_ON_AUTHENTICATION_FAILED: { 309 handleAuthenticationFailed((String) msg.obj /* failureReason */); 310 break; 311 } 312 313 case MSG_ON_ERROR: { 314 SomeArgs args = (SomeArgs) msg.obj; 315 handleOnError( 316 args.argi1 /* cookie */, 317 args.argi2 /* error */, 318 (String) args.arg1 /* message */); 319 args.recycle(); 320 break; 321 } 322 323 case MSG_ON_ACQUIRED: { 324 SomeArgs args = (SomeArgs) msg.obj; 325 handleOnAcquired( 326 args.argi1 /* acquiredInfo */, 327 (String) args.arg1 /* message */); 328 args.recycle(); 329 break; 330 } 331 332 case MSG_ON_DISMISSED: { 333 handleOnDismissed(msg.arg1); 334 break; 335 } 336 337 case MSG_ON_TRY_AGAIN_PRESSED: { 338 handleOnTryAgainPressed(); 339 break; 340 } 341 342 case MSG_ON_READY_FOR_AUTHENTICATION: { 343 SomeArgs args = (SomeArgs) msg.obj; 344 handleOnReadyForAuthentication( 345 args.argi1 /* cookie */, 346 (boolean) args.arg1 /* requireConfirmation */, 347 args.argi2 /* userId */); 348 args.recycle(); 349 break; 350 } 351 352 case MSG_AUTHENTICATE: { 353 SomeArgs args = (SomeArgs) msg.obj; 354 handleAuthenticate( 355 (IBinder) args.arg1 /* token */, 356 (long) args.arg2 /* sessionId */, 357 args.argi1 /* userid */, 358 (IBiometricServiceReceiver) args.arg3 /* receiver */, 359 (String) args.arg4 /* opPackageName */, 360 (Bundle) args.arg5 /* bundle */, 361 args.argi2 /* callingUid */, 362 args.argi3 /* callingPid */, 363 args.argi4 /* callingUserId */, 364 (IBiometricConfirmDeviceCredentialCallback) args.arg6 /* callback */); 365 args.recycle(); 366 break; 367 } 368 369 case MSG_CANCEL_AUTHENTICATION: { 370 SomeArgs args = (SomeArgs) msg.obj; 371 handleCancelAuthentication( 372 (IBinder) args.arg1 /* token */, 373 (String) args.arg2 /* opPackageName */); 374 args.recycle(); 375 break; 376 } 377 378 case MSG_ON_CONFIRM_DEVICE_CREDENTIAL_SUCCESS: { 379 handleOnConfirmDeviceCredentialSuccess(); 380 break; 381 } 382 383 case MSG_ON_CONFIRM_DEVICE_CREDENTIAL_ERROR: { 384 SomeArgs args = (SomeArgs) msg.obj; 385 handleOnConfirmDeviceCredentialError( 386 args.argi1 /* error */, 387 (String) args.arg1 /* errorMsg */); 388 args.recycle(); 389 break; 390 } 391 392 case MSG_REGISTER_CANCELLATION_CALLBACK: { 393 handleRegisterCancellationCallback( 394 (IBiometricConfirmDeviceCredentialCallback) msg.obj /* callback */); 395 break; 396 } 397 398 default: 399 Slog.e(TAG, "Unknown message: " + msg); 400 break; 401 } 402 } 403 }; 404 405 private final class Authenticator { 406 int mType; 407 BiometricAuthenticator mAuthenticator; 408 Authenticator(int type, BiometricAuthenticator authenticator)409 Authenticator(int type, BiometricAuthenticator authenticator) { 410 mType = type; 411 mAuthenticator = authenticator; 412 } 413 getType()414 int getType() { 415 return mType; 416 } 417 getAuthenticator()418 BiometricAuthenticator getAuthenticator() { 419 return mAuthenticator; 420 } 421 } 422 423 private final class SettingObserver extends ContentObserver { 424 425 private static final boolean DEFAULT_KEYGUARD_ENABLED = true; 426 private static final boolean DEFAULT_APP_ENABLED = true; 427 private static final boolean DEFAULT_ALWAYS_REQUIRE_CONFIRMATION = false; 428 429 private final Uri FACE_UNLOCK_KEYGUARD_ENABLED = 430 Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED); 431 private final Uri FACE_UNLOCK_APP_ENABLED = 432 Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_APP_ENABLED); 433 private final Uri FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION = 434 Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION); 435 436 private final ContentResolver mContentResolver; 437 438 private Map<Integer, Boolean> mFaceEnabledOnKeyguard = new HashMap<>(); 439 private Map<Integer, Boolean> mFaceEnabledForApps = new HashMap<>(); 440 private Map<Integer, Boolean> mFaceAlwaysRequireConfirmation = new HashMap<>(); 441 442 /** 443 * Creates a content observer. 444 * 445 * @param handler The handler to run {@link #onChange} on, or null if none. 446 */ SettingObserver(Handler handler)447 SettingObserver(Handler handler) { 448 super(handler); 449 mContentResolver = getContext().getContentResolver(); 450 updateContentObserver(); 451 } 452 updateContentObserver()453 void updateContentObserver() { 454 mContentResolver.unregisterContentObserver(this); 455 mContentResolver.registerContentObserver(FACE_UNLOCK_KEYGUARD_ENABLED, 456 false /* notifyForDescendents */, 457 this /* observer */, 458 UserHandle.USER_ALL); 459 mContentResolver.registerContentObserver(FACE_UNLOCK_APP_ENABLED, 460 false /* notifyForDescendents */, 461 this /* observer */, 462 UserHandle.USER_ALL); 463 mContentResolver.registerContentObserver(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, 464 false /* notifyForDescendents */, 465 this /* observer */, 466 UserHandle.USER_ALL); 467 } 468 469 @Override onChange(boolean selfChange, Uri uri, int userId)470 public void onChange(boolean selfChange, Uri uri, int userId) { 471 if (FACE_UNLOCK_KEYGUARD_ENABLED.equals(uri)) { 472 mFaceEnabledOnKeyguard.put(userId, Settings.Secure.getIntForUser( 473 mContentResolver, 474 Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED, 475 DEFAULT_KEYGUARD_ENABLED ? 1 : 0 /* default */, 476 userId) != 0); 477 478 if (userId == ActivityManager.getCurrentUser() && !selfChange) { 479 notifyEnabledOnKeyguardCallbacks(userId); 480 } 481 } else if (FACE_UNLOCK_APP_ENABLED.equals(uri)) { 482 mFaceEnabledForApps.put(userId, Settings.Secure.getIntForUser( 483 mContentResolver, 484 Settings.Secure.FACE_UNLOCK_APP_ENABLED, 485 DEFAULT_APP_ENABLED ? 1 : 0 /* default */, 486 userId) != 0); 487 } else if (FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION.equals(uri)) { 488 mFaceAlwaysRequireConfirmation.put(userId, Settings.Secure.getIntForUser( 489 mContentResolver, 490 Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, 491 DEFAULT_ALWAYS_REQUIRE_CONFIRMATION ? 1 : 0 /* default */, 492 userId) != 0); 493 } 494 } 495 getFaceEnabledOnKeyguard()496 boolean getFaceEnabledOnKeyguard() { 497 final int user = ActivityManager.getCurrentUser(); 498 if (!mFaceEnabledOnKeyguard.containsKey(user)) { 499 onChange(true /* selfChange */, FACE_UNLOCK_KEYGUARD_ENABLED, user); 500 } 501 return mFaceEnabledOnKeyguard.get(user); 502 } 503 getFaceEnabledForApps(int userId)504 boolean getFaceEnabledForApps(int userId) { 505 if (!mFaceEnabledForApps.containsKey(userId)) { 506 onChange(true /* selfChange */, FACE_UNLOCK_APP_ENABLED, userId); 507 } 508 return mFaceEnabledForApps.getOrDefault(userId, DEFAULT_APP_ENABLED); 509 } 510 getFaceAlwaysRequireConfirmation(int userId)511 boolean getFaceAlwaysRequireConfirmation(int userId) { 512 if (!mFaceAlwaysRequireConfirmation.containsKey(userId)) { 513 onChange(true /* selfChange */, FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, userId); 514 } 515 return mFaceAlwaysRequireConfirmation.get(userId); 516 } 517 notifyEnabledOnKeyguardCallbacks(int userId)518 void notifyEnabledOnKeyguardCallbacks(int userId) { 519 List<EnabledOnKeyguardCallback> callbacks = mEnabledOnKeyguardCallbacks; 520 for (int i = 0; i < callbacks.size(); i++) { 521 callbacks.get(i).notify(BiometricSourceType.FACE, 522 mFaceEnabledOnKeyguard.getOrDefault(userId, 523 DEFAULT_KEYGUARD_ENABLED)); 524 } 525 } 526 } 527 528 private final class EnabledOnKeyguardCallback implements IBinder.DeathRecipient { 529 530 private final IBiometricEnabledOnKeyguardCallback mCallback; 531 EnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback)532 EnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback) { 533 mCallback = callback; 534 try { 535 mCallback.asBinder().linkToDeath(EnabledOnKeyguardCallback.this, 0); 536 } catch (RemoteException e) { 537 Slog.w(TAG, "Unable to linkToDeath", e); 538 } 539 } 540 notify(BiometricSourceType sourceType, boolean enabled)541 void notify(BiometricSourceType sourceType, boolean enabled) { 542 try { 543 mCallback.onChanged(sourceType, enabled); 544 } catch (DeadObjectException e) { 545 Slog.w(TAG, "Death while invoking notify", e); 546 mEnabledOnKeyguardCallbacks.remove(this); 547 } catch (RemoteException e) { 548 Slog.w(TAG, "Failed to invoke onChanged", e); 549 } 550 } 551 552 @Override binderDied()553 public void binderDied() { 554 Slog.e(TAG, "Enabled callback binder died"); 555 mEnabledOnKeyguardCallbacks.remove(this); 556 } 557 } 558 559 // Wrap the client's receiver so we can do things with the BiometricDialog first 560 private final IBiometricServiceReceiverInternal mInternalReceiver = 561 new IBiometricServiceReceiverInternal.Stub() { 562 @Override 563 public void onAuthenticationSucceeded(boolean requireConfirmation, byte[] token) 564 throws RemoteException { 565 SomeArgs args = SomeArgs.obtain(); 566 args.arg1 = requireConfirmation; 567 args.arg2 = token; 568 mHandler.obtainMessage(MSG_ON_AUTHENTICATION_SUCCEEDED, args).sendToTarget(); 569 } 570 571 @Override 572 public void onAuthenticationFailed(int cookie, boolean requireConfirmation) 573 throws RemoteException { 574 String failureReason = getContext().getString(R.string.biometric_not_recognized); 575 mHandler.obtainMessage(MSG_ON_AUTHENTICATION_FAILED, failureReason).sendToTarget(); 576 } 577 578 @Override 579 public void onError(int cookie, int error, String message) throws RemoteException { 580 // Determine if error is hard or soft error. Certain errors (such as TIMEOUT) are 581 // soft errors and we should allow the user to try authenticating again instead of 582 // dismissing BiometricPrompt. 583 if (error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT) { 584 mHandler.obtainMessage(MSG_ON_AUTHENTICATION_FAILED, message).sendToTarget(); 585 } else { 586 SomeArgs args = SomeArgs.obtain(); 587 args.argi1 = cookie; 588 args.argi2 = error; 589 args.arg1 = message; 590 mHandler.obtainMessage(MSG_ON_ERROR, args).sendToTarget(); 591 } 592 } 593 594 @Override 595 public void onAcquired(int acquiredInfo, String message) throws RemoteException { 596 SomeArgs args = SomeArgs.obtain(); 597 args.argi1 = acquiredInfo; 598 args.arg1 = message; 599 mHandler.obtainMessage(MSG_ON_ACQUIRED, args).sendToTarget(); 600 } 601 602 @Override 603 public void onDialogDismissed(int reason) throws RemoteException { 604 mHandler.obtainMessage(MSG_ON_DISMISSED, reason, 0 /* arg2 */).sendToTarget(); 605 } 606 607 @Override 608 public void onTryAgainPressed() { 609 mHandler.sendEmptyMessage(MSG_ON_TRY_AGAIN_PRESSED); 610 } 611 }; 612 613 614 /** 615 * This is just a pass-through service that wraps Fingerprint, Iris, Face services. This service 616 * should not carry any state. The reality is we need to keep a tiny amount of state so that 617 * cancelAuthentication() can go to the right place. 618 */ 619 private final class BiometricServiceWrapper extends IBiometricService.Stub { 620 @Override // Binder call onReadyForAuthentication(int cookie, boolean requireConfirmation, int userId)621 public void onReadyForAuthentication(int cookie, boolean requireConfirmation, int userId) { 622 checkInternalPermission(); 623 624 SomeArgs args = SomeArgs.obtain(); 625 args.argi1 = cookie; 626 args.arg1 = requireConfirmation; 627 args.argi2 = userId; 628 mHandler.obtainMessage(MSG_ON_READY_FOR_AUTHENTICATION, args).sendToTarget(); 629 } 630 631 @Override // Binder call authenticate(IBinder token, long sessionId, int userId, IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle, IBiometricConfirmDeviceCredentialCallback callback)632 public void authenticate(IBinder token, long sessionId, int userId, 633 IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle, 634 IBiometricConfirmDeviceCredentialCallback callback) 635 throws RemoteException { 636 final int callingUid = Binder.getCallingUid(); 637 final int callingPid = Binder.getCallingPid(); 638 final int callingUserId = UserHandle.getCallingUserId(); 639 640 // TODO(b/123378871): Remove when moved. 641 if (callback != null) { 642 checkInternalPermission(); 643 } 644 645 // In the BiometricServiceBase, check do the AppOps and foreground check. 646 if (userId == callingUserId) { 647 // Check the USE_BIOMETRIC permission here. 648 checkPermission(); 649 } else { 650 // Only allow internal clients to authenticate with a different userId 651 Slog.w(TAG, "User " + callingUserId + " is requesting authentication of userid: " 652 + userId); 653 checkInternalPermission(); 654 } 655 656 if (token == null || receiver == null || opPackageName == null || bundle == null) { 657 Slog.e(TAG, "Unable to authenticate, one or more null arguments"); 658 return; 659 } 660 661 final boolean isFromConfirmDeviceCredential = 662 bundle.getBoolean(BiometricPrompt.KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, false); 663 if (isFromConfirmDeviceCredential) { 664 checkInternalPermission(); 665 } 666 667 // Check the usage of this in system server. Need to remove this check if it becomes 668 // a public API. 669 final boolean useDefaultTitle = 670 bundle.getBoolean(BiometricPrompt.KEY_USE_DEFAULT_TITLE, false); 671 if (useDefaultTitle) { 672 checkInternalPermission(); 673 // Set the default title if necessary 674 if (TextUtils.isEmpty(bundle.getCharSequence(BiometricPrompt.KEY_TITLE))) { 675 bundle.putCharSequence(BiometricPrompt.KEY_TITLE, 676 getContext().getString(R.string.biometric_dialog_default_title)); 677 } 678 } 679 680 // Launch CDC instead if necessary. CDC will return results through an AIDL call, since 681 // we can't get activity results. Store the receiver somewhere so we can forward the 682 // result back to the client. 683 // TODO(b/123378871): Remove when moved. 684 if (bundle.getBoolean(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL)) { 685 mHandler.post(() -> { 686 final KeyguardManager kgm = getContext().getSystemService( 687 KeyguardManager.class); 688 if (!kgm.isDeviceSecure()) { 689 try { 690 receiver.onError( 691 BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL, 692 getContext().getString( 693 R.string.biometric_error_device_not_secured)); 694 } catch (RemoteException e) { 695 Slog.e(TAG, "Remote exception", e); 696 } 697 return; 698 } 699 mConfirmDeviceCredentialReceiver = receiver; 700 // Use this so we don't need to duplicate logic.. 701 final Intent intent = kgm.createConfirmDeviceCredentialIntent(null /* title */, 702 null /* description */, userId); 703 // Then give it the bundle to do magic behavior.. 704 intent.putExtra(KeyguardManager.EXTRA_BIOMETRIC_PROMPT_BUNDLE, bundle); 705 // Create a new task with this activity located at the root. 706 intent.setFlags( 707 Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT); 708 getContext().startActivityAsUser(intent, UserHandle.CURRENT); 709 }); 710 return; 711 } 712 713 SomeArgs args = SomeArgs.obtain(); 714 args.arg1 = token; 715 args.arg2 = sessionId; 716 args.argi1 = userId; 717 args.arg3 = receiver; 718 args.arg4 = opPackageName; 719 args.arg5 = bundle; 720 args.argi2 = callingUid; 721 args.argi3 = callingPid; 722 args.argi4 = callingUserId; 723 args.arg6 = callback; 724 725 mHandler.obtainMessage(MSG_AUTHENTICATE, args).sendToTarget(); 726 } 727 728 @Override // Binder call onConfirmDeviceCredentialSuccess()729 public void onConfirmDeviceCredentialSuccess() { 730 checkInternalPermission(); 731 732 mHandler.sendEmptyMessage(MSG_ON_CONFIRM_DEVICE_CREDENTIAL_SUCCESS); 733 } 734 735 @Override // Binder call onConfirmDeviceCredentialError(int error, String message)736 public void onConfirmDeviceCredentialError(int error, String message) { 737 checkInternalPermission(); 738 739 SomeArgs args = SomeArgs.obtain(); 740 args.argi1 = error; 741 args.arg1 = message; 742 mHandler.obtainMessage(MSG_ON_CONFIRM_DEVICE_CREDENTIAL_ERROR, args).sendToTarget(); 743 } 744 745 @Override // Binder call registerCancellationCallback( IBiometricConfirmDeviceCredentialCallback callback)746 public void registerCancellationCallback( 747 IBiometricConfirmDeviceCredentialCallback callback) { 748 // TODO(b/123378871): Remove when moved. 749 // This callback replaces the one stored in the current session. If the session is null 750 // we can ignore this, since it means ConfirmDeviceCredential was launched by something 751 // else (not BiometricPrompt) 752 checkInternalPermission(); 753 754 mHandler.obtainMessage(MSG_REGISTER_CANCELLATION_CALLBACK, callback).sendToTarget(); 755 } 756 757 @Override // Binder call cancelAuthentication(IBinder token, String opPackageName)758 public void cancelAuthentication(IBinder token, String opPackageName) 759 throws RemoteException { 760 checkPermission(); 761 762 SomeArgs args = SomeArgs.obtain(); 763 args.arg1 = token; 764 args.arg2 = opPackageName; 765 mHandler.obtainMessage(MSG_CANCEL_AUTHENTICATION, args).sendToTarget(); 766 } 767 768 @Override // Binder call canAuthenticate(String opPackageName)769 public int canAuthenticate(String opPackageName) { 770 checkPermission(); 771 772 final int userId = UserHandle.getCallingUserId(); 773 final long ident = Binder.clearCallingIdentity(); 774 int error; 775 try { 776 final Pair<Integer, Integer> result = checkAndGetBiometricModality(userId); 777 error = result.second; 778 } finally { 779 Binder.restoreCallingIdentity(ident); 780 } 781 return error; 782 } 783 784 @Override // Binder call registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback)785 public void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback) 786 throws RemoteException { 787 checkInternalPermission(); 788 mEnabledOnKeyguardCallbacks.add(new EnabledOnKeyguardCallback(callback)); 789 try { 790 callback.onChanged(BiometricSourceType.FACE, 791 mSettingObserver.getFaceEnabledOnKeyguard()); 792 } catch (RemoteException e) { 793 Slog.w(TAG, "Remote exception", e); 794 } 795 } 796 797 @Override // Binder call setActiveUser(int userId)798 public void setActiveUser(int userId) { 799 checkInternalPermission(); 800 final long ident = Binder.clearCallingIdentity(); 801 try { 802 for (int i = 0; i < mAuthenticators.size(); i++) { 803 mAuthenticators.get(i).getAuthenticator().setActiveUser(userId); 804 } 805 } finally { 806 Binder.restoreCallingIdentity(ident); 807 } 808 } 809 810 @Override // Binder call resetLockout(byte[] token)811 public void resetLockout(byte[] token) { 812 checkInternalPermission(); 813 final long ident = Binder.clearCallingIdentity(); 814 try { 815 if (mFingerprintService != null) { 816 mFingerprintService.resetTimeout(token); 817 } 818 if (mFaceService != null) { 819 mFaceService.resetLockout(token); 820 } 821 } catch (RemoteException e) { 822 Slog.e(TAG, "Remote exception", e); 823 } finally { 824 Binder.restoreCallingIdentity(ident); 825 } 826 } 827 } 828 checkAppOp(String opPackageName, int callingUid)829 private void checkAppOp(String opPackageName, int callingUid) { 830 if (mAppOps.noteOp(AppOpsManager.OP_USE_BIOMETRIC, callingUid, 831 opPackageName) != AppOpsManager.MODE_ALLOWED) { 832 Slog.w(TAG, "Rejecting " + opPackageName + "; permission denied"); 833 throw new SecurityException("Permission denied"); 834 } 835 } 836 checkInternalPermission()837 private void checkInternalPermission() { 838 getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL, 839 "Must have USE_BIOMETRIC_INTERNAL permission"); 840 } 841 checkPermission()842 private void checkPermission() { 843 if (getContext().checkCallingOrSelfPermission(USE_FINGERPRINT) 844 != PackageManager.PERMISSION_GRANTED) { 845 getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC, 846 "Must have USE_BIOMETRIC permission"); 847 } 848 } 849 850 /** 851 * Initializes the system service. 852 * <p> 853 * Subclasses must define a single argument constructor that accepts the context 854 * and passes it to super. 855 * </p> 856 * 857 * @param context The system server context. 858 */ BiometricService(Context context)859 public BiometricService(Context context) { 860 super(context); 861 862 mAppOps = context.getSystemService(AppOpsManager.class); 863 mEnabledOnKeyguardCallbacks = new ArrayList<>(); 864 mSettingObserver = new SettingObserver(mHandler); 865 866 final PackageManager pm = context.getPackageManager(); 867 mHasFeatureFingerprint = pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT); 868 mHasFeatureIris = pm.hasSystemFeature(PackageManager.FEATURE_IRIS); 869 mHasFeatureFace = pm.hasSystemFeature(PackageManager.FEATURE_FACE); 870 871 try { 872 ActivityManager.getService().registerUserSwitchObserver( 873 new UserSwitchObserver() { 874 @Override 875 public void onUserSwitchComplete(int newUserId) { 876 mSettingObserver.updateContentObserver(); 877 mSettingObserver.notifyEnabledOnKeyguardCallbacks(newUserId); 878 } 879 }, BiometricService.class.getName() 880 ); 881 } catch (RemoteException e) { 882 Slog.e(TAG, "Failed to register user switch observer", e); 883 } 884 } 885 886 @Override onStart()887 public void onStart() { 888 // TODO: maybe get these on-demand 889 if (mHasFeatureFingerprint) { 890 mFingerprintService = IFingerprintService.Stub.asInterface( 891 ServiceManager.getService(Context.FINGERPRINT_SERVICE)); 892 } 893 if (mHasFeatureFace) { 894 mFaceService = IFaceService.Stub.asInterface( 895 ServiceManager.getService(Context.FACE_SERVICE)); 896 } 897 898 mActivityTaskManager = ActivityTaskManager.getService(); 899 mStatusBarService = IStatusBarService.Stub.asInterface( 900 ServiceManager.getService(Context.STATUS_BAR_SERVICE)); 901 902 // Cache the authenticators 903 for (int i = 0; i < FEATURE_ID.length; i++) { 904 if (hasFeature(FEATURE_ID[i])) { 905 Authenticator authenticator = 906 new Authenticator(FEATURE_ID[i], getAuthenticator(FEATURE_ID[i])); 907 mAuthenticators.add(authenticator); 908 } 909 } 910 911 publishBinderService(Context.BIOMETRIC_SERVICE, new BiometricServiceWrapper()); 912 } 913 914 /** 915 * Checks if there are any available biometrics, and returns the modality. This method also 916 * returns errors through the callback (no biometric feature, hardware not detected, no 917 * templates enrolled, etc). This service must not start authentication if errors are sent. 918 * 919 * @Returns A pair [Modality, Error] with Modality being one of 920 * {@link BiometricAuthenticator#TYPE_NONE}, 921 * {@link BiometricAuthenticator#TYPE_FINGERPRINT}, 922 * {@link BiometricAuthenticator#TYPE_IRIS}, 923 * {@link BiometricAuthenticator#TYPE_FACE} 924 * and the error containing one of the {@link BiometricConstants} errors. 925 */ checkAndGetBiometricModality(int userId)926 private Pair<Integer, Integer> checkAndGetBiometricModality(int userId) { 927 int modality = TYPE_NONE; 928 929 // No biometric features, send error 930 if (mAuthenticators.isEmpty()) { 931 return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT); 932 } 933 934 // Assuming that authenticators are listed in priority-order, the rest of this function 935 // will go through and find the first authenticator that's available, enrolled, and enabled. 936 // The tricky part is returning the correct error. Error strings that are modality-specific 937 // should also respect the priority-order. 938 939 // Find first authenticator that's detected, enrolled, and enabled. 940 boolean isHardwareDetected = false; 941 boolean hasTemplatesEnrolled = false; 942 boolean enabledForApps = false; 943 944 int firstHwAvailable = TYPE_NONE; 945 for (int i = 0; i < mAuthenticators.size(); i++) { 946 modality = mAuthenticators.get(i).getType(); 947 BiometricAuthenticator authenticator = mAuthenticators.get(i).getAuthenticator(); 948 if (authenticator.isHardwareDetected()) { 949 isHardwareDetected = true; 950 if (firstHwAvailable == TYPE_NONE) { 951 // Store the first one since we want to return the error in correct priority 952 // order. 953 firstHwAvailable = modality; 954 } 955 if (authenticator.hasEnrolledTemplates(userId)) { 956 hasTemplatesEnrolled = true; 957 if (isEnabledForApp(modality, userId)) { 958 // TODO(b/110907543): When face settings (and other settings) have both a 959 // user toggle as well as a work profile settings page, this needs to be 960 // updated to reflect the correct setting. 961 enabledForApps = true; 962 break; 963 } 964 } 965 } 966 } 967 968 // Check error conditions 969 if (!isHardwareDetected) { 970 return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE); 971 } else if (!hasTemplatesEnrolled) { 972 // Return the modality here so the correct error string can be sent. This error is 973 // preferred over !enabledForApps 974 return new Pair<>(firstHwAvailable, BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS); 975 } else if (!enabledForApps) { 976 return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE); 977 } 978 979 return new Pair<>(modality, BiometricConstants.BIOMETRIC_SUCCESS); 980 } 981 isEnabledForApp(int modality, int userId)982 private boolean isEnabledForApp(int modality, int userId) { 983 switch(modality) { 984 case TYPE_FINGERPRINT: 985 return true; 986 case TYPE_IRIS: 987 return true; 988 case TYPE_FACE: 989 return mSettingObserver.getFaceEnabledForApps(userId); 990 default: 991 Slog.w(TAG, "Unsupported modality: " + modality); 992 return false; 993 } 994 } 995 getErrorString(int type, int error, int vendorCode)996 private String getErrorString(int type, int error, int vendorCode) { 997 switch (type) { 998 case TYPE_FINGERPRINT: 999 return FingerprintManager.getErrorString(getContext(), error, vendorCode); 1000 case TYPE_IRIS: 1001 Slog.w(TAG, "Modality not supported"); 1002 return null; // not supported 1003 case TYPE_FACE: 1004 return FaceManager.getErrorString(getContext(), error, vendorCode); 1005 default: 1006 Slog.w(TAG, "Unable to get error string for modality: " + type); 1007 return null; 1008 } 1009 } 1010 getAuthenticator(int type)1011 private BiometricAuthenticator getAuthenticator(int type) { 1012 switch (type) { 1013 case TYPE_FINGERPRINT: 1014 return (FingerprintManager) 1015 getContext().getSystemService(Context.FINGERPRINT_SERVICE); 1016 case TYPE_IRIS: 1017 return null; 1018 case TYPE_FACE: 1019 return (FaceManager) 1020 getContext().getSystemService(Context.FACE_SERVICE); 1021 default: 1022 return null; 1023 } 1024 } 1025 hasFeature(int type)1026 private boolean hasFeature(int type) { 1027 switch (type) { 1028 case TYPE_FINGERPRINT: 1029 return mHasFeatureFingerprint; 1030 case TYPE_IRIS: 1031 return mHasFeatureIris; 1032 case TYPE_FACE: 1033 return mHasFeatureFace; 1034 default: 1035 return false; 1036 } 1037 } 1038 logDialogDismissed(int reason)1039 private void logDialogDismissed(int reason) { 1040 if (reason == BiometricPrompt.DISMISSED_REASON_POSITIVE) { 1041 // Explicit auth, authentication confirmed. 1042 // Latency in this case is authenticated -> confirmed. <Biometric>Service 1043 // should have the first half (first acquired -> authenticated). 1044 final long latency = System.currentTimeMillis() 1045 - mCurrentAuthSession.mAuthenticatedTimeMs; 1046 1047 if (LoggableMonitor.DEBUG) { 1048 Slog.v(LoggableMonitor.TAG, "Confirmed! Modality: " + statsModality() 1049 + ", User: " + mCurrentAuthSession.mUserId 1050 + ", IsCrypto: " + mCurrentAuthSession.isCrypto() 1051 + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT 1052 + ", RequireConfirmation: " 1053 + mCurrentAuthSession.mRequireConfirmation 1054 + ", State: " + StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED 1055 + ", Latency: " + latency); 1056 } 1057 1058 StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED, 1059 statsModality(), 1060 mCurrentAuthSession.mUserId, 1061 mCurrentAuthSession.isCrypto(), 1062 BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, 1063 mCurrentAuthSession.mRequireConfirmation, 1064 StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED, 1065 latency, 1066 Utils.isDebugEnabled(getContext(), mCurrentAuthSession.mUserId)); 1067 } else { 1068 int error = reason == BiometricPrompt.DISMISSED_REASON_NEGATIVE 1069 ? BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON 1070 : reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL 1071 ? BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED 1072 : 0; 1073 if (LoggableMonitor.DEBUG) { 1074 Slog.v(LoggableMonitor.TAG, "Dismissed! Modality: " + statsModality() 1075 + ", User: " + mCurrentAuthSession.mUserId 1076 + ", IsCrypto: " + mCurrentAuthSession.isCrypto() 1077 + ", Action: " + BiometricsProtoEnums.ACTION_AUTHENTICATE 1078 + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT 1079 + ", Error: " + error); 1080 } 1081 // Auth canceled 1082 StatsLog.write(StatsLog.BIOMETRIC_ERROR_OCCURRED, 1083 statsModality(), 1084 mCurrentAuthSession.mUserId, 1085 mCurrentAuthSession.isCrypto(), 1086 BiometricsProtoEnums.ACTION_AUTHENTICATE, 1087 BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, 1088 error, 1089 0 /* vendorCode */, 1090 Utils.isDebugEnabled(getContext(), mCurrentAuthSession.mUserId)); 1091 } 1092 } 1093 statsModality()1094 private int statsModality() { 1095 int modality = 0; 1096 if (mCurrentAuthSession == null) { 1097 return BiometricsProtoEnums.MODALITY_UNKNOWN; 1098 } 1099 if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_FINGERPRINT) 1100 != 0) { 1101 modality |= BiometricsProtoEnums.MODALITY_FINGERPRINT; 1102 } 1103 if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_IRIS) != 0) { 1104 modality |= BiometricsProtoEnums.MODALITY_IRIS; 1105 } 1106 if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_FACE) != 0) { 1107 modality |= BiometricsProtoEnums.MODALITY_FACE; 1108 } 1109 return modality; 1110 } 1111 handleTaskStackChanged()1112 private void handleTaskStackChanged() { 1113 try { 1114 final List<ActivityManager.RunningTaskInfo> runningTasks = 1115 mActivityTaskManager.getTasks(1); 1116 if (!runningTasks.isEmpty()) { 1117 final String topPackage = runningTasks.get(0).topActivity.getPackageName(); 1118 if (mCurrentAuthSession != null 1119 && !topPackage.contentEquals(mCurrentAuthSession.mOpPackageName)) { 1120 mStatusBarService.hideBiometricDialog(); 1121 mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener); 1122 mCurrentAuthSession.mClientReceiver.onError( 1123 BiometricConstants.BIOMETRIC_ERROR_CANCELED, 1124 getContext().getString( 1125 com.android.internal.R.string.biometric_error_canceled) 1126 ); 1127 mCurrentAuthSession.mState = STATE_AUTH_IDLE; 1128 mCurrentAuthSession = null; 1129 } 1130 } 1131 } catch (RemoteException e) { 1132 Slog.e(TAG, "Unable to get running tasks", e); 1133 } 1134 } 1135 handleAuthenticationSucceeded(boolean requireConfirmation, byte[] token)1136 private void handleAuthenticationSucceeded(boolean requireConfirmation, byte[] token) { 1137 1138 try { 1139 // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded 1140 // after user dismissed/canceled dialog). 1141 if (mCurrentAuthSession == null) { 1142 Slog.e(TAG, "onAuthenticationSucceeded(): Auth session is null"); 1143 return; 1144 } 1145 1146 if (!requireConfirmation) { 1147 mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener); 1148 KeyStore.getInstance().addAuthToken(token); 1149 mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded(); 1150 mCurrentAuthSession.mState = STATE_AUTH_IDLE; 1151 mCurrentAuthSession = null; 1152 } else { 1153 mCurrentAuthSession.mAuthenticatedTimeMs = System.currentTimeMillis(); 1154 // Store the auth token and submit it to keystore after the confirmation 1155 // button has been pressed. 1156 mCurrentAuthSession.mTokenEscrow = token; 1157 mCurrentAuthSession.mState = STATE_AUTH_PENDING_CONFIRM; 1158 } 1159 1160 // Notify SysUI that the biometric has been authenticated. SysUI already knows 1161 // the implicit/explicit state and will react accordingly. 1162 mStatusBarService.onBiometricAuthenticated(true, null /* failureReason */); 1163 } catch (RemoteException e) { 1164 Slog.e(TAG, "Remote exception", e); 1165 } 1166 } 1167 handleAuthenticationFailed(String failureReason)1168 private void handleAuthenticationFailed(String failureReason) { 1169 try { 1170 // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded 1171 // after user dismissed/canceled dialog). 1172 if (mCurrentAuthSession == null) { 1173 Slog.e(TAG, "onAuthenticationFailed(): Auth session is null"); 1174 return; 1175 } 1176 1177 mStatusBarService.onBiometricAuthenticated(false, failureReason); 1178 1179 // TODO: This logic will need to be updated if BP is multi-modal 1180 if ((mCurrentAuthSession.mModality & TYPE_FACE) != 0) { 1181 // Pause authentication. onBiometricAuthenticated(false) causes the 1182 // dialog to show a "try again" button for passive modalities. 1183 mCurrentAuthSession.mState = STATE_AUTH_PAUSED; 1184 } 1185 1186 mCurrentAuthSession.mClientReceiver.onAuthenticationFailed(); 1187 } catch (RemoteException e) { 1188 Slog.e(TAG, "Remote exception", e); 1189 } 1190 } 1191 handleOnConfirmDeviceCredentialSuccess()1192 private void handleOnConfirmDeviceCredentialSuccess() { 1193 if (mConfirmDeviceCredentialReceiver == null) { 1194 Slog.w(TAG, "onCDCASuccess null!"); 1195 return; 1196 } 1197 try { 1198 mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener); 1199 mConfirmDeviceCredentialReceiver.onAuthenticationSucceeded(); 1200 if (mCurrentAuthSession != null) { 1201 mCurrentAuthSession.mState = STATE_AUTH_IDLE; 1202 mCurrentAuthSession = null; 1203 } 1204 } catch (RemoteException e) { 1205 Slog.e(TAG, "RemoteException", e); 1206 } 1207 mConfirmDeviceCredentialReceiver = null; 1208 } 1209 handleOnConfirmDeviceCredentialError(int error, String message)1210 private void handleOnConfirmDeviceCredentialError(int error, String message) { 1211 if (mConfirmDeviceCredentialReceiver == null) { 1212 Slog.w(TAG, "onCDCAError null! Error: " + error + " " + message); 1213 return; 1214 } 1215 try { 1216 mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener); 1217 mConfirmDeviceCredentialReceiver.onError(error, message); 1218 if (mCurrentAuthSession != null) { 1219 mCurrentAuthSession.mState = STATE_AUTH_IDLE; 1220 mCurrentAuthSession = null; 1221 } 1222 } catch (RemoteException e) { 1223 Slog.e(TAG, "RemoteException", e); 1224 } 1225 mConfirmDeviceCredentialReceiver = null; 1226 } 1227 handleRegisterCancellationCallback( IBiometricConfirmDeviceCredentialCallback callback)1228 private void handleRegisterCancellationCallback( 1229 IBiometricConfirmDeviceCredentialCallback callback) { 1230 if (mCurrentAuthSession == null) { 1231 Slog.d(TAG, "Current auth session null"); 1232 return; 1233 } 1234 Slog.d(TAG, "Updating cancel callback"); 1235 mCurrentAuthSession.mConfirmDeviceCredentialCallback = callback; 1236 } 1237 handleOnError(int cookie, int error, String message)1238 private void handleOnError(int cookie, int error, String message) { 1239 Slog.d(TAG, "Error: " + error + " cookie: " + cookie); 1240 // Errors can either be from the current auth session or the pending auth session. 1241 // The pending auth session may receive errors such as ERROR_LOCKOUT before 1242 // it becomes the current auth session. Similarly, the current auth session may 1243 // receive errors such as ERROR_CANCELED while the pending auth session is preparing 1244 // to be started. Thus we must match error messages with their cookies to be sure 1245 // of their intended receivers. 1246 try { 1247 if (mCurrentAuthSession != null && mCurrentAuthSession.containsCookie(cookie)) { 1248 1249 if (mCurrentAuthSession.isFromConfirmDeviceCredential()) { 1250 // If we were invoked by ConfirmDeviceCredential, do not delete the current 1251 // auth session since we still need to respond to cancel signal while 1252 if (DEBUG) Slog.d(TAG, "From CDC, transition to CANCELED_SHOWING_CDC state"); 1253 1254 // Send the error to ConfirmDeviceCredential so that it goes to Pin/Pattern/Pass 1255 // screen 1256 mCurrentAuthSession.mClientReceiver.onError(error, message); 1257 mCurrentAuthSession.mState = STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC; 1258 mStatusBarService.hideBiometricDialog(); 1259 } else if (mCurrentAuthSession.mState == STATE_AUTH_STARTED) { 1260 mStatusBarService.onBiometricError(message); 1261 if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) { 1262 mActivityTaskManager.unregisterTaskStackListener( 1263 mTaskStackListener); 1264 mCurrentAuthSession.mClientReceiver.onError(error, message); 1265 mCurrentAuthSession.mState = STATE_AUTH_IDLE; 1266 mCurrentAuthSession = null; 1267 mStatusBarService.hideBiometricDialog(); 1268 } else { 1269 // Send errors after the dialog is dismissed. 1270 mHandler.postDelayed(() -> { 1271 try { 1272 if (mCurrentAuthSession != null) { 1273 mActivityTaskManager.unregisterTaskStackListener( 1274 mTaskStackListener); 1275 mCurrentAuthSession.mClientReceiver.onError(error, 1276 message); 1277 mCurrentAuthSession.mState = STATE_AUTH_IDLE; 1278 mCurrentAuthSession = null; 1279 } 1280 } catch (RemoteException e) { 1281 Slog.e(TAG, "Remote exception", e); 1282 } 1283 }, BiometricPrompt.HIDE_DIALOG_DELAY); 1284 } 1285 } else if (mCurrentAuthSession.mState == STATE_AUTH_PAUSED) { 1286 // In the "try again" state, we should forward canceled errors to 1287 // the client and and clean up. 1288 mCurrentAuthSession.mClientReceiver.onError(error, message); 1289 mStatusBarService.onBiometricError(message); 1290 mActivityTaskManager.unregisterTaskStackListener( 1291 mTaskStackListener); 1292 mCurrentAuthSession.mState = STATE_AUTH_IDLE; 1293 mCurrentAuthSession = null; 1294 } else { 1295 Slog.e(TAG, "Impossible session error state: " 1296 + mCurrentAuthSession.mState); 1297 } 1298 } else if (mPendingAuthSession != null 1299 && mPendingAuthSession.containsCookie(cookie)) { 1300 if (mPendingAuthSession.mState == STATE_AUTH_CALLED) { 1301 mPendingAuthSession.mClientReceiver.onError(error, message); 1302 mPendingAuthSession.mState = STATE_AUTH_IDLE; 1303 mPendingAuthSession = null; 1304 } else { 1305 Slog.e(TAG, "Impossible pending session error state: " 1306 + mPendingAuthSession.mState); 1307 } 1308 } 1309 } catch (RemoteException e) { 1310 Slog.e(TAG, "Remote exception", e); 1311 } 1312 } 1313 handleOnAcquired(int acquiredInfo, String message)1314 private void handleOnAcquired(int acquiredInfo, String message) { 1315 // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded 1316 // after user dismissed/canceled dialog). 1317 if (mCurrentAuthSession == null) { 1318 Slog.e(TAG, "onAcquired(): Auth session is null"); 1319 return; 1320 } 1321 1322 if (acquiredInfo != BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) { 1323 if (message == null) { 1324 Slog.w(TAG, "Ignoring null message: " + acquiredInfo); 1325 return; 1326 } 1327 try { 1328 mStatusBarService.onBiometricHelp(message); 1329 } catch (RemoteException e) { 1330 Slog.e(TAG, "Remote exception", e); 1331 } 1332 } 1333 } 1334 handleOnDismissed(int reason)1335 private void handleOnDismissed(int reason) { 1336 if (mCurrentAuthSession == null) { 1337 Slog.e(TAG, "onDialogDismissed: " + reason + ", auth session null"); 1338 return; 1339 } 1340 1341 logDialogDismissed(reason); 1342 1343 try { 1344 if (reason != BiometricPrompt.DISMISSED_REASON_POSITIVE) { 1345 // Positive button is used by passive modalities as a "confirm" button, 1346 // do not send to client 1347 mCurrentAuthSession.mClientReceiver.onDialogDismissed(reason); 1348 // Cancel authentication. Skip the token/package check since we are cancelling 1349 // from system server. The interface is permission protected so this is fine. 1350 cancelInternal(null /* token */, null /* package */, false /* fromClient */); 1351 } 1352 if (reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL) { 1353 mCurrentAuthSession.mClientReceiver.onError( 1354 BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED, 1355 getContext().getString( 1356 com.android.internal.R.string.biometric_error_user_canceled)); 1357 } else if (reason == BiometricPrompt.DISMISSED_REASON_POSITIVE) { 1358 // Have the service send the token to KeyStore, and send onAuthenticated 1359 // to the application 1360 KeyStore.getInstance().addAuthToken(mCurrentAuthSession.mTokenEscrow); 1361 mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded(); 1362 } 1363 1364 // Do not clean up yet if we are from ConfirmDeviceCredential. We should be in the 1365 // STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC. The session should only be removed when 1366 // ConfirmDeviceCredential is confirmed or canceled. 1367 // TODO(b/123378871): Remove when moved 1368 if (!mCurrentAuthSession.isFromConfirmDeviceCredential()) { 1369 mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener); 1370 mCurrentAuthSession.mState = STATE_AUTH_IDLE; 1371 mCurrentAuthSession = null; 1372 } 1373 } catch (RemoteException e) { 1374 Slog.e(TAG, "Remote exception", e); 1375 } 1376 } 1377 handleOnTryAgainPressed()1378 private void handleOnTryAgainPressed() { 1379 Slog.d(TAG, "onTryAgainPressed"); 1380 // No need to check permission, since it can only be invoked by SystemUI 1381 // (or system server itself). 1382 authenticateInternal(mCurrentAuthSession.mToken, 1383 mCurrentAuthSession.mSessionId, 1384 mCurrentAuthSession.mUserId, 1385 mCurrentAuthSession.mClientReceiver, 1386 mCurrentAuthSession.mOpPackageName, 1387 mCurrentAuthSession.mBundle, 1388 mCurrentAuthSession.mCallingUid, 1389 mCurrentAuthSession.mCallingPid, 1390 mCurrentAuthSession.mCallingUserId, 1391 mCurrentAuthSession.mModality, 1392 mCurrentAuthSession.mConfirmDeviceCredentialCallback); 1393 } 1394 handleOnReadyForAuthentication(int cookie, boolean requireConfirmation, int userId)1395 private void handleOnReadyForAuthentication(int cookie, boolean requireConfirmation, 1396 int userId) { 1397 Iterator it = mPendingAuthSession.mModalitiesWaiting.entrySet().iterator(); 1398 while (it.hasNext()) { 1399 Map.Entry<Integer, Integer> pair = (Map.Entry) it.next(); 1400 if (pair.getValue() == cookie) { 1401 mPendingAuthSession.mModalitiesMatched.put(pair.getKey(), pair.getValue()); 1402 mPendingAuthSession.mModalitiesWaiting.remove(pair.getKey()); 1403 Slog.d(TAG, "Matched cookie: " + cookie + ", " 1404 + mPendingAuthSession.mModalitiesWaiting.size() + " remaining"); 1405 break; 1406 } 1407 } 1408 1409 if (mPendingAuthSession.mModalitiesWaiting.isEmpty()) { 1410 final boolean continuing = mCurrentAuthSession != null 1411 && mCurrentAuthSession.mState == STATE_AUTH_PAUSED; 1412 1413 mCurrentAuthSession = mPendingAuthSession; 1414 mPendingAuthSession = null; 1415 1416 mCurrentAuthSession.mState = STATE_AUTH_STARTED; 1417 try { 1418 int modality = TYPE_NONE; 1419 it = mCurrentAuthSession.mModalitiesMatched.entrySet().iterator(); 1420 while (it.hasNext()) { 1421 Map.Entry<Integer, Integer> pair = (Map.Entry) it.next(); 1422 if (pair.getKey() == TYPE_FINGERPRINT) { 1423 mFingerprintService.startPreparedClient(pair.getValue()); 1424 } else if (pair.getKey() == TYPE_IRIS) { 1425 Slog.e(TAG, "Iris unsupported"); 1426 } else if (pair.getKey() == TYPE_FACE) { 1427 mFaceService.startPreparedClient(pair.getValue()); 1428 } else { 1429 Slog.e(TAG, "Unknown modality: " + pair.getKey()); 1430 } 1431 modality |= pair.getKey(); 1432 } 1433 1434 if (!continuing) { 1435 mStatusBarService.showBiometricDialog(mCurrentAuthSession.mBundle, 1436 mInternalReceiver, modality, requireConfirmation, userId); 1437 mActivityTaskManager.registerTaskStackListener(mTaskStackListener); 1438 } 1439 } catch (RemoteException e) { 1440 Slog.e(TAG, "Remote exception", e); 1441 } 1442 } 1443 } 1444 handleAuthenticate(IBinder token, long sessionId, int userId, IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle, int callingUid, int callingPid, int callingUserId, IBiometricConfirmDeviceCredentialCallback callback)1445 private void handleAuthenticate(IBinder token, long sessionId, int userId, 1446 IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle, 1447 int callingUid, int callingPid, int callingUserId, 1448 IBiometricConfirmDeviceCredentialCallback callback) { 1449 1450 mHandler.post(() -> { 1451 final Pair<Integer, Integer> result = checkAndGetBiometricModality(userId); 1452 final int modality = result.first; 1453 final int error = result.second; 1454 1455 // Check for errors, notify callback, and return 1456 if (error != BiometricConstants.BIOMETRIC_SUCCESS) { 1457 try { 1458 final String hardwareUnavailable = 1459 getContext().getString(R.string.biometric_error_hw_unavailable); 1460 switch (error) { 1461 case BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT: 1462 receiver.onError(error, hardwareUnavailable); 1463 break; 1464 case BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE: 1465 receiver.onError(error, hardwareUnavailable); 1466 break; 1467 case BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS: 1468 receiver.onError(error, 1469 getErrorString(modality, error, 0 /* vendorCode */)); 1470 break; 1471 default: 1472 Slog.e(TAG, "Unhandled error"); 1473 break; 1474 } 1475 } catch (RemoteException e) { 1476 Slog.e(TAG, "Unable to send error", e); 1477 } 1478 return; 1479 } 1480 1481 mCurrentModality = modality; 1482 1483 // Start preparing for authentication. Authentication starts when 1484 // all modalities requested have invoked onReadyForAuthentication. 1485 authenticateInternal(token, sessionId, userId, receiver, opPackageName, bundle, 1486 callingUid, callingPid, callingUserId, modality, callback); 1487 }); 1488 } 1489 1490 /** 1491 * authenticate() (above) which is called from BiometricPrompt determines which 1492 * modality/modalities to start authenticating with. authenticateInternal() should only be 1493 * used for: 1494 * 1) Preparing <Biometric>Services for authentication when BiometricPrompt#authenticate is, 1495 * invoked, shortly after which BiometricPrompt is shown and authentication starts 1496 * 2) Preparing <Biometric>Services for authentication when BiometricPrompt is already shown 1497 * and the user has pressed "try again" 1498 */ authenticateInternal(IBinder token, long sessionId, int userId, IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle, int callingUid, int callingPid, int callingUserId, int modality, IBiometricConfirmDeviceCredentialCallback callback)1499 private void authenticateInternal(IBinder token, long sessionId, int userId, 1500 IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle, 1501 int callingUid, int callingPid, int callingUserId, int modality, 1502 IBiometricConfirmDeviceCredentialCallback callback) { 1503 try { 1504 boolean requireConfirmation = bundle.getBoolean( 1505 BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true /* default */); 1506 if ((modality & TYPE_FACE) != 0) { 1507 // Check if the user has forced confirmation to be required in Settings. 1508 requireConfirmation = requireConfirmation 1509 || mSettingObserver.getFaceAlwaysRequireConfirmation(userId); 1510 } 1511 // Generate random cookies to pass to the services that should prepare to start 1512 // authenticating. Store the cookie here and wait for all services to "ack" 1513 // with the cookie. Once all cookies are received, we can show the prompt 1514 // and let the services start authenticating. The cookie should be non-zero. 1515 final int cookie = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1; 1516 Slog.d(TAG, "Creating auth session. Modality: " + modality 1517 + ", cookie: " + cookie); 1518 final HashMap<Integer, Integer> authenticators = new HashMap<>(); 1519 authenticators.put(modality, cookie); 1520 mPendingAuthSession = new AuthSession(authenticators, token, sessionId, userId, 1521 receiver, opPackageName, bundle, callingUid, callingPid, callingUserId, 1522 modality, requireConfirmation, callback); 1523 mPendingAuthSession.mState = STATE_AUTH_CALLED; 1524 // No polymorphism :( 1525 if ((modality & TYPE_FINGERPRINT) != 0) { 1526 mFingerprintService.prepareForAuthentication(token, sessionId, userId, 1527 mInternalReceiver, opPackageName, cookie, 1528 callingUid, callingPid, callingUserId); 1529 } 1530 if ((modality & TYPE_IRIS) != 0) { 1531 Slog.w(TAG, "Iris unsupported"); 1532 } 1533 if ((modality & TYPE_FACE) != 0) { 1534 mFaceService.prepareForAuthentication(requireConfirmation, 1535 token, sessionId, userId, mInternalReceiver, opPackageName, 1536 cookie, callingUid, callingPid, callingUserId); 1537 } 1538 } catch (RemoteException e) { 1539 Slog.e(TAG, "Unable to start authentication", e); 1540 } 1541 } 1542 handleCancelAuthentication(IBinder token, String opPackageName)1543 private void handleCancelAuthentication(IBinder token, String opPackageName) { 1544 if (token == null || opPackageName == null) { 1545 Slog.e(TAG, "Unable to cancel, one or more null arguments"); 1546 return; 1547 } 1548 1549 if (mCurrentAuthSession != null 1550 && mCurrentAuthSession.mState == STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC) { 1551 if (DEBUG) Slog.d(TAG, "Cancel received while ConfirmDeviceCredential showing"); 1552 try { 1553 mCurrentAuthSession.mConfirmDeviceCredentialCallback.cancel(); 1554 } catch (RemoteException e) { 1555 Slog.e(TAG, "Unable to cancel ConfirmDeviceCredential", e); 1556 } 1557 1558 // TODO(b/123378871): Remove when moved. Piggy back on this for now to clean up. 1559 handleOnConfirmDeviceCredentialError(BiometricConstants.BIOMETRIC_ERROR_CANCELED, 1560 getContext().getString(R.string.biometric_error_canceled)); 1561 } else if (mCurrentAuthSession != null 1562 && mCurrentAuthSession.mState != STATE_AUTH_STARTED) { 1563 // We need to check the current authenticators state. If we're pending confirm 1564 // or idle, we need to dismiss the dialog and send an ERROR_CANCELED to the client, 1565 // since we won't be getting an onError from the driver. 1566 try { 1567 // Send error to client 1568 mCurrentAuthSession.mClientReceiver.onError( 1569 BiometricConstants.BIOMETRIC_ERROR_CANCELED, 1570 getContext().getString( 1571 com.android.internal.R.string.biometric_error_user_canceled) 1572 ); 1573 1574 mCurrentAuthSession.mState = STATE_AUTH_IDLE; 1575 mCurrentAuthSession = null; 1576 mStatusBarService.hideBiometricDialog(); 1577 } catch (RemoteException e) { 1578 Slog.e(TAG, "Remote exception", e); 1579 } 1580 } else { 1581 boolean fromCDC = false; 1582 if (mCurrentAuthSession != null) { 1583 fromCDC = mCurrentAuthSession.mBundle.getBoolean( 1584 BiometricPrompt.KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, false); 1585 } 1586 1587 if (fromCDC) { 1588 if (DEBUG) Slog.d(TAG, "Cancelling from CDC"); 1589 cancelInternal(token, opPackageName, false /* fromClient */); 1590 } else { 1591 cancelInternal(token, opPackageName, true /* fromClient */); 1592 } 1593 1594 } 1595 } 1596 cancelInternal(IBinder token, String opPackageName, boolean fromClient)1597 void cancelInternal(IBinder token, String opPackageName, boolean fromClient) { 1598 final int callingUid = Binder.getCallingUid(); 1599 final int callingPid = Binder.getCallingPid(); 1600 final int callingUserId = UserHandle.getCallingUserId(); 1601 mHandler.post(() -> { 1602 try { 1603 // TODO: For multiple modalities, send a single ERROR_CANCELED only when all 1604 // drivers have canceled authentication. 1605 if ((mCurrentModality & TYPE_FINGERPRINT) != 0) { 1606 mFingerprintService.cancelAuthenticationFromService(token, opPackageName, 1607 callingUid, callingPid, callingUserId, fromClient); 1608 } 1609 if ((mCurrentModality & TYPE_IRIS) != 0) { 1610 Slog.w(TAG, "Iris unsupported"); 1611 } 1612 if ((mCurrentModality & TYPE_FACE) != 0) { 1613 mFaceService.cancelAuthenticationFromService(token, opPackageName, 1614 callingUid, callingPid, callingUserId, fromClient); 1615 } 1616 } catch (RemoteException e) { 1617 Slog.e(TAG, "Unable to cancel authentication"); 1618 } 1619 }); 1620 } 1621 1622 } 1623