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 android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.RequiresPermission; 22 import android.app.ActivityManagerNative; 23 import android.content.Context; 24 import android.os.Binder; 25 import android.os.CancellationSignal; 26 import android.os.CancellationSignal.OnCancelListener; 27 import android.os.Handler; 28 import android.os.IBinder; 29 import android.os.Looper; 30 import android.os.RemoteException; 31 import android.os.UserHandle; 32 import android.security.keystore.AndroidKeyStoreProvider; 33 import android.util.Log; 34 import android.util.Slog; 35 36 import java.security.Signature; 37 import java.util.List; 38 39 import javax.crypto.Cipher; 40 import javax.crypto.Mac; 41 42 import static android.Manifest.permission.USE_FINGERPRINT; 43 import static android.Manifest.permission.MANAGE_FINGERPRINT; 44 45 /** 46 * A class that coordinates access to the fingerprint hardware. 47 * <p> 48 * Use {@link android.content.Context#getSystemService(java.lang.String)} 49 * with argument {@link android.content.Context#FINGERPRINT_SERVICE} to get 50 * an instance of this class. 51 */ 52 53 public class FingerprintManager { 54 private static final String TAG = "FingerprintManager"; 55 private static final boolean DEBUG = true; 56 private static final int MSG_ENROLL_RESULT = 100; 57 private static final int MSG_ACQUIRED = 101; 58 private static final int MSG_AUTHENTICATION_SUCCEEDED = 102; 59 private static final int MSG_AUTHENTICATION_FAILED = 103; 60 private static final int MSG_ERROR = 104; 61 private static final int MSG_REMOVED = 105; 62 63 // 64 // Error messages from fingerprint hardware during initilization, enrollment, authentication or 65 // removal. Must agree with the list in fingerprint.h 66 // 67 68 /** 69 * The hardware is unavailable. Try again later. 70 */ 71 public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; 72 73 /** 74 * Error state returned when the sensor was unable to process the current image. 75 */ 76 public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; 77 78 /** 79 * Error state returned when the current request has been running too long. This is intended to 80 * prevent programs from waiting for the fingerprint sensor indefinitely. The timeout is 81 * platform and sensor-specific, but is generally on the order of 30 seconds. 82 */ 83 public static final int FINGERPRINT_ERROR_TIMEOUT = 3; 84 85 /** 86 * Error state returned for operations like enrollment; the operation cannot be completed 87 * because there's not enough storage remaining to complete the operation. 88 */ 89 public static final int FINGERPRINT_ERROR_NO_SPACE = 4; 90 91 /** 92 * The operation was canceled because the fingerprint sensor is unavailable. For example, 93 * this may happen when the user is switched, the device is locked or another pending operation 94 * prevents or disables it. 95 */ 96 public static final int FINGERPRINT_ERROR_CANCELED = 5; 97 98 /** 99 * The {@link FingerprintManager#remove(Fingerprint, RemovalCallback)} call failed. Typically 100 * this will happen when the provided fingerprint id was incorrect. 101 * 102 * @hide 103 */ 104 public static final int FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6; 105 106 /** 107 * The operation was canceled because the API is locked out due to too many attempts. 108 */ 109 public static final int FINGERPRINT_ERROR_LOCKOUT = 7; 110 111 /** 112 * Hardware vendors may extend this list if there are conditions that do not fall under one of 113 * the above categories. Vendors are responsible for providing error strings for these errors. 114 * @hide 115 */ 116 public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000; 117 118 // 119 // Image acquisition messages. Must agree with those in fingerprint.h 120 // 121 122 /** 123 * The image acquired was good. 124 */ 125 public static final int FINGERPRINT_ACQUIRED_GOOD = 0; 126 127 /** 128 * Only a partial fingerprint image was detected. During enrollment, the user should be 129 * informed on what needs to happen to resolve this problem, e.g. "press firmly on sensor." 130 */ 131 public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; 132 133 /** 134 * The fingerprint image was too noisy to process due to a detected condition (i.e. dry skin) or 135 * a possibly dirty sensor (See {@link #FINGERPRINT_ACQUIRED_IMAGER_DIRTY}). 136 */ 137 public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; 138 139 /** 140 * The fingerprint image was too noisy due to suspected or detected dirt on the sensor. 141 * For example, it's reasonable return this after multiple 142 * {@link #FINGERPRINT_ACQUIRED_INSUFFICIENT} or actual detection of dirt on the sensor 143 * (stuck pixels, swaths, etc.). The user is expected to take action to clean the sensor 144 * when this is returned. 145 */ 146 public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3; 147 148 /** 149 * The fingerprint image was unreadable due to lack of motion. This is most appropriate for 150 * linear array sensors that require a swipe motion. 151 */ 152 public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; 153 154 /** 155 * The fingerprint image was incomplete due to quick motion. While mostly appropriate for 156 * linear array sensors, this could also happen if the finger was moved during acquisition. 157 * The user should be asked to move the finger slower (linear) or leave the finger on the sensor 158 * longer. 159 */ 160 public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; 161 162 /** 163 * Hardware vendors may extend this list if there are conditions that do not fall under one of 164 * the above categories. Vendors are responsible for providing error strings for these errors. 165 * @hide 166 */ 167 public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000; 168 169 private IFingerprintService mService; 170 private Context mContext; 171 private IBinder mToken = new Binder(); 172 private AuthenticationCallback mAuthenticationCallback; 173 private EnrollmentCallback mEnrollmentCallback; 174 private RemovalCallback mRemovalCallback; 175 private CryptoObject mCryptoObject; 176 private Fingerprint mRemovalFingerprint; 177 private Handler mHandler; 178 179 private class OnEnrollCancelListener implements OnCancelListener { 180 @Override onCancel()181 public void onCancel() { 182 cancelEnrollment(); 183 } 184 } 185 186 private class OnAuthenticationCancelListener implements OnCancelListener { 187 private CryptoObject mCrypto; 188 OnAuthenticationCancelListener(CryptoObject crypto)189 public OnAuthenticationCancelListener(CryptoObject crypto) { 190 mCrypto = crypto; 191 } 192 193 @Override onCancel()194 public void onCancel() { 195 cancelAuthentication(mCrypto); 196 } 197 } 198 199 /** 200 * A wrapper class for the crypto objects supported by FingerprintManager. Currently the 201 * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects. 202 */ 203 public static final class CryptoObject { 204 CryptoObject(@onNull Signature signature)205 public CryptoObject(@NonNull Signature signature) { 206 mCrypto = signature; 207 } 208 CryptoObject(@onNull Cipher cipher)209 public CryptoObject(@NonNull Cipher cipher) { 210 mCrypto = cipher; 211 } 212 CryptoObject(@onNull Mac mac)213 public CryptoObject(@NonNull Mac mac) { 214 mCrypto = mac; 215 } 216 217 /** 218 * Get {@link Signature} object. 219 * @return {@link Signature} object or null if this doesn't contain one. 220 */ getSignature()221 public Signature getSignature() { 222 return mCrypto instanceof Signature ? (Signature) mCrypto : null; 223 } 224 225 /** 226 * Get {@link Cipher} object. 227 * @return {@link Cipher} object or null if this doesn't contain one. 228 */ getCipher()229 public Cipher getCipher() { 230 return mCrypto instanceof Cipher ? (Cipher) mCrypto : null; 231 } 232 233 /** 234 * Get {@link Mac} object. 235 * @return {@link Mac} object or null if this doesn't contain one. 236 */ getMac()237 public Mac getMac() { 238 return mCrypto instanceof Mac ? (Mac) mCrypto : null; 239 } 240 241 /** 242 * @hide 243 * @return the opId associated with this object or 0 if none 244 */ getOpId()245 public long getOpId() { 246 return mCrypto != null ? 247 AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0; 248 } 249 250 private final Object mCrypto; 251 }; 252 253 /** 254 * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject, 255 * CancellationSignal, int, AuthenticationCallback, Handler)}. 256 */ 257 public static class AuthenticationResult { 258 private Fingerprint mFingerprint; 259 private CryptoObject mCryptoObject; 260 261 /** 262 * Authentication result 263 * 264 * @param crypto the crypto object 265 * @param fingerprint the recognized fingerprint data, if allowed. 266 * @hide 267 */ AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint)268 public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) { 269 mCryptoObject = crypto; 270 mFingerprint = fingerprint; 271 } 272 273 /** 274 * Obtain the crypto object associated with this transaction 275 * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject, 276 * CancellationSignal, int, AuthenticationCallback, Handler)}. 277 */ getCryptoObject()278 public CryptoObject getCryptoObject() { return mCryptoObject; } 279 280 /** 281 * Obtain the Fingerprint associated with this operation. Applications are strongly 282 * discouraged from associating specific fingers with specific applications or operations. 283 * 284 * @hide 285 */ getFingerprint()286 public Fingerprint getFingerprint() { return mFingerprint; } 287 }; 288 289 /** 290 * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject, 291 * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link 292 * FingerprintManager#authenticate(CryptoObject, CancellationSignal, 293 * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to 294 * fingerprint events. 295 */ 296 public static abstract class AuthenticationCallback { 297 /** 298 * Called when an unrecoverable error has been encountered and the operation is complete. 299 * No further callbacks will be made on this object. 300 * @param errorCode An integer identifying the error message 301 * @param errString A human-readable error string that can be shown in UI 302 */ onAuthenticationError(int errorCode, CharSequence errString)303 public void onAuthenticationError(int errorCode, CharSequence errString) { } 304 305 /** 306 * Called when a recoverable error has been encountered during authentication. The help 307 * string is provided to give the user guidance for what went wrong, such as 308 * "Sensor dirty, please clean it." 309 * @param helpCode An integer identifying the error message 310 * @param helpString A human-readable string that can be shown in UI 311 */ onAuthenticationHelp(int helpCode, CharSequence helpString)312 public void onAuthenticationHelp(int helpCode, CharSequence helpString) { } 313 314 /** 315 * Called when a fingerprint is recognized. 316 * @param result An object containing authentication-related data 317 */ onAuthenticationSucceeded(AuthenticationResult result)318 public void onAuthenticationSucceeded(AuthenticationResult result) { } 319 320 /** 321 * Called when a fingerprint is valid but not recognized. 322 */ onAuthenticationFailed()323 public void onAuthenticationFailed() { } 324 325 /** 326 * Called when a fingerprint image has been acquired, but wasn't processed yet. 327 * 328 * @param acquireInfo one of FINGERPRINT_ACQUIRED_* constants 329 * @hide 330 */ onAuthenticationAcquired(int acquireInfo)331 public void onAuthenticationAcquired(int acquireInfo) {} 332 }; 333 334 /** 335 * Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback, 336 * CancellationSignal, int). Users of {@link #FingerprintManager()} 337 * must provide an implementation of this to {@link FingerprintManager#enroll(long, 338 * CancellationSignal, int, EnrollmentCallback) for listening to fingerprint events. 339 * 340 * @hide 341 */ 342 public static abstract class EnrollmentCallback { 343 /** 344 * Called when an unrecoverable error has been encountered and the operation is complete. 345 * No further callbacks will be made on this object. 346 * @param errMsgId An integer identifying the error message 347 * @param errString A human-readable error string that can be shown in UI 348 */ onEnrollmentError(int errMsgId, CharSequence errString)349 public void onEnrollmentError(int errMsgId, CharSequence errString) { } 350 351 /** 352 * Called when a recoverable error has been encountered during enrollment. The help 353 * string is provided to give the user guidance for what went wrong, such as 354 * "Sensor dirty, please clean it" or what they need to do next, such as 355 * "Touch sensor again." 356 * @param helpMsgId An integer identifying the error message 357 * @param helpString A human-readable string that can be shown in UI 358 */ onEnrollmentHelp(int helpMsgId, CharSequence helpString)359 public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { } 360 361 /** 362 * Called as each enrollment step progresses. Enrollment is considered complete when 363 * remaining reaches 0. This function will not be called if enrollment fails. See 364 * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} 365 * @param remaining The number of remaining steps 366 */ onEnrollmentProgress(int remaining)367 public void onEnrollmentProgress(int remaining) { } 368 }; 369 370 /** 371 * Callback structure provided to {@link FingerprintManager#remove(int). Users of 372 * {@link #FingerprintManager()} may optionally provide an implementation of this to 373 * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to 374 * fingerprint template removal events. 375 * 376 * @hide 377 */ 378 public static abstract class RemovalCallback { 379 /** 380 * Called when the given fingerprint can't be removed. 381 * @param fp The fingerprint that the call attempted to remove 382 * @param errMsgId An associated error message id 383 * @param errString An error message indicating why the fingerprint id can't be removed 384 */ onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString)385 public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { } 386 387 /** 388 * Called when a given fingerprint is successfully removed. 389 * @param fingerprint the fingerprint template that was removed. 390 */ onRemovalSucceeded(Fingerprint fingerprint)391 public void onRemovalSucceeded(Fingerprint fingerprint) { } 392 }; 393 394 /** 395 * Request authentication of a crypto object. This call warms up the fingerprint hardware 396 * and starts scanning for a fingerprint. It terminates when 397 * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or 398 * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at 399 * which point the object is no longer valid. The operation can be canceled by using the 400 * provided cancel object. 401 * 402 * @param crypto object associated with the call or null if none required. 403 * @param cancel an object that can be used to cancel authentication 404 * @param flags optional flags; should be 0 405 * @param callback an object to receive authentication events 406 * @param handler an optional handler to handle callback events 407 * 408 * @throws IllegalArgumentException if the crypto operation is not supported or is not backed 409 * by <a href="{@docRoot}training/articles/keystore.html">Android Keystore 410 * facility</a>. 411 * @throws IllegalStateException if the crypto primitive is not initialized. 412 */ 413 @RequiresPermission(USE_FINGERPRINT) authenticate(@ullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler)414 public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, 415 int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) { 416 authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId()); 417 } 418 419 /** 420 * Use the provided handler thread for events. 421 * @param handler 422 */ useHandler(Handler handler)423 private void useHandler(Handler handler) { 424 if (handler != null) { 425 mHandler = new MyHandler(handler.getLooper()); 426 } else if (mHandler.getLooper() != mContext.getMainLooper()){ 427 mHandler = new MyHandler(mContext.getMainLooper()); 428 } 429 } 430 431 /** 432 * Per-user version 433 * @hide 434 */ 435 @RequiresPermission(USE_FINGERPRINT) authenticate(@ullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId)436 public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, 437 int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) { 438 if (callback == null) { 439 throw new IllegalArgumentException("Must supply an authentication callback"); 440 } 441 442 if (cancel != null) { 443 if (cancel.isCanceled()) { 444 Log.w(TAG, "authentication already canceled"); 445 return; 446 } else { 447 cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto)); 448 } 449 } 450 451 if (mService != null) try { 452 useHandler(handler); 453 mAuthenticationCallback = callback; 454 mCryptoObject = crypto; 455 long sessionId = crypto != null ? crypto.getOpId() : 0; 456 mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags, 457 mContext.getOpPackageName()); 458 } catch (RemoteException e) { 459 Log.w(TAG, "Remote exception while authenticating: ", e); 460 if (callback != null) { 461 // Though this may not be a hardware issue, it will cause apps to give up or try 462 // again later. 463 callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 464 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE)); 465 } 466 } 467 } 468 469 /** 470 * Request fingerprint enrollment. This call warms up the fingerprint hardware 471 * and starts scanning for fingerprints. Progress will be indicated by callbacks to the 472 * {@link EnrollmentCallback} object. It terminates when 473 * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or 474 * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at 475 * which point the object is no longer valid. The operation can be canceled by using the 476 * provided cancel object. 477 * @param token a unique token provided by a recent creation or verification of device 478 * credentials (e.g. pin, pattern or password). 479 * @param cancel an object that can be used to cancel enrollment 480 * @param flags optional flags 481 * @param callback an object to receive enrollment events 482 * @hide 483 */ 484 @RequiresPermission(MANAGE_FINGERPRINT) enroll(byte [] token, CancellationSignal cancel, int flags, EnrollmentCallback callback)485 public void enroll(byte [] token, CancellationSignal cancel, int flags, 486 EnrollmentCallback callback) { 487 if (callback == null) { 488 throw new IllegalArgumentException("Must supply an enrollment callback"); 489 } 490 491 if (cancel != null) { 492 if (cancel.isCanceled()) { 493 Log.w(TAG, "enrollment already canceled"); 494 return; 495 } else { 496 cancel.setOnCancelListener(new OnEnrollCancelListener()); 497 } 498 } 499 500 if (mService != null) try { 501 mEnrollmentCallback = callback; 502 mService.enroll(mToken, token, getCurrentUserId(), mServiceReceiver, flags); 503 } catch (RemoteException e) { 504 Log.w(TAG, "Remote exception in enroll: ", e); 505 if (callback != null) { 506 // Though this may not be a hardware issue, it will cause apps to give up or try 507 // again later. 508 callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 509 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE)); 510 } 511 } 512 } 513 514 /** 515 * Requests a pre-enrollment auth token to tie enrollment to the confirmation of 516 * existing device credentials (e.g. pin/pattern/password). 517 * @hide 518 */ 519 @RequiresPermission(MANAGE_FINGERPRINT) preEnroll()520 public long preEnroll() { 521 long result = 0; 522 if (mService != null) try { 523 result = mService.preEnroll(mToken); 524 } catch (RemoteException e) { 525 Log.w(TAG, "Remote exception in enroll: ", e); 526 } 527 return result; 528 } 529 530 /** 531 * Finishes enrollment and cancels the current auth token. 532 * @hide 533 */ 534 @RequiresPermission(MANAGE_FINGERPRINT) postEnroll()535 public int postEnroll() { 536 int result = 0; 537 if (mService != null) try { 538 result = mService.postEnroll(mToken); 539 } catch (RemoteException e) { 540 Log.w(TAG, "Remote exception in post enroll: ", e); 541 } 542 return result; 543 } 544 545 /** 546 * Remove given fingerprint template from fingerprint hardware and/or protected storage. 547 * @param fp the fingerprint item to remove 548 * @param callback an optional callback to verify that fingerprint templates have been 549 * successfully removed. May be null of no callback is required. 550 * 551 * @hide 552 */ 553 @RequiresPermission(MANAGE_FINGERPRINT) remove(Fingerprint fp, RemovalCallback callback)554 public void remove(Fingerprint fp, RemovalCallback callback) { 555 if (mService != null) try { 556 mRemovalCallback = callback; 557 mRemovalFingerprint = fp; 558 mService.remove(mToken, fp.getFingerId(), getCurrentUserId(), mServiceReceiver); 559 } catch (RemoteException e) { 560 Log.w(TAG, "Remote exception in remove: ", e); 561 if (callback != null) { 562 callback.onRemovalError(fp, FINGERPRINT_ERROR_HW_UNAVAILABLE, 563 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE)); 564 } 565 } 566 } 567 568 /** 569 * Renames the given fingerprint template 570 * @param fpId the fingerprint id 571 * @param newName the new name 572 * 573 * @hide 574 */ 575 @RequiresPermission(MANAGE_FINGERPRINT) rename(int fpId, String newName)576 public void rename(int fpId, String newName) { 577 // Renames the given fpId 578 if (mService != null) { 579 try { 580 mService.rename(fpId, getCurrentUserId(), newName); 581 } catch (RemoteException e) { 582 Log.v(TAG, "Remote exception in rename(): ", e); 583 } 584 } else { 585 Log.w(TAG, "rename(): Service not connected!"); 586 } 587 } 588 589 /** 590 * Obtain the list of enrolled fingerprints templates. 591 * @return list of current fingerprint items 592 * 593 * @hide 594 */ 595 @RequiresPermission(USE_FINGERPRINT) getEnrolledFingerprints(int userId)596 public List<Fingerprint> getEnrolledFingerprints(int userId) { 597 if (mService != null) try { 598 return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName()); 599 } catch (RemoteException e) { 600 Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e); 601 } 602 return null; 603 } 604 605 /** 606 * Obtain the list of enrolled fingerprints templates. 607 * @return list of current fingerprint items 608 * 609 * @hide 610 */ 611 @RequiresPermission(USE_FINGERPRINT) getEnrolledFingerprints()612 public List<Fingerprint> getEnrolledFingerprints() { 613 return getEnrolledFingerprints(UserHandle.myUserId()); 614 } 615 616 /** 617 * Determine if there is at least one fingerprint enrolled. 618 * 619 * @return true if at least one fingerprint is enrolled, false otherwise 620 */ 621 @RequiresPermission(USE_FINGERPRINT) hasEnrolledFingerprints()622 public boolean hasEnrolledFingerprints() { 623 if (mService != null) try { 624 return mService.hasEnrolledFingerprints(UserHandle.myUserId(), 625 mContext.getOpPackageName()); 626 } catch (RemoteException e) { 627 Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e); 628 } 629 return false; 630 } 631 632 /** 633 * Determine if fingerprint hardware is present and functional. 634 * 635 * @return true if hardware is present and functional, false otherwise. 636 */ 637 @RequiresPermission(USE_FINGERPRINT) isHardwareDetected()638 public boolean isHardwareDetected() { 639 if (mService != null) { 640 try { 641 long deviceId = 0; /* TODO: plumb hardware id to FPMS */ 642 return mService.isHardwareDetected(deviceId, mContext.getOpPackageName()); 643 } catch (RemoteException e) { 644 Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e); 645 } 646 } else { 647 Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!"); 648 } 649 return false; 650 } 651 652 /** 653 * Retrieves the authenticator token for binding keys to the lifecycle 654 * of the current set of fingerprints. Used only by internal clients. 655 * 656 * @hide 657 */ getAuthenticatorId()658 public long getAuthenticatorId() { 659 if (mService != null) { 660 try { 661 return mService.getAuthenticatorId(mContext.getOpPackageName()); 662 } catch (RemoteException e) { 663 Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e); 664 } 665 } else { 666 Log.w(TAG, "getAuthenticatorId(): Service not connected!"); 667 } 668 return 0; 669 } 670 671 private class MyHandler extends Handler { MyHandler(Context context)672 private MyHandler(Context context) { 673 super(context.getMainLooper()); 674 } 675 MyHandler(Looper looper)676 private MyHandler(Looper looper) { 677 super(looper); 678 } 679 handleMessage(android.os.Message msg)680 public void handleMessage(android.os.Message msg) { 681 switch(msg.what) { 682 case MSG_ENROLL_RESULT: 683 sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */); 684 break; 685 case MSG_ACQUIRED: 686 sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */); 687 break; 688 case MSG_AUTHENTICATION_SUCCEEDED: 689 sendAuthenticatedSucceeded((Fingerprint) msg.obj); 690 break; 691 case MSG_AUTHENTICATION_FAILED: 692 sendAuthenticatedFailed(); 693 break; 694 case MSG_ERROR: 695 sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */); 696 break; 697 case MSG_REMOVED: 698 sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */, 699 msg.arg2 /* groupId */); 700 } 701 } 702 sendRemovedResult(long deviceId, int fingerId, int groupId)703 private void sendRemovedResult(long deviceId, int fingerId, int groupId) { 704 if (mRemovalCallback != null) { 705 int reqFingerId = mRemovalFingerprint.getFingerId(); 706 int reqGroupId = mRemovalFingerprint.getGroupId(); 707 if (fingerId != reqFingerId) { 708 Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId); 709 } 710 if (fingerId != reqFingerId) { 711 Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId); 712 } 713 mRemovalCallback.onRemovalSucceeded(mRemovalFingerprint); 714 } 715 } 716 sendErrorResult(long deviceId, int errMsgId)717 private void sendErrorResult(long deviceId, int errMsgId) { 718 if (mEnrollmentCallback != null) { 719 mEnrollmentCallback.onEnrollmentError(errMsgId, getErrorString(errMsgId)); 720 } else if (mAuthenticationCallback != null) { 721 mAuthenticationCallback.onAuthenticationError(errMsgId, getErrorString(errMsgId)); 722 } else if (mRemovalCallback != null) { 723 mRemovalCallback.onRemovalError(mRemovalFingerprint, errMsgId, 724 getErrorString(errMsgId)); 725 } 726 } 727 sendEnrollResult(Fingerprint fp, int remaining)728 private void sendEnrollResult(Fingerprint fp, int remaining) { 729 if (mEnrollmentCallback != null) { 730 mEnrollmentCallback.onEnrollmentProgress(remaining); 731 } 732 } 733 sendAuthenticatedSucceeded(Fingerprint fp)734 private void sendAuthenticatedSucceeded(Fingerprint fp) { 735 if (mAuthenticationCallback != null) { 736 final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp); 737 mAuthenticationCallback.onAuthenticationSucceeded(result); 738 } 739 } 740 sendAuthenticatedFailed()741 private void sendAuthenticatedFailed() { 742 if (mAuthenticationCallback != null) { 743 mAuthenticationCallback.onAuthenticationFailed(); 744 } 745 } 746 sendAcquiredResult(long deviceId, int acquireInfo)747 private void sendAcquiredResult(long deviceId, int acquireInfo) { 748 if (mAuthenticationCallback != null) { 749 mAuthenticationCallback.onAuthenticationAcquired(acquireInfo); 750 } 751 final String msg = getAcquiredString(acquireInfo); 752 if (msg == null) { 753 return; 754 } 755 if (mEnrollmentCallback != null) { 756 mEnrollmentCallback.onEnrollmentHelp(acquireInfo, msg); 757 } else if (mAuthenticationCallback != null) { 758 mAuthenticationCallback.onAuthenticationHelp(acquireInfo, msg); 759 } 760 } 761 }; 762 763 /** 764 * @hide 765 */ FingerprintManager(Context context, IFingerprintService service)766 public FingerprintManager(Context context, IFingerprintService service) { 767 mContext = context; 768 mService = service; 769 if (mService == null) { 770 Slog.v(TAG, "FingerprintManagerService was null"); 771 } 772 mHandler = new MyHandler(context); 773 } 774 getCurrentUserId()775 private int getCurrentUserId() { 776 try { 777 return ActivityManagerNative.getDefault().getCurrentUser().id; 778 } catch (RemoteException e) { 779 Log.w(TAG, "Failed to get current user id\n"); 780 return UserHandle.USER_NULL; 781 } 782 } 783 cancelEnrollment()784 private void cancelEnrollment() { 785 if (mService != null) try { 786 mService.cancelEnrollment(mToken); 787 } catch (RemoteException e) { 788 if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment"); 789 } 790 } 791 cancelAuthentication(CryptoObject cryptoObject)792 private void cancelAuthentication(CryptoObject cryptoObject) { 793 if (mService != null) try { 794 mService.cancelAuthentication(mToken, mContext.getOpPackageName()); 795 } catch (RemoteException e) { 796 if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment"); 797 } 798 } 799 getErrorString(int errMsg)800 private String getErrorString(int errMsg) { 801 switch (errMsg) { 802 case FINGERPRINT_ERROR_UNABLE_TO_PROCESS: 803 return mContext.getString( 804 com.android.internal.R.string.fingerprint_error_unable_to_process); 805 case FINGERPRINT_ERROR_HW_UNAVAILABLE: 806 return mContext.getString( 807 com.android.internal.R.string.fingerprint_error_hw_not_available); 808 case FINGERPRINT_ERROR_NO_SPACE: 809 return mContext.getString( 810 com.android.internal.R.string.fingerprint_error_no_space); 811 case FINGERPRINT_ERROR_TIMEOUT: 812 return mContext.getString(com.android.internal.R.string.fingerprint_error_timeout); 813 case FINGERPRINT_ERROR_CANCELED: 814 return mContext.getString(com.android.internal.R.string.fingerprint_error_canceled); 815 case FINGERPRINT_ERROR_LOCKOUT: 816 return mContext.getString(com.android.internal.R.string.fingerprint_error_lockout); 817 default: 818 if (errMsg >= FINGERPRINT_ERROR_VENDOR_BASE) { 819 int msgNumber = errMsg - FINGERPRINT_ERROR_VENDOR_BASE; 820 String[] msgArray = mContext.getResources().getStringArray( 821 com.android.internal.R.array.fingerprint_error_vendor); 822 if (msgNumber < msgArray.length) { 823 return msgArray[msgNumber]; 824 } 825 } 826 return null; 827 } 828 } 829 getAcquiredString(int acquireInfo)830 private String getAcquiredString(int acquireInfo) { 831 switch (acquireInfo) { 832 case FINGERPRINT_ACQUIRED_GOOD: 833 return null; 834 case FINGERPRINT_ACQUIRED_PARTIAL: 835 return mContext.getString( 836 com.android.internal.R.string.fingerprint_acquired_partial); 837 case FINGERPRINT_ACQUIRED_INSUFFICIENT: 838 return mContext.getString( 839 com.android.internal.R.string.fingerprint_acquired_insufficient); 840 case FINGERPRINT_ACQUIRED_IMAGER_DIRTY: 841 return mContext.getString( 842 com.android.internal.R.string.fingerprint_acquired_imager_dirty); 843 case FINGERPRINT_ACQUIRED_TOO_SLOW: 844 return mContext.getString( 845 com.android.internal.R.string.fingerprint_acquired_too_slow); 846 case FINGERPRINT_ACQUIRED_TOO_FAST: 847 return mContext.getString( 848 com.android.internal.R.string.fingerprint_acquired_too_fast); 849 default: 850 if (acquireInfo >= FINGERPRINT_ACQUIRED_VENDOR_BASE) { 851 int msgNumber = acquireInfo - FINGERPRINT_ACQUIRED_VENDOR_BASE; 852 String[] msgArray = mContext.getResources().getStringArray( 853 com.android.internal.R.array.fingerprint_acquired_vendor); 854 if (msgNumber < msgArray.length) { 855 return msgArray[msgNumber]; 856 } 857 } 858 return null; 859 } 860 } 861 862 private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() { 863 864 @Override // binder call 865 public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) { 866 mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0, 867 new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget(); 868 } 869 870 @Override // binder call 871 public void onAcquired(long deviceId, int acquireInfo) { 872 mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget(); 873 } 874 875 @Override // binder call 876 public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) { 877 mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget(); 878 } 879 880 @Override // binder call 881 public void onAuthenticationFailed(long deviceId) { 882 mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();; 883 } 884 885 @Override // binder call 886 public void onError(long deviceId, int error) { 887 mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget(); 888 } 889 890 @Override // binder call 891 public void onRemoved(long deviceId, int fingerId, int groupId) { 892 mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget(); 893 } 894 }; 895 896 } 897 898