FingerprintManager.java revision f501b58de8f467a80fef49c704555781bc61ea6f
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 17package android.hardware.fingerprint; 18 19import android.annotation.NonNull; 20import android.annotation.Nullable; 21import android.annotation.RequiresPermission; 22import android.app.ActivityManagerNative; 23import android.content.Context; 24import android.os.Binder; 25import android.os.CancellationSignal; 26import android.os.CancellationSignal.OnCancelListener; 27import android.os.Handler; 28import android.os.IBinder; 29import android.os.Looper; 30import android.os.RemoteException; 31import android.os.UserHandle; 32import android.security.keystore.AndroidKeyStoreProvider; 33import android.util.Log; 34import android.util.Slog; 35 36import java.security.Signature; 37import java.util.List; 38 39import javax.crypto.Cipher; 40import javax.crypto.Mac; 41 42import static android.Manifest.permission.USE_FINGERPRINT; 43import 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 53public 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 181 public void onCancel() { 182 cancelEnrollment(); 183 } 184 } 185 186 private class OnAuthenticationCancelListener implements OnCancelListener { 187 private CryptoObject mCrypto; 188 189 public OnAuthenticationCancelListener(CryptoObject crypto) { 190 mCrypto = crypto; 191 } 192 193 @Override 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 205 public CryptoObject(@NonNull Signature signature) { 206 mCrypto = signature; 207 } 208 209 public CryptoObject(@NonNull Cipher cipher) { 210 mCrypto = cipher; 211 } 212 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 */ 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 */ 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 */ 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 */ 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 final 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 318 public void onAuthenticationSucceeded(AuthenticationResult result) { } 319 320 /** 321 * Called when a fingerprint is valid but not recognized. 322 */ 323 public void onAuthenticationFailed() { } 324 }; 325 326 /** 327 * Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback, 328 * CancellationSignal, int). Users of {@link #FingerprintManager()} 329 * must provide an implementation of this to {@link FingerprintManager#enroll(long, 330 * CancellationSignal, int, EnrollmentCallback) for listening to fingerprint events. 331 * 332 * @hide 333 */ 334 public static abstract class EnrollmentCallback { 335 /** 336 * Called when an unrecoverable error has been encountered and the operation is complete. 337 * No further callbacks will be made on this object. 338 * @param errMsgId An integer identifying the error message 339 * @param errString A human-readable error string that can be shown in UI 340 */ 341 public void onEnrollmentError(int errMsgId, CharSequence errString) { } 342 343 /** 344 * Called when a recoverable error has been encountered during enrollment. The help 345 * string is provided to give the user guidance for what went wrong, such as 346 * "Sensor dirty, please clean it" or what they need to do next, such as 347 * "Touch sensor again." 348 * @param helpMsgId An integer identifying the error message 349 * @param helpString A human-readable string that can be shown in UI 350 */ 351 public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { } 352 353 /** 354 * Called as each enrollment step progresses. Enrollment is considered complete when 355 * remaining reaches 0. This function will not be called if enrollment fails. See 356 * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} 357 * @param remaining The number of remaining steps 358 */ 359 public void onEnrollmentProgress(int remaining) { } 360 }; 361 362 /** 363 * Callback structure provided to {@link FingerprintManager#remove(int). Users of 364 * {@link #FingerprintManager()} may optionally provide an implementation of this to 365 * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to 366 * fingerprint template removal events. 367 * 368 * @hide 369 */ 370 public static abstract class RemovalCallback { 371 /** 372 * Called when the given fingerprint can't be removed. 373 * @param fp The fingerprint that the call attempted to remove 374 * @param errMsgId An associated error message id 375 * @param errString An error message indicating why the fingerprint id can't be removed 376 */ 377 public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { } 378 379 /** 380 * Called when a given fingerprint is successfully removed. 381 * @param fingerprint the fingerprint template that was removed. 382 */ 383 public void onRemovalSucceeded(Fingerprint fingerprint) { } 384 }; 385 386 /** 387 * Request authentication of a crypto object. This call warms up the fingerprint hardware 388 * and starts scanning for a fingerprint. It terminates when 389 * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or 390 * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult) is called, at 391 * which point the object is no longer valid. The operation can be canceled by using the 392 * provided cancel object. 393 * 394 * @param crypto object associated with the call or null if none required. 395 * @param cancel an object that can be used to cancel authentication 396 * @param flags optional flags; should be 0 397 * @param callback an object to receive authentication events 398 * @param handler an optional handler to handle callback events 399 */ 400 @RequiresPermission(USE_FINGERPRINT) 401 public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, 402 int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) { 403 authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId()); 404 } 405 406 /** 407 * Use the provided handler thread for events. 408 * @param handler 409 */ 410 private void useHandler(Handler handler) { 411 if (handler != null) { 412 mHandler = new MyHandler(handler.getLooper()); 413 } else if (mHandler.getLooper() != mContext.getMainLooper()){ 414 mHandler = new MyHandler(mContext.getMainLooper()); 415 } 416 } 417 418 /** 419 * Per-user version 420 * @hide 421 */ 422 @RequiresPermission(USE_FINGERPRINT) 423 public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, 424 int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) { 425 if (callback == null) { 426 throw new IllegalArgumentException("Must supply an authentication callback"); 427 } 428 429 if (cancel != null) { 430 if (cancel.isCanceled()) { 431 Log.w(TAG, "authentication already canceled"); 432 return; 433 } else { 434 cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto)); 435 } 436 } 437 438 if (mService != null) try { 439 useHandler(handler); 440 mAuthenticationCallback = callback; 441 mCryptoObject = crypto; 442 long sessionId = crypto != null ? crypto.getOpId() : 0; 443 mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags, 444 mContext.getOpPackageName()); 445 } catch (RemoteException e) { 446 Log.w(TAG, "Remote exception while authenticating: ", e); 447 if (callback != null) { 448 // Though this may not be a hardware issue, it will cause apps to give up or try 449 // again later. 450 callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 451 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE)); 452 } 453 } 454 } 455 456 /** 457 * Request fingerprint enrollment. This call warms up the fingerprint hardware 458 * and starts scanning for fingerprints. Progress will be indicated by callbacks to the 459 * {@link EnrollmentCallback} object. It terminates when 460 * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or 461 * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at 462 * which point the object is no longer valid. The operation can be canceled by using the 463 * provided cancel object. 464 * @param token a unique token provided by a recent creation or verification of device 465 * credentials (e.g. pin, pattern or password). 466 * @param cancel an object that can be used to cancel enrollment 467 * @param flags optional flags 468 * @param callback an object to receive enrollment events 469 * @hide 470 */ 471 @RequiresPermission(MANAGE_FINGERPRINT) 472 public void enroll(byte [] token, CancellationSignal cancel, int flags, 473 EnrollmentCallback callback) { 474 if (callback == null) { 475 throw new IllegalArgumentException("Must supply an enrollment callback"); 476 } 477 478 if (cancel != null) { 479 if (cancel.isCanceled()) { 480 Log.w(TAG, "enrollment already canceled"); 481 return; 482 } else { 483 cancel.setOnCancelListener(new OnEnrollCancelListener()); 484 } 485 } 486 487 if (mService != null) try { 488 mEnrollmentCallback = callback; 489 mService.enroll(mToken, token, getCurrentUserId(), mServiceReceiver, flags); 490 } catch (RemoteException e) { 491 Log.w(TAG, "Remote exception in enroll: ", e); 492 if (callback != null) { 493 // Though this may not be a hardware issue, it will cause apps to give up or try 494 // again later. 495 callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 496 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE)); 497 } 498 } 499 } 500 501 /** 502 * Requests a pre-enrollment auth token to tie enrollment to the confirmation of 503 * existing device credentials (e.g. pin/pattern/password). 504 * @hide 505 */ 506 @RequiresPermission(MANAGE_FINGERPRINT) 507 public long preEnroll() { 508 long result = 0; 509 if (mService != null) try { 510 result = mService.preEnroll(mToken); 511 } catch (RemoteException e) { 512 Log.w(TAG, "Remote exception in enroll: ", e); 513 } 514 return result; 515 } 516 517 /** 518 * Remove given fingerprint template from fingerprint hardware and/or protected storage. 519 * @param fp the fingerprint item to remove 520 * @param callback an optional callback to verify that fingerprint templates have been 521 * successfully removed. May be null of no callback is required. 522 * 523 * @hide 524 */ 525 @RequiresPermission(MANAGE_FINGERPRINT) 526 public void remove(Fingerprint fp, RemovalCallback callback) { 527 if (mService != null) try { 528 mRemovalCallback = callback; 529 mRemovalFingerprint = fp; 530 mService.remove(mToken, fp.getFingerId(), getCurrentUserId(), mServiceReceiver); 531 } catch (RemoteException e) { 532 Log.w(TAG, "Remote exception in remove: ", e); 533 if (callback != null) { 534 callback.onRemovalError(fp, FINGERPRINT_ERROR_HW_UNAVAILABLE, 535 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE)); 536 } 537 } 538 } 539 540 /** 541 * Renames the given fingerprint template 542 * @param fpId the fingerprint id 543 * @param newName the new name 544 * 545 * @hide 546 */ 547 @RequiresPermission(MANAGE_FINGERPRINT) 548 public void rename(int fpId, String newName) { 549 // Renames the given fpId 550 if (mService != null) { 551 try { 552 mService.rename(fpId, getCurrentUserId(), newName); 553 } catch (RemoteException e) { 554 Log.v(TAG, "Remote exception in rename(): ", e); 555 } 556 } else { 557 Log.w(TAG, "rename(): Service not connected!"); 558 } 559 } 560 561 /** 562 * Obtain the list of enrolled fingerprints templates. 563 * @return list of current fingerprint items 564 * 565 * @hide 566 */ 567 @RequiresPermission(USE_FINGERPRINT) 568 public List<Fingerprint> getEnrolledFingerprints(int userId) { 569 if (mService != null) try { 570 return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName()); 571 } catch (RemoteException e) { 572 Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e); 573 } 574 return null; 575 } 576 577 /** 578 * Obtain the list of enrolled fingerprints templates. 579 * @return list of current fingerprint items 580 * 581 * @hide 582 */ 583 @RequiresPermission(USE_FINGERPRINT) 584 public List<Fingerprint> getEnrolledFingerprints() { 585 return getEnrolledFingerprints(UserHandle.myUserId()); 586 } 587 588 /** 589 * Determine if there is at least one fingerprint enrolled. 590 * 591 * @return true if at least one fingerprint is enrolled, false otherwise 592 */ 593 @RequiresPermission(USE_FINGERPRINT) 594 public boolean hasEnrolledFingerprints() { 595 if (mService != null) try { 596 return mService.hasEnrolledFingerprints(UserHandle.myUserId(), 597 mContext.getOpPackageName()); 598 } catch (RemoteException e) { 599 Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e); 600 } 601 return false; 602 } 603 604 /** 605 * Determine if fingerprint hardware is present and functional. 606 * 607 * @return true if hardware is present and functional, false otherwise. 608 */ 609 @RequiresPermission(USE_FINGERPRINT) 610 public boolean isHardwareDetected() { 611 if (mService != null) { 612 try { 613 long deviceId = 0; /* TODO: plumb hardware id to FPMS */ 614 return mService.isHardwareDetected(deviceId, mContext.getOpPackageName()); 615 } catch (RemoteException e) { 616 Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e); 617 } 618 } else { 619 Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!"); 620 } 621 return false; 622 } 623 624 /** 625 * Retrieves the authenticator token for binding keys to the lifecycle 626 * of the current set of fingerprints. Used only by internal clients. 627 * 628 * @hide 629 */ 630 public long getAuthenticatorId() { 631 if (mService != null) { 632 try { 633 return mService.getAuthenticatorId(mContext.getOpPackageName()); 634 } catch (RemoteException e) { 635 Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e); 636 } 637 } else { 638 Log.w(TAG, "getAuthenticatorId(): Service not connected!"); 639 } 640 return 0; 641 } 642 643 private class MyHandler extends Handler { 644 private MyHandler(Context context) { 645 super(context.getMainLooper()); 646 } 647 648 private MyHandler(Looper looper) { 649 super(looper); 650 } 651 652 public void handleMessage(android.os.Message msg) { 653 switch(msg.what) { 654 case MSG_ENROLL_RESULT: 655 sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */); 656 break; 657 case MSG_ACQUIRED: 658 sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */); 659 break; 660 case MSG_AUTHENTICATION_SUCCEEDED: 661 sendAuthenticatedSucceeded((Fingerprint) msg.obj); 662 break; 663 case MSG_AUTHENTICATION_FAILED: 664 sendAuthenticatedFailed(); 665 break; 666 case MSG_ERROR: 667 sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */); 668 break; 669 case MSG_REMOVED: 670 sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */, 671 msg.arg2 /* groupId */); 672 } 673 } 674 675 private void sendRemovedResult(long deviceId, int fingerId, int groupId) { 676 if (mRemovalCallback != null) { 677 int reqFingerId = mRemovalFingerprint.getFingerId(); 678 int reqGroupId = mRemovalFingerprint.getGroupId(); 679 if (fingerId != reqFingerId) { 680 Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId); 681 } 682 if (fingerId != reqFingerId) { 683 Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId); 684 } 685 mRemovalCallback.onRemovalSucceeded(mRemovalFingerprint); 686 } 687 } 688 689 private void sendErrorResult(long deviceId, int errMsgId) { 690 if (mEnrollmentCallback != null) { 691 mEnrollmentCallback.onEnrollmentError(errMsgId, getErrorString(errMsgId)); 692 } else if (mAuthenticationCallback != null) { 693 mAuthenticationCallback.onAuthenticationError(errMsgId, getErrorString(errMsgId)); 694 } else if (mRemovalCallback != null) { 695 mRemovalCallback.onRemovalError(mRemovalFingerprint, errMsgId, 696 getErrorString(errMsgId)); 697 } 698 } 699 700 private void sendEnrollResult(Fingerprint fp, int remaining) { 701 if (mEnrollmentCallback != null) { 702 mEnrollmentCallback.onEnrollmentProgress(remaining); 703 } 704 } 705 706 private void sendAuthenticatedSucceeded(Fingerprint fp) { 707 if (mAuthenticationCallback != null) { 708 final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp); 709 mAuthenticationCallback.onAuthenticationSucceeded(result); 710 } 711 } 712 713 private void sendAuthenticatedFailed() { 714 if (mAuthenticationCallback != null) { 715 mAuthenticationCallback.onAuthenticationFailed(); 716 } 717 } 718 719 private void sendAcquiredResult(long deviceId, int acquireInfo) { 720 final String msg = getAcquiredString(acquireInfo); 721 if (msg == null) return; 722 723 if (mEnrollmentCallback != null) { 724 mEnrollmentCallback.onEnrollmentHelp(acquireInfo, msg); 725 } else if (mAuthenticationCallback != null) { 726 mAuthenticationCallback.onAuthenticationHelp(acquireInfo, msg); 727 } 728 } 729 }; 730 731 /** 732 * @hide 733 */ 734 public FingerprintManager(Context context, IFingerprintService service) { 735 mContext = context; 736 mService = service; 737 if (mService == null) { 738 Slog.v(TAG, "FingerprintManagerService was null"); 739 } 740 mHandler = new MyHandler(context); 741 } 742 743 private int getCurrentUserId() { 744 try { 745 return ActivityManagerNative.getDefault().getCurrentUser().id; 746 } catch (RemoteException e) { 747 Log.w(TAG, "Failed to get current user id\n"); 748 return UserHandle.USER_NULL; 749 } 750 } 751 752 private void cancelEnrollment() { 753 if (mService != null) try { 754 mService.cancelEnrollment(mToken); 755 } catch (RemoteException e) { 756 if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment"); 757 } 758 } 759 760 private void cancelAuthentication(CryptoObject cryptoObject) { 761 if (mService != null) try { 762 mService.cancelAuthentication(mToken, mContext.getOpPackageName()); 763 } catch (RemoteException e) { 764 if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment"); 765 } 766 } 767 768 private String getErrorString(int errMsg) { 769 switch (errMsg) { 770 case FINGERPRINT_ERROR_UNABLE_TO_PROCESS: 771 return mContext.getString( 772 com.android.internal.R.string.fingerprint_error_unable_to_process); 773 case FINGERPRINT_ERROR_HW_UNAVAILABLE: 774 return mContext.getString( 775 com.android.internal.R.string.fingerprint_error_hw_not_available); 776 case FINGERPRINT_ERROR_NO_SPACE: 777 return mContext.getString( 778 com.android.internal.R.string.fingerprint_error_no_space); 779 case FINGERPRINT_ERROR_TIMEOUT: 780 return mContext.getString(com.android.internal.R.string.fingerprint_error_timeout); 781 case FINGERPRINT_ERROR_CANCELED: 782 return mContext.getString(com.android.internal.R.string.fingerprint_error_canceled); 783 case FINGERPRINT_ERROR_LOCKOUT: 784 return mContext.getString(com.android.internal.R.string.fingerprint_error_lockout); 785 default: 786 if (errMsg >= FINGERPRINT_ERROR_VENDOR_BASE) { 787 int msgNumber = errMsg - FINGERPRINT_ERROR_VENDOR_BASE; 788 String[] msgArray = mContext.getResources().getStringArray( 789 com.android.internal.R.array.fingerprint_error_vendor); 790 if (msgNumber < msgArray.length) { 791 return msgArray[msgNumber]; 792 } 793 } 794 return null; 795 } 796 } 797 798 private String getAcquiredString(int acquireInfo) { 799 switch (acquireInfo) { 800 case FINGERPRINT_ACQUIRED_GOOD: 801 return null; 802 case FINGERPRINT_ACQUIRED_PARTIAL: 803 return mContext.getString( 804 com.android.internal.R.string.fingerprint_acquired_partial); 805 case FINGERPRINT_ACQUIRED_INSUFFICIENT: 806 return mContext.getString( 807 com.android.internal.R.string.fingerprint_acquired_insufficient); 808 case FINGERPRINT_ACQUIRED_IMAGER_DIRTY: 809 return mContext.getString( 810 com.android.internal.R.string.fingerprint_acquired_imager_dirty); 811 case FINGERPRINT_ACQUIRED_TOO_SLOW: 812 return mContext.getString( 813 com.android.internal.R.string.fingerprint_acquired_too_slow); 814 case FINGERPRINT_ACQUIRED_TOO_FAST: 815 return mContext.getString( 816 com.android.internal.R.string.fingerprint_acquired_too_fast); 817 default: 818 if (acquireInfo >= FINGERPRINT_ACQUIRED_VENDOR_BASE) { 819 int msgNumber = acquireInfo - FINGERPRINT_ACQUIRED_VENDOR_BASE; 820 String[] msgArray = mContext.getResources().getStringArray( 821 com.android.internal.R.array.fingerprint_acquired_vendor); 822 if (msgNumber < msgArray.length) { 823 return msgArray[msgNumber]; 824 } 825 } 826 return null; 827 } 828 } 829 830 private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() { 831 832 @Override // binder call 833 public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) { 834 mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0, 835 new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget(); 836 } 837 838 @Override // binder call 839 public void onAcquired(long deviceId, int acquireInfo) { 840 mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget(); 841 } 842 843 @Override // binder call 844 public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) { 845 mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget(); 846 } 847 848 @Override // binder call 849 public void onAuthenticationFailed(long deviceId) { 850 mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();; 851 } 852 853 @Override // binder call 854 public void onError(long deviceId, int error) { 855 mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget(); 856 } 857 858 @Override // binder call 859 public void onRemoved(long deviceId, int fingerId, int groupId) { 860 mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget(); 861 } 862 }; 863 864} 865 866