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