1 /* 2 * Copyright (C) 2014 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 android.hardware.fingerprint; 18 19 import static android.Manifest.permission.INTERACT_ACROSS_USERS; 20 import static android.Manifest.permission.MANAGE_FINGERPRINT; 21 import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT; 22 import static android.Manifest.permission.TEST_BIOMETRIC; 23 import static android.Manifest.permission.USE_BIOMETRIC; 24 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; 25 import static android.Manifest.permission.USE_FINGERPRINT; 26 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE; 27 import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON; 28 29 import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE; 30 import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_HAS_ENROLLED_FINGERPRINTS; 31 import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_IS_HARDWARE_DETECTED; 32 33 import android.annotation.IntDef; 34 import android.annotation.NonNull; 35 import android.annotation.Nullable; 36 import android.annotation.RequiresFeature; 37 import android.annotation.RequiresPermission; 38 import android.annotation.SystemService; 39 import android.annotation.TestApi; 40 import android.app.ActivityManager; 41 import android.compat.annotation.UnsupportedAppUsage; 42 import android.content.Context; 43 import android.content.pm.PackageManager; 44 import android.hardware.biometrics.BiometricAuthenticator; 45 import android.hardware.biometrics.BiometricConstants; 46 import android.hardware.biometrics.BiometricFingerprintConstants; 47 import android.hardware.biometrics.BiometricPrompt; 48 import android.hardware.biometrics.BiometricStateListener; 49 import android.hardware.biometrics.BiometricTestSession; 50 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; 51 import android.hardware.biometrics.SensorProperties; 52 import android.os.Binder; 53 import android.os.Build; 54 import android.os.CancellationSignal; 55 import android.os.CancellationSignal.OnCancelListener; 56 import android.os.Handler; 57 import android.os.IBinder; 58 import android.os.IRemoteCallback; 59 import android.os.Looper; 60 import android.os.PowerManager; 61 import android.os.RemoteException; 62 import android.os.UserHandle; 63 import android.security.identity.IdentityCredential; 64 import android.security.identity.PresentationSession; 65 import android.util.Slog; 66 import android.view.Surface; 67 68 import com.android.internal.util.FrameworkStatsLog; 69 70 import java.lang.annotation.Retention; 71 import java.lang.annotation.RetentionPolicy; 72 import java.security.Signature; 73 import java.util.ArrayList; 74 import java.util.List; 75 import java.util.concurrent.Executor; 76 77 import javax.crypto.Cipher; 78 import javax.crypto.Mac; 79 80 /** 81 * A class that coordinates access to the fingerprint hardware. 82 * @deprecated See {@link BiometricPrompt} which shows a system-provided dialog upon starting 83 * authentication. In a world where devices may have different types of biometric authentication, 84 * it's much more realistic to have a system-provided authentication dialog since the method may 85 * vary by vendor/device. 86 */ 87 @SuppressWarnings("deprecation") 88 @Deprecated 89 @SystemService(Context.FINGERPRINT_SERVICE) 90 @RequiresFeature(PackageManager.FEATURE_FINGERPRINT) 91 public class FingerprintManager implements BiometricAuthenticator, BiometricFingerprintConstants { 92 private static final String TAG = "FingerprintManager"; 93 private static final boolean DEBUG = true; 94 private static final int MSG_ENROLL_RESULT = 100; 95 private static final int MSG_ACQUIRED = 101; 96 private static final int MSG_AUTHENTICATION_SUCCEEDED = 102; 97 private static final int MSG_AUTHENTICATION_FAILED = 103; 98 private static final int MSG_ERROR = 104; 99 private static final int MSG_REMOVED = 105; 100 private static final int MSG_CHALLENGE_GENERATED = 106; 101 private static final int MSG_FINGERPRINT_DETECTED = 107; 102 private static final int MSG_UDFPS_POINTER_DOWN = 108; 103 private static final int MSG_UDFPS_POINTER_UP = 109; 104 private static final int MSG_POWER_BUTTON_PRESSED = 110; 105 106 /** 107 * @hide 108 */ 109 public static final int ENROLL_FIND_SENSOR = 1; 110 /** 111 * @hide 112 */ 113 public static final int ENROLL_ENROLL = 2; 114 115 /** 116 * @hide 117 */ 118 @IntDef({ENROLL_FIND_SENSOR, ENROLL_ENROLL}) 119 @Retention(RetentionPolicy.SOURCE) 120 public @interface EnrollReason {} 121 122 /** 123 * Request authentication with any single sensor. 124 * @hide 125 */ 126 public static final int SENSOR_ID_ANY = -1; 127 128 private static class RemoveTracker { 129 static final int REMOVE_SINGLE = 1; 130 static final int REMOVE_ALL = 2; 131 @IntDef({REMOVE_SINGLE, REMOVE_ALL}) 132 @interface RemoveRequest {} 133 134 final @RemoveRequest int mRemoveRequest; 135 @Nullable final Fingerprint mSingleFingerprint; 136 RemoveTracker(@emoveRequest int request, @Nullable Fingerprint fingerprint)137 RemoveTracker(@RemoveRequest int request, @Nullable Fingerprint fingerprint) { 138 mRemoveRequest = request; 139 mSingleFingerprint = fingerprint; 140 } 141 } 142 143 private IFingerprintService mService; 144 private Context mContext; 145 private IBinder mToken = new Binder(); 146 private AuthenticationCallback mAuthenticationCallback; 147 private FingerprintDetectionCallback mFingerprintDetectionCallback; 148 private EnrollmentCallback mEnrollmentCallback; 149 private RemovalCallback mRemovalCallback; 150 private GenerateChallengeCallback mGenerateChallengeCallback; 151 private CryptoObject mCryptoObject; 152 @Nullable private RemoveTracker mRemoveTracker; 153 private Handler mHandler; 154 @Nullable private float[] mEnrollStageThresholds; 155 156 /** 157 * Retrieves a list of properties for all fingerprint sensors on the device. 158 * @hide 159 */ 160 @TestApi 161 @NonNull 162 @RequiresPermission(TEST_BIOMETRIC) getSensorProperties()163 public List<SensorProperties> getSensorProperties() { 164 final List<SensorProperties> properties = new ArrayList<>(); 165 final List<FingerprintSensorPropertiesInternal> internalProperties 166 = getSensorPropertiesInternal(); 167 for (FingerprintSensorPropertiesInternal internalProp : internalProperties) { 168 properties.add(FingerprintSensorProperties.from(internalProp)); 169 } 170 return properties; 171 } 172 173 /** 174 * Retrieves a test session for FingerprintManager. 175 * @hide 176 */ 177 @TestApi 178 @NonNull 179 @RequiresPermission(TEST_BIOMETRIC) createTestSession(int sensorId)180 public BiometricTestSession createTestSession(int sensorId) { 181 try { 182 return new BiometricTestSession(mContext, sensorId, 183 (context, sensorId1, callback) -> mService 184 .createTestSession(sensorId1, callback, context.getOpPackageName())); 185 } catch (RemoteException e) { 186 throw e.rethrowFromSystemServer(); 187 } 188 } 189 190 private class OnEnrollCancelListener implements OnCancelListener { 191 private final long mAuthRequestId; 192 OnEnrollCancelListener(long id)193 private OnEnrollCancelListener(long id) { 194 mAuthRequestId = id; 195 } 196 197 @Override onCancel()198 public void onCancel() { 199 Slog.d(TAG, "Cancel fingerprint enrollment requested for: " + mAuthRequestId); 200 cancelEnrollment(mAuthRequestId); 201 } 202 } 203 204 private class OnAuthenticationCancelListener implements OnCancelListener { 205 private final long mAuthRequestId; 206 OnAuthenticationCancelListener(long id)207 OnAuthenticationCancelListener(long id) { 208 mAuthRequestId = id; 209 } 210 211 @Override onCancel()212 public void onCancel() { 213 Slog.d(TAG, "Cancel fingerprint authentication requested for: " + mAuthRequestId); 214 cancelAuthentication(mAuthRequestId); 215 } 216 } 217 218 private class OnFingerprintDetectionCancelListener implements OnCancelListener { 219 private final long mAuthRequestId; 220 OnFingerprintDetectionCancelListener(long id)221 OnFingerprintDetectionCancelListener(long id) { 222 mAuthRequestId = id; 223 } 224 225 @Override onCancel()226 public void onCancel() { 227 Slog.d(TAG, "Cancel fingerprint detect requested for: " + mAuthRequestId); 228 cancelFingerprintDetect(mAuthRequestId); 229 } 230 } 231 232 /** 233 * A wrapper class for the crypto objects supported by FingerprintManager. Currently the 234 * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects. 235 * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.CryptoObject} 236 */ 237 @Deprecated 238 public static final class CryptoObject extends android.hardware.biometrics.CryptoObject { CryptoObject(@onNull Signature signature)239 public CryptoObject(@NonNull Signature signature) { 240 super(signature); 241 } 242 CryptoObject(@onNull Cipher cipher)243 public CryptoObject(@NonNull Cipher cipher) { 244 super(cipher); 245 } 246 CryptoObject(@onNull Mac mac)247 public CryptoObject(@NonNull Mac mac) { 248 super(mac); 249 } 250 251 /** 252 * Get {@link Signature} object. 253 * @return {@link Signature} object or null if this doesn't contain one. 254 */ getSignature()255 public Signature getSignature() { 256 return super.getSignature(); 257 } 258 259 /** 260 * Get {@link Cipher} object. 261 * @return {@link Cipher} object or null if this doesn't contain one. 262 */ getCipher()263 public Cipher getCipher() { 264 return super.getCipher(); 265 } 266 267 /** 268 * Get {@link Mac} object. 269 * @return {@link Mac} object or null if this doesn't contain one. 270 */ getMac()271 public Mac getMac() { 272 return super.getMac(); 273 } 274 275 /** 276 * Get {@link IdentityCredential} object. 277 * @return {@link IdentityCredential} object or null if this doesn't contain one. 278 * @hide 279 * @deprecated Use {@link PresentationSession} instead of {@link IdentityCredential}. 280 */ 281 @Deprecated getIdentityCredential()282 public IdentityCredential getIdentityCredential() { 283 return super.getIdentityCredential(); 284 } 285 286 /** 287 * Get {@link PresentationSession} object. 288 * @return {@link PresentationSession} object or null if this doesn't contain one. 289 * @hide 290 */ getPresentationSession()291 public PresentationSession getPresentationSession() { 292 return super.getPresentationSession(); 293 } 294 } 295 296 /** 297 * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject, 298 * CancellationSignal, int, AuthenticationCallback, Handler)}. 299 * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationResult} 300 */ 301 @Deprecated 302 public static class AuthenticationResult { 303 private Fingerprint mFingerprint; 304 private CryptoObject mCryptoObject; 305 private int mUserId; 306 private boolean mIsStrongBiometric; 307 308 /** 309 * Authentication result 310 * 311 * @param crypto the crypto object 312 * @param fingerprint the recognized fingerprint data, if allowed. 313 * @hide 314 */ AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint, int userId, boolean isStrongBiometric)315 public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint, int userId, 316 boolean isStrongBiometric) { 317 mCryptoObject = crypto; 318 mFingerprint = fingerprint; 319 mUserId = userId; 320 mIsStrongBiometric = isStrongBiometric; 321 } 322 323 /** 324 * Obtain the crypto object associated with this transaction 325 * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject, 326 * CancellationSignal, int, AuthenticationCallback, Handler)}. 327 */ getCryptoObject()328 public CryptoObject getCryptoObject() { return mCryptoObject; } 329 330 /** 331 * Obtain the Fingerprint associated with this operation. Applications are strongly 332 * discouraged from associating specific fingers with specific applications or operations. 333 * 334 * @hide 335 */ 336 @UnsupportedAppUsage getFingerprint()337 public Fingerprint getFingerprint() { return mFingerprint; } 338 339 /** 340 * Obtain the userId for which this fingerprint was authenticated. 341 * @hide 342 */ getUserId()343 public int getUserId() { return mUserId; } 344 345 /** 346 * Check whether the strength of the fingerprint modality associated with this operation is 347 * strong (i.e. not weak or convenience). 348 * @hide 349 */ isStrongBiometric()350 public boolean isStrongBiometric() { 351 return mIsStrongBiometric; 352 } 353 } 354 355 /** 356 * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject, 357 * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link 358 * FingerprintManager#authenticate(CryptoObject, CancellationSignal, 359 * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to 360 * fingerprint events. 361 * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationCallback} 362 */ 363 @Deprecated 364 public static abstract class AuthenticationCallback 365 extends BiometricAuthenticator.AuthenticationCallback { 366 /** 367 * Called when an unrecoverable error has been encountered and the operation is complete. 368 * No further callbacks will be made on this object. 369 * @param errorCode An integer identifying the error message 370 * @param errString A human-readable error string that can be shown in UI 371 */ 372 @Override onAuthenticationError(int errorCode, CharSequence errString)373 public void onAuthenticationError(int errorCode, CharSequence errString) { } 374 375 /** 376 * Called when a recoverable error has been encountered during authentication. The help 377 * string is provided to give the user guidance for what went wrong, such as 378 * "Sensor dirty, please clean it." 379 * @param helpCode An integer identifying the error message 380 * @param helpString A human-readable string that can be shown in UI 381 */ 382 @Override onAuthenticationHelp(int helpCode, CharSequence helpString)383 public void onAuthenticationHelp(int helpCode, CharSequence helpString) { } 384 385 /** 386 * Called when a fingerprint is recognized. 387 * @param result An object containing authentication-related data 388 */ onAuthenticationSucceeded(AuthenticationResult result)389 public void onAuthenticationSucceeded(AuthenticationResult result) { } 390 391 /** 392 * Called when a fingerprint is valid but not recognized. 393 */ 394 @Override onAuthenticationFailed()395 public void onAuthenticationFailed() { } 396 397 /** 398 * Called when a fingerprint image has been acquired, but wasn't processed yet. 399 * 400 * @param acquireInfo one of FINGERPRINT_ACQUIRED_* constants 401 * @hide 402 */ 403 @Override onAuthenticationAcquired(int acquireInfo)404 public void onAuthenticationAcquired(int acquireInfo) {} 405 406 /** 407 * Invoked for under-display fingerprint sensors when a touch has been detected on the 408 * sensor area. 409 * @hide 410 */ onUdfpsPointerDown(int sensorId)411 public void onUdfpsPointerDown(int sensorId) {} 412 413 /** 414 * Invoked for under-display fingerprint sensors when a touch has been removed from the 415 * sensor area. 416 * @hide 417 */ onUdfpsPointerUp(int sensorId)418 public void onUdfpsPointerUp(int sensorId) {} 419 } 420 421 /** 422 * Callback structure provided for {@link #detectFingerprint(CancellationSignal, 423 * FingerprintDetectionCallback, int, Surface)}. 424 * @hide 425 */ 426 public interface FingerprintDetectionCallback { 427 /** 428 * Invoked when a fingerprint has been detected. 429 */ onFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric)430 void onFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric); 431 } 432 433 /** 434 * Callback structure provided to {@link FingerprintManager#enroll(byte[], CancellationSignal, 435 * int, EnrollmentCallback)} must provide an implementation of this for listening to 436 * fingerprint events. 437 * 438 * @hide 439 */ 440 public static abstract class EnrollmentCallback { 441 /** 442 * Called when an unrecoverable error has been encountered and the operation is complete. 443 * No further callbacks will be made on this object. 444 * @param errMsgId An integer identifying the error message 445 * @param errString A human-readable error string that can be shown in UI 446 */ onEnrollmentError(int errMsgId, CharSequence errString)447 public void onEnrollmentError(int errMsgId, CharSequence errString) { } 448 449 /** 450 * Called when a recoverable error has been encountered during enrollment. The help 451 * string is provided to give the user guidance for what went wrong, such as 452 * "Sensor dirty, please clean it" or what they need to do next, such as 453 * "Touch sensor again." 454 * @param helpMsgId An integer identifying the error message 455 * @param helpString A human-readable string that can be shown in UI 456 */ onEnrollmentHelp(int helpMsgId, CharSequence helpString)457 public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { } 458 459 /** 460 * Called as each enrollment step progresses. Enrollment is considered complete when 461 * remaining reaches 0. This function will not be called if enrollment fails. See 462 * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} 463 * @param remaining The number of remaining steps 464 */ onEnrollmentProgress(int remaining)465 public void onEnrollmentProgress(int remaining) { } 466 } 467 468 /** 469 * Callback structure provided to {@link #remove}. Users of {@link FingerprintManager} may 470 * optionally provide an implementation of this to 471 * {@link #remove(Fingerprint, int, RemovalCallback)} for listening to fingerprint template 472 * removal events. 473 * 474 * @hide 475 */ 476 public static abstract class RemovalCallback { 477 /** 478 * Called when the given fingerprint can't be removed. 479 * @param fp The fingerprint that the call attempted to remove 480 * @param errMsgId An associated error message id 481 * @param errString An error message indicating why the fingerprint id can't be removed 482 */ onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString)483 public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { } 484 485 /** 486 * Called when a given fingerprint is successfully removed. 487 * @param fp The fingerprint template that was removed. 488 * @param remaining The number of fingerprints yet to be removed in this operation. If 489 * {@link #remove} is called on one fingerprint, this should be 0. If 490 * {@link #remove} is called on a group, this should be the number of remaining 491 * fingerprints in the group, and 0 after the last fingerprint is removed. 492 */ onRemovalSucceeded(@ullable Fingerprint fp, int remaining)493 public void onRemovalSucceeded(@Nullable Fingerprint fp, int remaining) { } 494 } 495 496 /** 497 * @hide 498 */ 499 public static abstract class LockoutResetCallback { 500 501 /** 502 * Called when lockout period expired and clients are allowed to listen for fingerprint 503 * again. 504 */ onLockoutReset(int sensorId)505 public void onLockoutReset(int sensorId) { } 506 } 507 508 /** 509 * Callbacks for generate challenge operations. 510 * 511 * @hide 512 */ 513 public interface GenerateChallengeCallback { 514 /** Called when a challenged has been generated. */ onChallengeGenerated(int sensorId, int userId, long challenge)515 void onChallengeGenerated(int sensorId, int userId, long challenge); 516 } 517 518 /** 519 * Use the provided handler thread for events. 520 * @param handler 521 */ useHandler(Handler handler)522 private void useHandler(Handler handler) { 523 if (handler != null) { 524 mHandler = new MyHandler(handler.getLooper()); 525 } else if (mHandler.getLooper() != mContext.getMainLooper()) { 526 mHandler = new MyHandler(mContext.getMainLooper()); 527 } 528 } 529 530 /** 531 * Request authentication of a crypto object. This call warms up the fingerprint hardware 532 * and starts scanning for a fingerprint. It terminates when 533 * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or 534 * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at 535 * which point the object is no longer valid. The operation can be canceled by using the 536 * provided cancel object. 537 * 538 * @param crypto object associated with the call or null if none required. 539 * @param cancel an object that can be used to cancel authentication 540 * @param flags optional flags; should be 0 541 * @param callback an object to receive authentication events 542 * @param handler an optional handler to handle callback events 543 * 544 * @throws IllegalArgumentException if the crypto operation is not supported or is not backed 545 * by <a href="{@docRoot}training/articles/keystore.html">Android Keystore 546 * facility</a>. 547 * @throws IllegalStateException if the crypto primitive is not initialized. 548 * @deprecated See {@link BiometricPrompt#authenticate(CancellationSignal, Executor, 549 * BiometricPrompt.AuthenticationCallback)} and {@link BiometricPrompt#authenticate( 550 * BiometricPrompt.CryptoObject, CancellationSignal, Executor, 551 * BiometricPrompt.AuthenticationCallback)} 552 */ 553 @Deprecated 554 @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT}) authenticate(@ullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler)555 public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, 556 int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) { 557 authenticate(crypto, cancel, callback, handler, SENSOR_ID_ANY, mContext.getUserId(), flags); 558 } 559 560 /** 561 * Per-user version of authenticate. 562 * @hide 563 */ 564 @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT}) authenticate(@ullable CryptoObject crypto, @Nullable CancellationSignal cancel, @NonNull AuthenticationCallback callback, Handler handler, int userId)565 public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, 566 @NonNull AuthenticationCallback callback, Handler handler, int userId) { 567 authenticate(crypto, cancel, callback, handler, SENSOR_ID_ANY, userId, 0 /* flags */); 568 } 569 570 /** 571 * Per-user and per-sensor version of authenticate. 572 * @hide 573 */ 574 @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT}) authenticate(@ullable CryptoObject crypto, @Nullable CancellationSignal cancel, @NonNull AuthenticationCallback callback, Handler handler, int sensorId, int userId, int flags)575 public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, 576 @NonNull AuthenticationCallback callback, Handler handler, int sensorId, int userId, 577 int flags) { 578 579 FrameworkStatsLog.write(FrameworkStatsLog.AUTH_DEPRECATED_API_USED, 580 AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE, 581 mContext.getApplicationInfo().uid, 582 mContext.getApplicationInfo().targetSdkVersion); 583 584 if (callback == null) { 585 throw new IllegalArgumentException("Must supply an authentication callback"); 586 } 587 588 if (cancel != null && cancel.isCanceled()) { 589 Slog.w(TAG, "authentication already canceled"); 590 return; 591 } 592 593 final boolean ignoreEnrollmentState = flags == 0 ? false : true; 594 595 if (mService != null) { 596 try { 597 useHandler(handler); 598 mAuthenticationCallback = callback; 599 mCryptoObject = crypto; 600 final long operationId = crypto != null ? crypto.getOpId() : 0; 601 final long authId = 602 mService.authenticate( 603 mToken, 604 operationId, 605 sensorId, 606 userId, 607 mServiceReceiver, 608 mContext.getOpPackageName(), 609 mContext.getAttributionTag(), 610 ignoreEnrollmentState); 611 if (cancel != null) { 612 cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId)); 613 } 614 } catch (RemoteException e) { 615 Slog.w(TAG, "Remote exception while authenticating: ", e); 616 // Though this may not be a hardware issue, it will cause apps to give up or try 617 // again later. 618 callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 619 getErrorString(mContext, FINGERPRINT_ERROR_HW_UNAVAILABLE, 620 0 /* vendorCode */)); 621 } 622 } 623 } 624 625 /** 626 * Uses the fingerprint hardware to detect for the presence of a finger, without giving details 627 * about accept/reject/lockout. 628 * @hide 629 */ 630 @RequiresPermission(USE_BIOMETRIC_INTERNAL) detectFingerprint(@onNull CancellationSignal cancel, @NonNull FingerprintDetectionCallback callback, int userId)631 public void detectFingerprint(@NonNull CancellationSignal cancel, 632 @NonNull FingerprintDetectionCallback callback, int userId) { 633 if (mService == null) { 634 return; 635 } 636 637 if (cancel.isCanceled()) { 638 Slog.w(TAG, "Detection already cancelled"); 639 return; 640 } 641 642 mFingerprintDetectionCallback = callback; 643 644 try { 645 final long authId = mService.detectFingerprint(mToken, userId, mServiceReceiver, 646 mContext.getOpPackageName()); 647 cancel.setOnCancelListener(new OnFingerprintDetectionCancelListener(authId)); 648 } catch (RemoteException e) { 649 Slog.w(TAG, "Remote exception when requesting finger detect", e); 650 } 651 } 652 653 /** 654 * Request fingerprint enrollment. This call warms up the fingerprint hardware 655 * and starts scanning for fingerprints. Progress will be indicated by callbacks to the 656 * {@link EnrollmentCallback} object. It terminates when 657 * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or 658 * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at 659 * which point the object is no longer valid. The operation can be canceled by using the 660 * provided cancel object. 661 * @param token a unique token provided by a recent creation or verification of device 662 * credentials (e.g. pin, pattern or password). 663 * @param cancel an object that can be used to cancel enrollment 664 * @param userId the user to whom this fingerprint will belong to 665 * @param callback an object to receive enrollment events 666 * @param shouldLogMetrics a flag that indicates if enrollment failure/success metrics 667 * should be logged. 668 * @hide 669 */ 670 @RequiresPermission(MANAGE_FINGERPRINT) enroll(byte [] hardwareAuthToken, CancellationSignal cancel, int userId, EnrollmentCallback callback, @EnrollReason int enrollReason)671 public void enroll(byte [] hardwareAuthToken, CancellationSignal cancel, int userId, 672 EnrollmentCallback callback, @EnrollReason int enrollReason) { 673 if (userId == UserHandle.USER_CURRENT) { 674 userId = getCurrentUserId(); 675 } 676 if (callback == null) { 677 throw new IllegalArgumentException("Must supply an enrollment callback"); 678 } 679 680 if (cancel != null && cancel.isCanceled()) { 681 Slog.w(TAG, "enrollment already canceled"); 682 return; 683 } 684 685 if (mService != null) { 686 try { 687 mEnrollmentCallback = callback; 688 final long enrollId = mService.enroll(mToken, hardwareAuthToken, userId, 689 mServiceReceiver, mContext.getOpPackageName(), enrollReason); 690 if (cancel != null) { 691 cancel.setOnCancelListener(new OnEnrollCancelListener(enrollId)); 692 } 693 } catch (RemoteException e) { 694 Slog.w(TAG, "Remote exception in enroll: ", e); 695 // Though this may not be a hardware issue, it will cause apps to give up or try 696 // again later. 697 callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 698 getErrorString(mContext, FINGERPRINT_ERROR_HW_UNAVAILABLE, 699 0 /* vendorCode */)); 700 } 701 } 702 } 703 704 /** 705 * Generates a unique random challenge in the TEE. A typical use case is to have it wrapped in a 706 * HardwareAuthenticationToken, minted by Gatekeeper upon PIN/Pattern/Password verification. 707 * The HardwareAuthenticationToken can then be sent to the biometric HAL together with a 708 * request to perform sensitive operation(s) (for example enroll), represented by the challenge. 709 * Doing this ensures that a the sensitive operation cannot be performed unless the user has 710 * entered confirmed PIN/Pattern/Password. 711 * 712 * @see com.android.server.locksettings.LockSettingsService 713 * 714 * @hide 715 */ 716 @RequiresPermission(MANAGE_FINGERPRINT) generateChallenge(int sensorId, int userId, GenerateChallengeCallback callback)717 public void generateChallenge(int sensorId, int userId, GenerateChallengeCallback callback) { 718 if (mService != null) try { 719 mGenerateChallengeCallback = callback; 720 mService.generateChallenge(mToken, sensorId, userId, mServiceReceiver, 721 mContext.getOpPackageName()); 722 } catch (RemoteException e) { 723 throw e.rethrowFromSystemServer(); 724 } 725 } 726 727 /** 728 * Same as {@link #generateChallenge(int, GenerateChallengeCallback)}, but assumes the first 729 * enumerated sensor. 730 * @hide 731 */ 732 @RequiresPermission(MANAGE_FINGERPRINT) generateChallenge(int userId, GenerateChallengeCallback callback)733 public void generateChallenge(int userId, GenerateChallengeCallback callback) { 734 final FingerprintSensorPropertiesInternal sensorProps = getFirstFingerprintSensor(); 735 if (sensorProps == null) { 736 Slog.e(TAG, "No sensors"); 737 return; 738 } 739 generateChallenge(sensorProps.sensorId, userId, callback); 740 } 741 742 /** 743 * Revokes the specified challenge. 744 * @hide 745 */ 746 @RequiresPermission(MANAGE_FINGERPRINT) revokeChallenge(int userId, long challenge)747 public void revokeChallenge(int userId, long challenge) { 748 if (mService != null) { 749 try { 750 final FingerprintSensorPropertiesInternal sensorProps = getFirstFingerprintSensor(); 751 if (sensorProps == null) { 752 Slog.e(TAG, "No sensors"); 753 return; 754 } 755 mService.revokeChallenge(mToken, sensorProps.sensorId, userId, 756 mContext.getOpPackageName(), challenge); 757 } catch (RemoteException e) { 758 throw e.rethrowFromSystemServer(); 759 } 760 } 761 } 762 763 /** 764 * Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password) 765 * 766 * @param sensorId Sensor ID that this operation takes effect for 767 * @param userId User ID that this operation takes effect for. 768 * @param hardwareAuthToken An opaque token returned by password confirmation. 769 * @hide 770 */ 771 @RequiresPermission(RESET_FINGERPRINT_LOCKOUT) resetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken)772 public void resetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken) { 773 if (mService != null) { 774 try { 775 mService.resetLockout(mToken, sensorId, userId, hardwareAuthToken, 776 mContext.getOpPackageName()); 777 } catch (RemoteException e) { 778 throw e.rethrowFromSystemServer(); 779 } 780 } 781 } 782 783 /** 784 * Remove given fingerprint template from fingerprint hardware and/or protected storage. 785 * @param fp the fingerprint item to remove 786 * @param userId the user who this fingerprint belongs to 787 * @param callback an optional callback to verify that fingerprint templates have been 788 * successfully removed. May be null of no callback is required. 789 * 790 * @hide 791 */ 792 @RequiresPermission(MANAGE_FINGERPRINT) remove(Fingerprint fp, int userId, RemovalCallback callback)793 public void remove(Fingerprint fp, int userId, RemovalCallback callback) { 794 if (mService != null) try { 795 mRemovalCallback = callback; 796 mRemoveTracker = new RemoveTracker(RemoveTracker.REMOVE_SINGLE, fp); 797 mService.remove(mToken, fp.getBiometricId(), userId, mServiceReceiver, 798 mContext.getOpPackageName()); 799 } catch (RemoteException e) { 800 throw e.rethrowFromSystemServer(); 801 } 802 } 803 804 /** 805 * Removes all face templates for the given user. 806 * @hide 807 */ 808 @RequiresPermission(MANAGE_FINGERPRINT) removeAll(int userId, @NonNull RemovalCallback callback)809 public void removeAll(int userId, @NonNull RemovalCallback callback) { 810 if (mService != null) { 811 try { 812 mRemovalCallback = callback; 813 mRemoveTracker = new RemoveTracker(RemoveTracker.REMOVE_ALL, null /* fp */); 814 mService.removeAll(mToken, userId, mServiceReceiver, mContext.getOpPackageName()); 815 } catch (RemoteException e) { 816 throw e.rethrowFromSystemServer(); 817 } 818 } 819 } 820 821 /** 822 * Renames the given fingerprint template 823 * @param fpId the fingerprint id 824 * @param userId the user who this fingerprint belongs to 825 * @param newName the new name 826 * 827 * @hide 828 */ 829 @RequiresPermission(MANAGE_FINGERPRINT) rename(int fpId, int userId, String newName)830 public void rename(int fpId, int userId, String newName) { 831 // Renames the given fpId 832 if (mService != null) { 833 try { 834 mService.rename(fpId, userId, newName); 835 } catch (RemoteException e) { 836 throw e.rethrowFromSystemServer(); 837 } 838 } else { 839 Slog.w(TAG, "rename(): Service not connected!"); 840 } 841 } 842 843 /** 844 * Obtain the list of enrolled fingerprints templates. 845 * @return list of current fingerprint items 846 * 847 * @hide 848 */ 849 @RequiresPermission(USE_FINGERPRINT) 850 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getEnrolledFingerprints(int userId)851 public List<Fingerprint> getEnrolledFingerprints(int userId) { 852 if (mService != null) try { 853 return mService.getEnrolledFingerprints( 854 userId, mContext.getOpPackageName(), mContext.getAttributionTag()); 855 } catch (RemoteException e) { 856 throw e.rethrowFromSystemServer(); 857 } 858 return null; 859 } 860 861 /** 862 * Obtain the list of enrolled fingerprints templates. 863 * @return list of current fingerprint items 864 * 865 * @hide 866 */ 867 @RequiresPermission(USE_FINGERPRINT) 868 @UnsupportedAppUsage getEnrolledFingerprints()869 public List<Fingerprint> getEnrolledFingerprints() { 870 return getEnrolledFingerprints(mContext.getUserId()); 871 } 872 873 /** 874 * @hide 875 */ hasEnrolledTemplates()876 public boolean hasEnrolledTemplates() { 877 return hasEnrolledFingerprints(); 878 } 879 880 /** 881 * @hide 882 */ hasEnrolledTemplates(int userId)883 public boolean hasEnrolledTemplates(int userId) { 884 return hasEnrolledFingerprints(userId); 885 } 886 887 /** 888 * @hide 889 */ 890 @RequiresPermission(USE_BIOMETRIC_INTERNAL) setUdfpsOverlayController(@onNull IUdfpsOverlayController controller)891 public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) { 892 if (mService == null) { 893 Slog.w(TAG, "setUdfpsOverlayController: no fingerprint service"); 894 return; 895 } 896 897 try { 898 mService.setUdfpsOverlayController(controller); 899 } catch (RemoteException e) { 900 throw e.rethrowFromSystemServer(); 901 } 902 } 903 904 /** 905 * @hide 906 */ 907 @RequiresPermission(USE_BIOMETRIC_INTERNAL) setSidefpsController(@onNull ISidefpsController controller)908 public void setSidefpsController(@NonNull ISidefpsController controller) { 909 if (mService == null) { 910 Slog.w(TAG, "setSidefpsController: no fingerprint service"); 911 return; 912 } 913 914 try { 915 mService.setSidefpsController(controller); 916 } catch (RemoteException e) { 917 throw e.rethrowFromSystemServer(); 918 } 919 } 920 921 /** 922 * Forwards BiometricStateListener to FingerprintService 923 * @param listener new BiometricStateListener being added 924 * @hide 925 */ registerBiometricStateListener(@onNull BiometricStateListener listener)926 public void registerBiometricStateListener(@NonNull BiometricStateListener listener) { 927 try { 928 mService.registerBiometricStateListener(listener); 929 } catch (RemoteException e) { 930 throw e.rethrowFromSystemServer(); 931 } 932 } 933 934 /** 935 * @hide 936 */ 937 @RequiresPermission(USE_BIOMETRIC_INTERNAL) onPointerDown(long requestId, int sensorId, int x, int y, float minor, float major)938 public void onPointerDown(long requestId, int sensorId, int x, int y, 939 float minor, float major) { 940 if (mService == null) { 941 Slog.w(TAG, "onPointerDown: no fingerprint service"); 942 return; 943 } 944 945 try { 946 mService.onPointerDown(requestId, sensorId, x, y, minor, major); 947 } catch (RemoteException e) { 948 throw e.rethrowFromSystemServer(); 949 } 950 } 951 952 /** 953 * @hide 954 */ 955 @RequiresPermission(USE_BIOMETRIC_INTERNAL) onPointerUp(long requestId, int sensorId)956 public void onPointerUp(long requestId, int sensorId) { 957 if (mService == null) { 958 Slog.w(TAG, "onPointerUp: no fingerprint service"); 959 return; 960 } 961 962 try { 963 mService.onPointerUp(requestId, sensorId); 964 } catch (RemoteException e) { 965 throw e.rethrowFromSystemServer(); 966 } 967 } 968 969 /** 970 * TODO(b/218388821): The parameter list should be replaced with PointerContext. 971 * @hide 972 */ 973 @RequiresPermission(USE_BIOMETRIC_INTERNAL) onPointerDown( long requestId, int sensorId, int pointerId, float x, float y, float minor, float major, float orientation, long time, long gestureStart, boolean isAod)974 public void onPointerDown( 975 long requestId, 976 int sensorId, 977 int pointerId, 978 float x, 979 float y, 980 float minor, 981 float major, 982 float orientation, 983 long time, 984 long gestureStart, 985 boolean isAod) { 986 if (mService == null) { 987 Slog.w(TAG, "onPointerDown: no fingerprint service"); 988 return; 989 } 990 991 // TODO(b/218388821): Propagate all the parameters to FingerprintService. 992 Slog.e(TAG, "onPointerDown: not implemented!"); 993 } 994 995 /** 996 * TODO(b/218388821): The parameter list should be replaced with PointerContext. 997 * @hide 998 */ 999 @RequiresPermission(USE_BIOMETRIC_INTERNAL) onPointerUp( long requestId, int sensorId, int pointerId, float x, float y, float minor, float major, float orientation, long time, long gestureStart, boolean isAod)1000 public void onPointerUp( 1001 long requestId, 1002 int sensorId, 1003 int pointerId, 1004 float x, 1005 float y, 1006 float minor, 1007 float major, 1008 float orientation, 1009 long time, 1010 long gestureStart, 1011 boolean isAod) { 1012 if (mService == null) { 1013 Slog.w(TAG, "onPointerUp: no fingerprint service"); 1014 return; 1015 } 1016 1017 // TODO(b/218388821): Propagate all the parameters to FingerprintService. 1018 Slog.e(TAG, "onPointerUp: not implemented!"); 1019 } 1020 1021 /** 1022 * @hide 1023 */ 1024 @RequiresPermission(USE_BIOMETRIC_INTERNAL) onUiReady(long requestId, int sensorId)1025 public void onUiReady(long requestId, int sensorId) { 1026 if (mService == null) { 1027 Slog.w(TAG, "onUiReady: no fingerprint service"); 1028 return; 1029 } 1030 1031 try { 1032 mService.onUiReady(requestId, sensorId); 1033 } catch (RemoteException e) { 1034 throw e.rethrowFromSystemServer(); 1035 } 1036 } 1037 1038 /** 1039 * This is triggered by SideFpsEventHandler 1040 * @hide 1041 */ 1042 @RequiresPermission(USE_BIOMETRIC_INTERNAL) onPowerPressed()1043 public void onPowerPressed() { 1044 Slog.i(TAG, "onPowerPressed"); 1045 mHandler.obtainMessage(MSG_POWER_BUTTON_PRESSED).sendToTarget(); 1046 } 1047 1048 /** 1049 * Determine if there is at least one fingerprint enrolled. 1050 * 1051 * @return true if at least one fingerprint is enrolled, false otherwise 1052 * @deprecated See {@link BiometricPrompt} and 1053 * {@link FingerprintManager#FINGERPRINT_ERROR_NO_FINGERPRINTS} 1054 */ 1055 @Deprecated 1056 @RequiresPermission(USE_FINGERPRINT) hasEnrolledFingerprints()1057 public boolean hasEnrolledFingerprints() { 1058 FrameworkStatsLog.write(FrameworkStatsLog.AUTH_DEPRECATED_API_USED, 1059 AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_HAS_ENROLLED_FINGERPRINTS, 1060 mContext.getApplicationInfo().uid, 1061 mContext.getApplicationInfo().targetSdkVersion); 1062 1063 return hasEnrolledFingerprints(UserHandle.myUserId()); 1064 } 1065 1066 /** 1067 * @hide 1068 */ 1069 @RequiresPermission(allOf = { 1070 USE_FINGERPRINT, 1071 INTERACT_ACROSS_USERS}) hasEnrolledFingerprints(int userId)1072 public boolean hasEnrolledFingerprints(int userId) { 1073 if (mService != null) try { 1074 return mService.hasEnrolledFingerprintsDeprecated( 1075 userId, mContext.getOpPackageName(), mContext.getAttributionTag()); 1076 } catch (RemoteException e) { 1077 throw e.rethrowFromSystemServer(); 1078 } 1079 return false; 1080 } 1081 1082 /** 1083 * Determine if fingerprint hardware is present and functional. 1084 * 1085 * @return true if hardware is present and functional, false otherwise. 1086 * @deprecated See {@link BiometricPrompt} and 1087 * {@link FingerprintManager#FINGERPRINT_ERROR_HW_UNAVAILABLE} 1088 */ 1089 @Deprecated 1090 @RequiresPermission(USE_FINGERPRINT) isHardwareDetected()1091 public boolean isHardwareDetected() { 1092 FrameworkStatsLog.write(FrameworkStatsLog.AUTH_DEPRECATED_API_USED, 1093 AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_IS_HARDWARE_DETECTED, 1094 mContext.getApplicationInfo().uid, 1095 mContext.getApplicationInfo().targetSdkVersion); 1096 1097 if (mService != null) { 1098 try { 1099 return mService.isHardwareDetectedDeprecated( 1100 mContext.getOpPackageName(), mContext.getAttributionTag()); 1101 } catch (RemoteException e) { 1102 throw e.rethrowFromSystemServer(); 1103 } 1104 } else { 1105 Slog.w(TAG, "isFingerprintHardwareDetected(): Service not connected!"); 1106 } 1107 return false; 1108 } 1109 1110 /** 1111 * Get statically configured sensor properties. 1112 * @hide 1113 */ 1114 @RequiresPermission(USE_BIOMETRIC_INTERNAL) 1115 @NonNull getSensorPropertiesInternal()1116 public List<FingerprintSensorPropertiesInternal> getSensorPropertiesInternal() { 1117 try { 1118 if (mService == null) { 1119 return new ArrayList<>(); 1120 } 1121 return mService.getSensorPropertiesInternal(mContext.getOpPackageName()); 1122 } catch (RemoteException e) { 1123 throw e.rethrowFromSystemServer(); 1124 } 1125 } 1126 1127 /** 1128 * Returns whether the device has a power button fingerprint sensor. 1129 * @return boolean indicating whether power button is fingerprint sensor 1130 * @hide 1131 */ isPowerbuttonFps()1132 public boolean isPowerbuttonFps() { 1133 final FingerprintSensorPropertiesInternal sensorProps = getFirstFingerprintSensor(); 1134 return sensorProps.sensorType == TYPE_POWER_BUTTON; 1135 } 1136 1137 /** 1138 * Adds a callback that gets called when the service registers all of the fingerprint 1139 * authenticators (HALs). 1140 * 1141 * If the fingerprint authenticators are already registered when the callback is added, the 1142 * callback is invoked immediately. 1143 * 1144 * The callback is automatically removed after it's invoked. 1145 * 1146 * @hide 1147 */ 1148 @RequiresPermission(USE_BIOMETRIC_INTERNAL) addAuthenticatorsRegisteredCallback( IFingerprintAuthenticatorsRegisteredCallback callback)1149 public void addAuthenticatorsRegisteredCallback( 1150 IFingerprintAuthenticatorsRegisteredCallback callback) { 1151 if (mService != null) { 1152 try { 1153 mService.addAuthenticatorsRegisteredCallback(callback); 1154 } catch (RemoteException e) { 1155 throw e.rethrowFromSystemServer(); 1156 } 1157 } else { 1158 Slog.w(TAG, "addProvidersAvailableCallback(): Service not connected!"); 1159 } 1160 } 1161 1162 /** 1163 * @hide 1164 */ 1165 @RequiresPermission(USE_BIOMETRIC_INTERNAL) 1166 @BiometricConstants.LockoutMode getLockoutModeForUser(int sensorId, int userId)1167 public int getLockoutModeForUser(int sensorId, int userId) { 1168 if (mService != null) { 1169 try { 1170 return mService.getLockoutModeForUser(sensorId, userId); 1171 } catch (RemoteException e) { 1172 e.rethrowFromSystemServer(); 1173 } 1174 } 1175 return BIOMETRIC_LOCKOUT_NONE; 1176 } 1177 1178 /** 1179 * @hide 1180 */ addLockoutResetCallback(final LockoutResetCallback callback)1181 public void addLockoutResetCallback(final LockoutResetCallback callback) { 1182 if (mService != null) { 1183 try { 1184 final PowerManager powerManager = mContext.getSystemService(PowerManager.class); 1185 mService.addLockoutResetCallback( 1186 new IBiometricServiceLockoutResetCallback.Stub() { 1187 1188 @Override 1189 public void onLockoutReset(int sensorId, IRemoteCallback serverCallback) 1190 throws RemoteException { 1191 try { 1192 final PowerManager.WakeLock wakeLock = powerManager.newWakeLock( 1193 PowerManager.PARTIAL_WAKE_LOCK, "lockoutResetCallback"); 1194 wakeLock.acquire(); 1195 mHandler.post(() -> { 1196 try { 1197 callback.onLockoutReset(sensorId); 1198 } finally { 1199 wakeLock.release(); 1200 } 1201 }); 1202 } finally { 1203 serverCallback.sendResult(null /* data */); 1204 } 1205 } 1206 }, mContext.getOpPackageName()); 1207 } catch (RemoteException e) { 1208 throw e.rethrowFromSystemServer(); 1209 } 1210 } else { 1211 Slog.w(TAG, "addLockoutResetCallback(): Service not connected!"); 1212 } 1213 } 1214 1215 private class MyHandler extends Handler { MyHandler(Context context)1216 private MyHandler(Context context) { 1217 super(context.getMainLooper()); 1218 } 1219 MyHandler(Looper looper)1220 private MyHandler(Looper looper) { 1221 super(looper); 1222 } 1223 1224 @Override handleMessage(android.os.Message msg)1225 public void handleMessage(android.os.Message msg) { 1226 switch (msg.what) { 1227 case MSG_ENROLL_RESULT: 1228 sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */); 1229 break; 1230 case MSG_ACQUIRED: 1231 sendAcquiredResult(msg.arg1 /* acquire info */, 1232 msg.arg2 /* vendorCode */); 1233 break; 1234 case MSG_AUTHENTICATION_SUCCEEDED: 1235 sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */, 1236 msg.arg2 == 1 /* isStrongBiometric */); 1237 break; 1238 case MSG_AUTHENTICATION_FAILED: 1239 sendAuthenticatedFailed(); 1240 break; 1241 case MSG_ERROR: 1242 sendErrorResult(msg.arg1 /* errMsgId */, msg.arg2 /* vendorCode */); 1243 break; 1244 case MSG_REMOVED: 1245 sendRemovedResult((Fingerprint) msg.obj, msg.arg1 /* remaining */); 1246 break; 1247 case MSG_CHALLENGE_GENERATED: 1248 sendChallengeGenerated(msg.arg1 /* sensorId */, msg.arg2 /* userId */, 1249 (long) msg.obj /* challenge */); 1250 break; 1251 case MSG_FINGERPRINT_DETECTED: 1252 sendFingerprintDetected(msg.arg1 /* sensorId */, msg.arg2 /* userId */, 1253 (boolean) msg.obj /* isStrongBiometric */); 1254 break; 1255 case MSG_UDFPS_POINTER_DOWN: 1256 sendUdfpsPointerDown(msg.arg1 /* sensorId */); 1257 break; 1258 case MSG_UDFPS_POINTER_UP: 1259 sendUdfpsPointerUp(msg.arg1 /* sensorId */); 1260 break; 1261 case MSG_POWER_BUTTON_PRESSED: 1262 sendPowerPressed(); 1263 break; 1264 default: 1265 Slog.w(TAG, "Unknown message: " + msg.what); 1266 1267 } 1268 } 1269 } 1270 sendRemovedResult(Fingerprint fingerprint, int remaining)1271 private void sendRemovedResult(Fingerprint fingerprint, int remaining) { 1272 if (mRemovalCallback == null) { 1273 return; 1274 } 1275 1276 if (mRemoveTracker == null) { 1277 Slog.w(TAG, "Removal tracker is null"); 1278 return; 1279 } 1280 1281 if (mRemoveTracker.mRemoveRequest == RemoveTracker.REMOVE_SINGLE) { 1282 if (fingerprint == null) { 1283 Slog.e(TAG, "Received MSG_REMOVED, but fingerprint is null"); 1284 return; 1285 } 1286 1287 if (mRemoveTracker.mSingleFingerprint == null) { 1288 Slog.e(TAG, "Missing fingerprint"); 1289 return; 1290 } 1291 1292 final int fingerId = fingerprint.getBiometricId(); 1293 int reqFingerId = mRemoveTracker.mSingleFingerprint.getBiometricId(); 1294 if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) { 1295 Slog.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId); 1296 return; 1297 } 1298 } 1299 1300 mRemovalCallback.onRemovalSucceeded(fingerprint, remaining); 1301 } 1302 sendEnrollResult(Fingerprint fp, int remaining)1303 private void sendEnrollResult(Fingerprint fp, int remaining) { 1304 if (mEnrollmentCallback != null) { 1305 mEnrollmentCallback.onEnrollmentProgress(remaining); 1306 } 1307 } 1308 sendAuthenticatedSucceeded(Fingerprint fp, int userId, boolean isStrongBiometric)1309 private void sendAuthenticatedSucceeded(Fingerprint fp, int userId, boolean isStrongBiometric) { 1310 if (mAuthenticationCallback != null) { 1311 final AuthenticationResult result = 1312 new AuthenticationResult(mCryptoObject, fp, userId, isStrongBiometric); 1313 mAuthenticationCallback.onAuthenticationSucceeded(result); 1314 } 1315 } 1316 sendAuthenticatedFailed()1317 private void sendAuthenticatedFailed() { 1318 if (mAuthenticationCallback != null) { 1319 mAuthenticationCallback.onAuthenticationFailed(); 1320 } 1321 } 1322 sendAcquiredResult(int acquireInfo, int vendorCode)1323 private void sendAcquiredResult(int acquireInfo, int vendorCode) { 1324 if (mAuthenticationCallback != null) { 1325 mAuthenticationCallback.onAuthenticationAcquired(acquireInfo); 1326 } 1327 final String msg = getAcquiredString(mContext, acquireInfo, vendorCode); 1328 if (msg == null) { 1329 return; 1330 } 1331 // emulate HAL 2.1 behavior and send real acquiredInfo 1332 final int clientInfo = acquireInfo == FINGERPRINT_ACQUIRED_VENDOR 1333 ? (vendorCode + FINGERPRINT_ACQUIRED_VENDOR_BASE) : acquireInfo; 1334 if (mEnrollmentCallback != null) { 1335 mEnrollmentCallback.onEnrollmentHelp(clientInfo, msg); 1336 } else if (mAuthenticationCallback != null) { 1337 if (acquireInfo != BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START) { 1338 mAuthenticationCallback.onAuthenticationHelp(clientInfo, msg); 1339 } 1340 } 1341 } 1342 sendErrorResult(int errMsgId, int vendorCode)1343 private void sendErrorResult(int errMsgId, int vendorCode) { 1344 // emulate HAL 2.1 behavior and send real errMsgId 1345 final int clientErrMsgId = errMsgId == FINGERPRINT_ERROR_VENDOR 1346 ? (vendorCode + FINGERPRINT_ERROR_VENDOR_BASE) : errMsgId; 1347 if (mEnrollmentCallback != null) { 1348 mEnrollmentCallback.onEnrollmentError(clientErrMsgId, 1349 getErrorString(mContext, errMsgId, vendorCode)); 1350 } else if (mAuthenticationCallback != null) { 1351 mAuthenticationCallback.onAuthenticationError(clientErrMsgId, 1352 getErrorString(mContext, errMsgId, vendorCode)); 1353 } else if (mRemovalCallback != null) { 1354 final Fingerprint fp = mRemoveTracker != null 1355 ? mRemoveTracker.mSingleFingerprint : null; 1356 mRemovalCallback.onRemovalError(fp, clientErrMsgId, 1357 getErrorString(mContext, errMsgId, vendorCode)); 1358 } 1359 } 1360 sendChallengeGenerated(int sensorId, int userId, long challenge)1361 private void sendChallengeGenerated(int sensorId, int userId, long challenge) { 1362 if (mGenerateChallengeCallback == null) { 1363 Slog.e(TAG, "sendChallengeGenerated, callback null"); 1364 return; 1365 } 1366 mGenerateChallengeCallback.onChallengeGenerated(sensorId, userId, challenge); 1367 } 1368 sendFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric)1369 private void sendFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric) { 1370 if (mFingerprintDetectionCallback == null) { 1371 Slog.e(TAG, "sendFingerprintDetected, callback null"); 1372 return; 1373 } 1374 mFingerprintDetectionCallback.onFingerprintDetected(sensorId, userId, isStrongBiometric); 1375 } 1376 sendUdfpsPointerDown(int sensorId)1377 private void sendUdfpsPointerDown(int sensorId) { 1378 if (mAuthenticationCallback == null) { 1379 Slog.e(TAG, "sendUdfpsPointerDown, callback null"); 1380 return; 1381 } 1382 mAuthenticationCallback.onUdfpsPointerDown(sensorId); 1383 } 1384 sendUdfpsPointerUp(int sensorId)1385 private void sendUdfpsPointerUp(int sensorId) { 1386 if (mAuthenticationCallback == null) { 1387 Slog.e(TAG, "sendUdfpsPointerUp, callback null"); 1388 return; 1389 } 1390 mAuthenticationCallback.onUdfpsPointerUp(sensorId); 1391 } 1392 sendPowerPressed()1393 private void sendPowerPressed() { 1394 try { 1395 mService.onPowerPressed(); 1396 } catch (RemoteException e) { 1397 Slog.e(TAG, "Error sending power press", e); 1398 } 1399 } 1400 1401 /** 1402 * @hide 1403 */ FingerprintManager(Context context, IFingerprintService service)1404 public FingerprintManager(Context context, IFingerprintService service) { 1405 mContext = context; 1406 mService = service; 1407 if (mService == null) { 1408 Slog.v(TAG, "FingerprintService was null"); 1409 } 1410 mHandler = new MyHandler(context); 1411 } 1412 getCurrentUserId()1413 private int getCurrentUserId() { 1414 try { 1415 return ActivityManager.getService().getCurrentUser().id; 1416 } catch (RemoteException e) { 1417 throw e.rethrowFromSystemServer(); 1418 } 1419 } 1420 1421 @Nullable getFirstFingerprintSensor()1422 private FingerprintSensorPropertiesInternal getFirstFingerprintSensor() { 1423 final List<FingerprintSensorPropertiesInternal> allSensors = getSensorPropertiesInternal(); 1424 return allSensors.isEmpty() ? null : allSensors.get(0); 1425 } 1426 cancelEnrollment(long requestId)1427 private void cancelEnrollment(long requestId) { 1428 if (mService != null) try { 1429 mService.cancelEnrollment(mToken, requestId); 1430 } catch (RemoteException e) { 1431 throw e.rethrowFromSystemServer(); 1432 } 1433 } 1434 cancelAuthentication(long requestId)1435 private void cancelAuthentication(long requestId) { 1436 if (mService != null) try { 1437 mService.cancelAuthentication( 1438 mToken, 1439 mContext.getOpPackageName(), 1440 mContext.getAttributionTag(), 1441 requestId); 1442 } catch (RemoteException e) { 1443 throw e.rethrowFromSystemServer(); 1444 } 1445 } 1446 cancelFingerprintDetect(long requestId)1447 private void cancelFingerprintDetect(long requestId) { 1448 if (mService == null) { 1449 return; 1450 } 1451 1452 try { 1453 mService.cancelFingerprintDetect(mToken, mContext.getOpPackageName(), requestId); 1454 } catch (RemoteException e) { 1455 throw e.rethrowFromSystemServer(); 1456 } 1457 } 1458 1459 /** 1460 * @hide 1461 */ getEnrollStageCount()1462 public int getEnrollStageCount() { 1463 if (mEnrollStageThresholds == null) { 1464 mEnrollStageThresholds = createEnrollStageThresholds(mContext); 1465 } 1466 return mEnrollStageThresholds.length + 1; 1467 } 1468 1469 /** 1470 * @hide 1471 */ getEnrollStageThreshold(int index)1472 public float getEnrollStageThreshold(int index) { 1473 if (mEnrollStageThresholds == null) { 1474 mEnrollStageThresholds = createEnrollStageThresholds(mContext); 1475 } 1476 1477 if (index < 0 || index > mEnrollStageThresholds.length) { 1478 Slog.w(TAG, "Unsupported enroll stage index: " + index); 1479 return index < 0 ? 0f : 1f; 1480 } 1481 1482 // The implicit threshold for the final stage is always 1. 1483 return index == mEnrollStageThresholds.length ? 1f : mEnrollStageThresholds[index]; 1484 } 1485 1486 @NonNull 1487 @RequiresPermission(USE_BIOMETRIC_INTERNAL) createEnrollStageThresholds(@onNull Context context)1488 private float[] createEnrollStageThresholds(@NonNull Context context) { 1489 // TODO(b/200604947): Fetch this value from FingerprintService, rather than internal config 1490 final String[] enrollStageThresholdStrings; 1491 if (isPowerbuttonFps()) { 1492 enrollStageThresholdStrings = context.getResources().getStringArray( 1493 com.android.internal.R.array.config_sfps_enroll_stage_thresholds); 1494 } else { 1495 enrollStageThresholdStrings = context.getResources().getStringArray( 1496 com.android.internal.R.array.config_udfps_enroll_stage_thresholds); 1497 } 1498 1499 final float[] enrollStageThresholds = new float[enrollStageThresholdStrings.length]; 1500 for (int i = 0; i < enrollStageThresholds.length; i++) { 1501 enrollStageThresholds[i] = Float.parseFloat(enrollStageThresholdStrings[i]); 1502 } 1503 return enrollStageThresholds; 1504 } 1505 1506 /** 1507 * @hide 1508 */ getErrorString(Context context, int errMsg, int vendorCode)1509 public static String getErrorString(Context context, int errMsg, int vendorCode) { 1510 switch (errMsg) { 1511 case FINGERPRINT_ERROR_HW_UNAVAILABLE: 1512 return context.getString( 1513 com.android.internal.R.string.fingerprint_error_hw_not_available); 1514 case FINGERPRINT_ERROR_UNABLE_TO_PROCESS: 1515 return context.getString( 1516 com.android.internal.R.string.fingerprint_error_unable_to_process); 1517 case FINGERPRINT_ERROR_TIMEOUT: 1518 return context.getString(com.android.internal.R.string.fingerprint_error_timeout); 1519 case FINGERPRINT_ERROR_NO_SPACE: 1520 return context.getString( 1521 com.android.internal.R.string.fingerprint_error_no_space); 1522 case FINGERPRINT_ERROR_CANCELED: 1523 return context.getString(com.android.internal.R.string.fingerprint_error_canceled); 1524 case FINGERPRINT_ERROR_LOCKOUT: 1525 return context.getString(com.android.internal.R.string.fingerprint_error_lockout); 1526 case FINGERPRINT_ERROR_LOCKOUT_PERMANENT: 1527 return context.getString( 1528 com.android.internal.R.string.fingerprint_error_lockout_permanent); 1529 case FINGERPRINT_ERROR_USER_CANCELED: 1530 return context.getString( 1531 com.android.internal.R.string.fingerprint_error_user_canceled); 1532 case FINGERPRINT_ERROR_NO_FINGERPRINTS: 1533 return context.getString( 1534 com.android.internal.R.string.fingerprint_error_no_fingerprints); 1535 case FINGERPRINT_ERROR_HW_NOT_PRESENT: 1536 return context.getString( 1537 com.android.internal.R.string.fingerprint_error_hw_not_present); 1538 case BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED: 1539 return context.getString( 1540 com.android.internal.R.string.fingerprint_error_security_update_required); 1541 case FINGERPRINT_ERROR_BAD_CALIBRATION: 1542 return context.getString( 1543 com.android.internal.R.string.fingerprint_error_bad_calibration); 1544 case BIOMETRIC_ERROR_POWER_PRESSED: 1545 return context.getString( 1546 com.android.internal.R.string.fingerprint_error_power_pressed); 1547 case FINGERPRINT_ERROR_VENDOR: { 1548 String[] msgArray = context.getResources().getStringArray( 1549 com.android.internal.R.array.fingerprint_error_vendor); 1550 if (vendorCode < msgArray.length) { 1551 return msgArray[vendorCode]; 1552 } 1553 } 1554 } 1555 1556 // This is used as a last resort in case a vendor string is missing 1557 // It should not happen for anything other than FINGERPRINT_ERROR_VENDOR, but 1558 // warn and use the default if all else fails. 1559 Slog.w(TAG, "Invalid error message: " + errMsg + ", " + vendorCode); 1560 return context.getString( 1561 com.android.internal.R.string.fingerprint_error_vendor_unknown); 1562 } 1563 1564 /** 1565 * @hide 1566 */ getAcquiredString(Context context, int acquireInfo, int vendorCode)1567 public static String getAcquiredString(Context context, int acquireInfo, int vendorCode) { 1568 switch (acquireInfo) { 1569 case FINGERPRINT_ACQUIRED_GOOD: 1570 return null; 1571 case FINGERPRINT_ACQUIRED_PARTIAL: 1572 return context.getString( 1573 com.android.internal.R.string.fingerprint_acquired_partial); 1574 case FINGERPRINT_ACQUIRED_INSUFFICIENT: 1575 return context.getString( 1576 com.android.internal.R.string.fingerprint_acquired_insufficient); 1577 case FINGERPRINT_ACQUIRED_IMAGER_DIRTY: 1578 return context.getString( 1579 com.android.internal.R.string.fingerprint_acquired_imager_dirty); 1580 case FINGERPRINT_ACQUIRED_TOO_SLOW: 1581 return context.getString( 1582 com.android.internal.R.string.fingerprint_acquired_too_slow); 1583 case FINGERPRINT_ACQUIRED_TOO_FAST: 1584 return context.getString( 1585 com.android.internal.R.string.fingerprint_acquired_too_fast); 1586 case FINGERPRINT_ACQUIRED_IMMOBILE: 1587 return context.getString( 1588 com.android.internal.R.string.fingerprint_acquired_immobile); 1589 case FINGERPRINT_ACQUIRED_TOO_BRIGHT: 1590 return context.getString( 1591 com.android.internal.R.string.fingerprint_acquired_too_bright); 1592 case FINGERPRINT_ACQUIRED_POWER_PRESSED: 1593 return context.getString( 1594 com.android.internal.R.string.fingerprint_acquired_power_press); 1595 case FINGERPRINT_ACQUIRED_VENDOR: { 1596 String[] msgArray = context.getResources().getStringArray( 1597 com.android.internal.R.array.fingerprint_acquired_vendor); 1598 if (vendorCode < msgArray.length) { 1599 return msgArray[vendorCode]; 1600 } 1601 } 1602 break; 1603 case FINGERPRINT_ACQUIRED_START: 1604 return null; 1605 } 1606 Slog.w(TAG, "Invalid acquired message: " + acquireInfo + ", " + vendorCode); 1607 return null; 1608 } 1609 1610 private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() { 1611 1612 @Override // binder call 1613 public void onEnrollResult(Fingerprint fp, int remaining) { 1614 mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0, fp).sendToTarget(); 1615 } 1616 1617 @Override // binder call 1618 public void onAcquired(int acquireInfo, int vendorCode) { 1619 mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode).sendToTarget(); 1620 } 1621 1622 @Override // binder call 1623 public void onAuthenticationSucceeded(Fingerprint fp, int userId, 1624 boolean isStrongBiometric) { 1625 mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, isStrongBiometric ? 1 : 0, 1626 fp).sendToTarget(); 1627 } 1628 1629 @Override 1630 public void onFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric) { 1631 mHandler.obtainMessage(MSG_FINGERPRINT_DETECTED, sensorId, userId, isStrongBiometric) 1632 .sendToTarget(); 1633 } 1634 1635 @Override // binder call 1636 public void onAuthenticationFailed() { 1637 mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget(); 1638 } 1639 1640 @Override // binder call 1641 public void onError(int error, int vendorCode) { 1642 mHandler.obtainMessage(MSG_ERROR, error, vendorCode).sendToTarget(); 1643 } 1644 1645 @Override // binder call 1646 public void onRemoved(Fingerprint fp, int remaining) { 1647 mHandler.obtainMessage(MSG_REMOVED, remaining, 0, fp).sendToTarget(); 1648 } 1649 1650 @Override // binder call 1651 public void onChallengeGenerated(int sensorId, int userId, long challenge) { 1652 mHandler.obtainMessage(MSG_CHALLENGE_GENERATED, sensorId, userId, challenge) 1653 .sendToTarget(); 1654 } 1655 1656 @Override // binder call 1657 public void onUdfpsPointerDown(int sensorId) { 1658 mHandler.obtainMessage(MSG_UDFPS_POINTER_DOWN, sensorId, 0).sendToTarget(); 1659 } 1660 1661 @Override // binder call 1662 public void onUdfpsPointerUp(int sensorId) { 1663 mHandler.obtainMessage(MSG_UDFPS_POINTER_UP, sensorId, 0).sendToTarget(); 1664 } 1665 }; 1666 1667 } 1668