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