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