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