Home | History | Annotate | Download | only in fingerprint
      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.annotation.SystemService;
     23 import android.app.ActivityManager;
     24 import android.content.Context;
     25 import android.os.Binder;
     26 import android.os.CancellationSignal;
     27 import android.os.CancellationSignal.OnCancelListener;
     28 import android.os.Handler;
     29 import android.os.IBinder;
     30 import android.os.IRemoteCallback;
     31 import android.os.Looper;
     32 import android.os.PowerManager;
     33 import android.os.RemoteException;
     34 import android.os.UserHandle;
     35 import android.security.keystore.AndroidKeyStoreProvider;
     36 import android.util.Log;
     37 import android.util.Slog;
     38 
     39 import java.security.Signature;
     40 import java.util.List;
     41 
     42 import javax.crypto.Cipher;
     43 import javax.crypto.Mac;
     44 
     45 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
     46 import static android.Manifest.permission.MANAGE_FINGERPRINT;
     47 import static android.Manifest.permission.USE_FINGERPRINT;
     48 
     49 /**
     50  * A class that coordinates access to the fingerprint hardware.
     51  */
     52 @SystemService(Context.FINGERPRINT_SERVICE)
     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     private static final int MSG_ENUMERATED = 106;
     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} call failed. Typically this will happen when the
    101      * 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      * This occurs after 5 failed attempts, and lasts for 30 seconds.
    110      */
    111     public static final int FINGERPRINT_ERROR_LOCKOUT = 7;
    112 
    113     /**
    114      * Hardware vendors may extend this list if there are conditions that do not fall under one of
    115      * the above categories. Vendors are responsible for providing error strings for these errors.
    116      * These messages are typically reserved for internal operations such as enrollment, but may be
    117      * used to express vendor errors not covered by the ones in fingerprint.h. Applications are
    118      * expected to show the error message string if they happen, but are advised not to rely on the
    119      * message id since they will be device and vendor-specific
    120      */
    121     public static final int FINGERPRINT_ERROR_VENDOR = 8;
    122 
    123     /**
    124      * The operation was canceled because FINGERPRINT_ERROR_LOCKOUT occurred too many times.
    125      * Fingerprint authentication is disabled until the user unlocks with strong authentication
    126      * (PIN/Pattern/Password)
    127      */
    128     public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9;
    129 
    130     /**
    131      * The user canceled the operation. Upon receiving this, applications should use alternate
    132      * authentication (e.g. a password). The application should also provide the means to return
    133      * to fingerprint authentication, such as a "use fingerprint" button.
    134      */
    135     public static final int FINGERPRINT_ERROR_USER_CANCELED = 10;
    136 
    137     /**
    138      * @hide
    139      */
    140     public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000;
    141 
    142     //
    143     // Image acquisition messages. Must agree with those in fingerprint.h
    144     //
    145 
    146     /**
    147      * The image acquired was good.
    148      */
    149     public static final int FINGERPRINT_ACQUIRED_GOOD = 0;
    150 
    151     /**
    152      * Only a partial fingerprint image was detected. During enrollment, the user should be
    153      * informed on what needs to happen to resolve this problem, e.g. "press firmly on sensor."
    154      */
    155     public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1;
    156 
    157     /**
    158      * The fingerprint image was too noisy to process due to a detected condition (i.e. dry skin) or
    159      * a possibly dirty sensor (See {@link #FINGERPRINT_ACQUIRED_IMAGER_DIRTY}).
    160      */
    161     public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2;
    162 
    163     /**
    164      * The fingerprint image was too noisy due to suspected or detected dirt on the sensor.
    165      * For example, it's reasonable return this after multiple
    166      * {@link #FINGERPRINT_ACQUIRED_INSUFFICIENT} or actual detection of dirt on the sensor
    167      * (stuck pixels, swaths, etc.). The user is expected to take action to clean the sensor
    168      * when this is returned.
    169      */
    170     public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3;
    171 
    172     /**
    173      * The fingerprint image was unreadable due to lack of motion. This is most appropriate for
    174      * linear array sensors that require a swipe motion.
    175      */
    176     public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4;
    177 
    178     /**
    179      * The fingerprint image was incomplete due to quick motion. While mostly appropriate for
    180      * linear array sensors,  this could also happen if the finger was moved during acquisition.
    181      * The user should be asked to move the finger slower (linear) or leave the finger on the sensor
    182      * longer.
    183      */
    184     public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5;
    185 
    186     /**
    187      * Hardware vendors may extend this list if there are conditions that do not fall under one of
    188      * the above categories. Vendors are responsible for providing error strings for these errors.
    189      * @hide
    190      */
    191     public static final int FINGERPRINT_ACQUIRED_VENDOR = 6;
    192     /**
    193      * @hide
    194      */
    195     public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
    196 
    197     private IFingerprintService mService;
    198     private Context mContext;
    199     private IBinder mToken = new Binder();
    200     private AuthenticationCallback mAuthenticationCallback;
    201     private EnrollmentCallback mEnrollmentCallback;
    202     private RemovalCallback mRemovalCallback;
    203     private EnumerateCallback mEnumerateCallback;
    204     private CryptoObject mCryptoObject;
    205     private Fingerprint mRemovalFingerprint;
    206     private Handler mHandler;
    207 
    208     private class OnEnrollCancelListener implements OnCancelListener {
    209         @Override
    210         public void onCancel() {
    211             cancelEnrollment();
    212         }
    213     }
    214 
    215     private class OnAuthenticationCancelListener implements OnCancelListener {
    216         private CryptoObject mCrypto;
    217 
    218         public OnAuthenticationCancelListener(CryptoObject crypto) {
    219             mCrypto = crypto;
    220         }
    221 
    222         @Override
    223         public void onCancel() {
    224             cancelAuthentication(mCrypto);
    225         }
    226     }
    227 
    228     /**
    229      * A wrapper class for the crypto objects supported by FingerprintManager. Currently the
    230      * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
    231      */
    232     public static final class CryptoObject {
    233 
    234         public CryptoObject(@NonNull Signature signature) {
    235             mCrypto = signature;
    236         }
    237 
    238         public CryptoObject(@NonNull Cipher cipher) {
    239             mCrypto = cipher;
    240         }
    241 
    242         public CryptoObject(@NonNull Mac mac) {
    243             mCrypto = mac;
    244         }
    245 
    246         /**
    247          * Get {@link Signature} object.
    248          * @return {@link Signature} object or null if this doesn't contain one.
    249          */
    250         public Signature getSignature() {
    251             return mCrypto instanceof Signature ? (Signature) mCrypto : null;
    252         }
    253 
    254         /**
    255          * Get {@link Cipher} object.
    256          * @return {@link Cipher} object or null if this doesn't contain one.
    257          */
    258         public Cipher getCipher() {
    259             return mCrypto instanceof Cipher ? (Cipher) mCrypto : null;
    260         }
    261 
    262         /**
    263          * Get {@link Mac} object.
    264          * @return {@link Mac} object or null if this doesn't contain one.
    265          */
    266         public Mac getMac() {
    267             return mCrypto instanceof Mac ? (Mac) mCrypto : null;
    268         }
    269 
    270         /**
    271          * @hide
    272          * @return the opId associated with this object or 0 if none
    273          */
    274         public long getOpId() {
    275             return mCrypto != null ?
    276                     AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0;
    277         }
    278 
    279         private final Object mCrypto;
    280     };
    281 
    282     /**
    283      * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject,
    284      *     CancellationSignal, int, AuthenticationCallback, Handler)}.
    285      */
    286     public static class AuthenticationResult {
    287         private Fingerprint mFingerprint;
    288         private CryptoObject mCryptoObject;
    289         private int mUserId;
    290 
    291         /**
    292          * Authentication result
    293          *
    294          * @param crypto the crypto object
    295          * @param fingerprint the recognized fingerprint data, if allowed.
    296          * @hide
    297          */
    298         public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint, int userId) {
    299             mCryptoObject = crypto;
    300             mFingerprint = fingerprint;
    301             mUserId = userId;
    302         }
    303 
    304         /**
    305          * Obtain the crypto object associated with this transaction
    306          * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject,
    307          *     CancellationSignal, int, AuthenticationCallback, Handler)}.
    308          */
    309         public CryptoObject getCryptoObject() { return mCryptoObject; }
    310 
    311         /**
    312          * Obtain the Fingerprint associated with this operation. Applications are strongly
    313          * discouraged from associating specific fingers with specific applications or operations.
    314          *
    315          * @hide
    316          */
    317         public Fingerprint getFingerprint() { return mFingerprint; }
    318 
    319         /**
    320          * Obtain the userId for which this fingerprint was authenticated.
    321          * @hide
    322          */
    323         public int getUserId() { return mUserId; }
    324     };
    325 
    326     /**
    327      * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject,
    328      * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link
    329      * FingerprintManager#authenticate(CryptoObject, CancellationSignal,
    330      * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to
    331      * fingerprint events.
    332      */
    333     public static abstract class AuthenticationCallback {
    334         /**
    335          * Called when an unrecoverable error has been encountered and the operation is complete.
    336          * No further callbacks will be made on this object.
    337          * @param errorCode An integer identifying the error message
    338          * @param errString A human-readable error string that can be shown in UI
    339          */
    340         public void onAuthenticationError(int errorCode, CharSequence errString) { }
    341 
    342         /**
    343          * Called when a recoverable error has been encountered during authentication. The help
    344          * string is provided to give the user guidance for what went wrong, such as
    345          * "Sensor dirty, please clean it."
    346          * @param helpCode An integer identifying the error message
    347          * @param helpString A human-readable string that can be shown in UI
    348          */
    349         public void onAuthenticationHelp(int helpCode, CharSequence helpString) { }
    350 
    351         /**
    352          * Called when a fingerprint is recognized.
    353          * @param result An object containing authentication-related data
    354          */
    355         public void onAuthenticationSucceeded(AuthenticationResult result) { }
    356 
    357         /**
    358          * Called when a fingerprint is valid but not recognized.
    359          */
    360         public void onAuthenticationFailed() { }
    361 
    362         /**
    363          * Called when a fingerprint image has been acquired, but wasn't processed yet.
    364          *
    365          * @param acquireInfo one of FINGERPRINT_ACQUIRED_* constants
    366          * @hide
    367          */
    368         public void onAuthenticationAcquired(int acquireInfo) {}
    369     };
    370 
    371     /**
    372      * Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback,
    373      * CancellationSignal, int). Users of {@link #FingerprintManager()}
    374      * must provide an implementation of this to {@link FingerprintManager#enroll(long,
    375      * CancellationSignal, int, EnrollmentCallback) for listening to fingerprint events.
    376      *
    377      * @hide
    378      */
    379     public static abstract class EnrollmentCallback {
    380         /**
    381          * Called when an unrecoverable error has been encountered and the operation is complete.
    382          * No further callbacks will be made on this object.
    383          * @param errMsgId An integer identifying the error message
    384          * @param errString A human-readable error string that can be shown in UI
    385          */
    386         public void onEnrollmentError(int errMsgId, CharSequence errString) { }
    387 
    388         /**
    389          * Called when a recoverable error has been encountered during enrollment. The help
    390          * string is provided to give the user guidance for what went wrong, such as
    391          * "Sensor dirty, please clean it" or what they need to do next, such as
    392          * "Touch sensor again."
    393          * @param helpMsgId An integer identifying the error message
    394          * @param helpString A human-readable string that can be shown in UI
    395          */
    396         public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { }
    397 
    398         /**
    399          * Called as each enrollment step progresses. Enrollment is considered complete when
    400          * remaining reaches 0. This function will not be called if enrollment fails. See
    401          * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)}
    402          * @param remaining The number of remaining steps
    403          */
    404         public void onEnrollmentProgress(int remaining) { }
    405     };
    406 
    407     /**
    408      * Callback structure provided to {@link #remove}. Users of {@link FingerprintManager} may
    409      * optionally provide an implementation of this to
    410      * {@link #remove(Fingerprint, int, RemovalCallback)} for listening to fingerprint template
    411      * removal events.
    412      *
    413      * @hide
    414      */
    415     public static abstract class RemovalCallback {
    416         /**
    417          * Called when the given fingerprint can't be removed.
    418          * @param fp The fingerprint that the call attempted to remove
    419          * @param errMsgId An associated error message id
    420          * @param errString An error message indicating why the fingerprint id can't be removed
    421          */
    422         public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { }
    423 
    424         /**
    425          * Called when a given fingerprint is successfully removed.
    426          * @param fp The fingerprint template that was removed.
    427          * @param remaining The number of fingerprints yet to be removed in this operation. If
    428          *         {@link #remove} is called on one fingerprint, this should be 0. If
    429          *         {@link #remove} is called on a group, this should be the number of remaining
    430          *         fingerprints in the group, and 0 after the last fingerprint is removed.
    431          */
    432         public void onRemovalSucceeded(Fingerprint fp, int remaining) { }
    433     };
    434 
    435     /**
    436      * Callback structure provided to {@link FingerprintManager#enumerate(int). Users of
    437      * {@link #FingerprintManager()} may optionally provide an implementation of this to
    438      * {@link FingerprintManager#enumerate(int, int, EnumerateCallback)} for listening to
    439      * fingerprint template removal events.
    440      *
    441      * @hide
    442      */
    443     public static abstract class EnumerateCallback {
    444         /**
    445          * Called when the given fingerprint can't be removed.
    446          * @param errMsgId An associated error message id
    447          * @param errString An error message indicating why the fingerprint id can't be removed
    448          */
    449         public void onEnumerateError(int errMsgId, CharSequence errString) { }
    450 
    451         /**
    452          * Called when a given fingerprint is successfully removed.
    453          * @param fingerprint the fingerprint template that was removed.
    454          */
    455         public void onEnumerate(Fingerprint fingerprint) { }
    456     };
    457 
    458     /**
    459      * @hide
    460      */
    461     public static abstract class LockoutResetCallback {
    462 
    463         /**
    464          * Called when lockout period expired and clients are allowed to listen for fingerprint
    465          * again.
    466          */
    467         public void onLockoutReset() { }
    468     };
    469 
    470     /**
    471      * Request authentication of a crypto object. This call warms up the fingerprint hardware
    472      * and starts scanning for a fingerprint. It terminates when
    473      * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
    474      * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
    475      * which point the object is no longer valid. The operation can be canceled by using the
    476      * provided cancel object.
    477      *
    478      * @param crypto object associated with the call or null if none required.
    479      * @param cancel an object that can be used to cancel authentication
    480      * @param flags optional flags; should be 0
    481      * @param callback an object to receive authentication events
    482      * @param handler an optional handler to handle callback events
    483      *
    484      * @throws IllegalArgumentException if the crypto operation is not supported or is not backed
    485      *         by <a href="{@docRoot}training/articles/keystore.html">Android Keystore
    486      *         facility</a>.
    487      * @throws IllegalStateException if the crypto primitive is not initialized.
    488      */
    489     @RequiresPermission(USE_FINGERPRINT)
    490     public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
    491             int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
    492         authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId());
    493     }
    494 
    495     /**
    496      * Use the provided handler thread for events.
    497      * @param handler
    498      */
    499     private void useHandler(Handler handler) {
    500         if (handler != null) {
    501             mHandler = new MyHandler(handler.getLooper());
    502         } else if (mHandler.getLooper() != mContext.getMainLooper()){
    503             mHandler = new MyHandler(mContext.getMainLooper());
    504         }
    505     }
    506 
    507     /**
    508      * Per-user version
    509      * @hide
    510      */
    511     @RequiresPermission(USE_FINGERPRINT)
    512     public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
    513             int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
    514         if (callback == null) {
    515             throw new IllegalArgumentException("Must supply an authentication callback");
    516         }
    517 
    518         if (cancel != null) {
    519             if (cancel.isCanceled()) {
    520                 Log.w(TAG, "authentication already canceled");
    521                 return;
    522             } else {
    523                 cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
    524             }
    525         }
    526 
    527         if (mService != null) try {
    528             useHandler(handler);
    529             mAuthenticationCallback = callback;
    530             mCryptoObject = crypto;
    531             long sessionId = crypto != null ? crypto.getOpId() : 0;
    532             mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,
    533                     mContext.getOpPackageName());
    534         } catch (RemoteException e) {
    535             Log.w(TAG, "Remote exception while authenticating: ", e);
    536             if (callback != null) {
    537                 // Though this may not be a hardware issue, it will cause apps to give up or try
    538                 // again later.
    539                 callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
    540                         getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */));
    541             }
    542         }
    543     }
    544 
    545     /**
    546      * Request fingerprint enrollment. This call warms up the fingerprint hardware
    547      * and starts scanning for fingerprints. Progress will be indicated by callbacks to the
    548      * {@link EnrollmentCallback} object. It terminates when
    549      * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or
    550      * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at
    551      * which point the object is no longer valid. The operation can be canceled by using the
    552      * provided cancel object.
    553      * @param token a unique token provided by a recent creation or verification of device
    554      * credentials (e.g. pin, pattern or password).
    555      * @param cancel an object that can be used to cancel enrollment
    556      * @param flags optional flags
    557      * @param userId the user to whom this fingerprint will belong to
    558      * @param callback an object to receive enrollment events
    559      * @hide
    560      */
    561     @RequiresPermission(MANAGE_FINGERPRINT)
    562     public void enroll(byte [] token, CancellationSignal cancel, int flags,
    563             int userId, EnrollmentCallback callback) {
    564         if (userId == UserHandle.USER_CURRENT) {
    565             userId = getCurrentUserId();
    566         }
    567         if (callback == null) {
    568             throw new IllegalArgumentException("Must supply an enrollment callback");
    569         }
    570 
    571         if (cancel != null) {
    572             if (cancel.isCanceled()) {
    573                 Log.w(TAG, "enrollment already canceled");
    574                 return;
    575             } else {
    576                 cancel.setOnCancelListener(new OnEnrollCancelListener());
    577             }
    578         }
    579 
    580         if (mService != null) try {
    581             mEnrollmentCallback = callback;
    582             mService.enroll(mToken, token, userId, mServiceReceiver, flags,
    583                     mContext.getOpPackageName());
    584         } catch (RemoteException e) {
    585             Log.w(TAG, "Remote exception in enroll: ", e);
    586             if (callback != null) {
    587                 // Though this may not be a hardware issue, it will cause apps to give up or try
    588                 // again later.
    589                 callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
    590                         getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */));
    591             }
    592         }
    593     }
    594 
    595     /**
    596      * Requests a pre-enrollment auth token to tie enrollment to the confirmation of
    597      * existing device credentials (e.g. pin/pattern/password).
    598      * @hide
    599      */
    600     @RequiresPermission(MANAGE_FINGERPRINT)
    601     public long preEnroll() {
    602         long result = 0;
    603         if (mService != null) try {
    604             result = mService.preEnroll(mToken);
    605         } catch (RemoteException e) {
    606             throw e.rethrowFromSystemServer();
    607         }
    608         return result;
    609     }
    610 
    611     /**
    612      * Finishes enrollment and cancels the current auth token.
    613      * @hide
    614      */
    615     @RequiresPermission(MANAGE_FINGERPRINT)
    616     public int postEnroll() {
    617         int result = 0;
    618         if (mService != null) try {
    619             result = mService.postEnroll(mToken);
    620         } catch (RemoteException e) {
    621             throw e.rethrowFromSystemServer();
    622         }
    623         return result;
    624     }
    625 
    626     /**
    627      * Sets the active user. This is meant to be used to select the current profile for enrollment
    628      * to allow separate enrolled fingers for a work profile
    629      * @param userId
    630      * @hide
    631      */
    632     @RequiresPermission(MANAGE_FINGERPRINT)
    633     public void setActiveUser(int userId) {
    634         if (mService != null) try {
    635             mService.setActiveUser(userId);
    636         } catch (RemoteException e) {
    637             throw e.rethrowFromSystemServer();
    638         }
    639     }
    640 
    641     /**
    642      * Remove given fingerprint template from fingerprint hardware and/or protected storage.
    643      * @param fp the fingerprint item to remove
    644      * @param userId the user who this fingerprint belongs to
    645      * @param callback an optional callback to verify that fingerprint templates have been
    646      * successfully removed. May be null of no callback is required.
    647      *
    648      * @hide
    649      */
    650     @RequiresPermission(MANAGE_FINGERPRINT)
    651     public void remove(Fingerprint fp, int userId, RemovalCallback callback) {
    652         if (mService != null) try {
    653             mRemovalCallback = callback;
    654             mRemovalFingerprint = fp;
    655             mService.remove(mToken, fp.getFingerId(), fp.getGroupId(), userId, mServiceReceiver);
    656         } catch (RemoteException e) {
    657             Log.w(TAG, "Remote exception in remove: ", e);
    658             if (callback != null) {
    659                 callback.onRemovalError(fp, FINGERPRINT_ERROR_HW_UNAVAILABLE,
    660                         getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */));
    661             }
    662         }
    663     }
    664 
    665     /**
    666      * Enumerate all fingerprint templates stored in hardware and/or protected storage.
    667      * @param userId the user who this fingerprint belongs to
    668      * @param callback an optional callback to verify that fingerprint templates have been
    669      * successfully removed. May be null of no callback is required.
    670      *
    671      * @hide
    672      */
    673     @RequiresPermission(MANAGE_FINGERPRINT)
    674     public void enumerate(int userId, @NonNull EnumerateCallback callback) {
    675         if (mService != null) try {
    676             mEnumerateCallback = callback;
    677             mService.enumerate(mToken, userId, mServiceReceiver);
    678         } catch (RemoteException e) {
    679             Log.w(TAG, "Remote exception in enumerate: ", e);
    680             if (callback != null) {
    681                 callback.onEnumerateError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
    682                         getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */));
    683             }
    684         }
    685     }
    686 
    687     /**
    688      * Renames the given fingerprint template
    689      * @param fpId the fingerprint id
    690      * @param userId the user who this fingerprint belongs to
    691      * @param newName the new name
    692      *
    693      * @hide
    694      */
    695     @RequiresPermission(MANAGE_FINGERPRINT)
    696     public void rename(int fpId, int userId, String newName) {
    697         // Renames the given fpId
    698         if (mService != null) {
    699             try {
    700                 mService.rename(fpId, userId, newName);
    701             } catch (RemoteException e) {
    702                 throw e.rethrowFromSystemServer();
    703             }
    704         } else {
    705             Log.w(TAG, "rename(): Service not connected!");
    706         }
    707     }
    708 
    709     /**
    710      * Obtain the list of enrolled fingerprints templates.
    711      * @return list of current fingerprint items
    712      *
    713      * @hide
    714      */
    715     @RequiresPermission(USE_FINGERPRINT)
    716     public List<Fingerprint> getEnrolledFingerprints(int userId) {
    717         if (mService != null) try {
    718             return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
    719         } catch (RemoteException e) {
    720             throw e.rethrowFromSystemServer();
    721         }
    722         return null;
    723     }
    724 
    725     /**
    726      * Obtain the list of enrolled fingerprints templates.
    727      * @return list of current fingerprint items
    728      *
    729      * @hide
    730      */
    731     @RequiresPermission(USE_FINGERPRINT)
    732     public List<Fingerprint> getEnrolledFingerprints() {
    733         return getEnrolledFingerprints(UserHandle.myUserId());
    734     }
    735 
    736     /**
    737      * Determine if there is at least one fingerprint enrolled.
    738      *
    739      * @return true if at least one fingerprint is enrolled, false otherwise
    740      */
    741     @RequiresPermission(USE_FINGERPRINT)
    742     public boolean hasEnrolledFingerprints() {
    743         if (mService != null) try {
    744             return mService.hasEnrolledFingerprints(
    745                     UserHandle.myUserId(), mContext.getOpPackageName());
    746         } catch (RemoteException e) {
    747             throw e.rethrowFromSystemServer();
    748         }
    749         return false;
    750     }
    751 
    752     /**
    753      * @hide
    754      */
    755     @RequiresPermission(allOf = {
    756             USE_FINGERPRINT,
    757             INTERACT_ACROSS_USERS})
    758     public boolean hasEnrolledFingerprints(int userId) {
    759         if (mService != null) try {
    760             return mService.hasEnrolledFingerprints(userId, mContext.getOpPackageName());
    761         } catch (RemoteException e) {
    762             throw e.rethrowFromSystemServer();
    763         }
    764         return false;
    765     }
    766 
    767     /**
    768      * Determine if fingerprint hardware is present and functional.
    769      *
    770      * @return true if hardware is present and functional, false otherwise.
    771      */
    772     @RequiresPermission(USE_FINGERPRINT)
    773     public boolean isHardwareDetected() {
    774         if (mService != null) {
    775             try {
    776                 long deviceId = 0; /* TODO: plumb hardware id to FPMS */
    777                 return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
    778             } catch (RemoteException e) {
    779                 throw e.rethrowFromSystemServer();
    780             }
    781         } else {
    782             Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
    783         }
    784         return false;
    785     }
    786 
    787     /**
    788      * Retrieves the authenticator token for binding keys to the lifecycle
    789      * of the calling user's fingerprints. Used only by internal clients.
    790      *
    791      * @hide
    792      */
    793     public long getAuthenticatorId() {
    794         if (mService != null) {
    795             try {
    796                 return mService.getAuthenticatorId(mContext.getOpPackageName());
    797             } catch (RemoteException e) {
    798                 throw e.rethrowFromSystemServer();
    799             }
    800         } else {
    801             Log.w(TAG, "getAuthenticatorId(): Service not connected!");
    802         }
    803         return 0;
    804     }
    805 
    806     /**
    807      * Reset the lockout timer when asked to do so by keyguard.
    808      *
    809      * @param token an opaque token returned by password confirmation.
    810      *
    811      * @hide
    812      */
    813     public void resetTimeout(byte[] token) {
    814         if (mService != null) {
    815             try {
    816                 mService.resetTimeout(token);
    817             } catch (RemoteException e) {
    818                 throw e.rethrowFromSystemServer();
    819             }
    820         } else {
    821             Log.w(TAG, "resetTimeout(): Service not connected!");
    822         }
    823     }
    824 
    825     /**
    826      * @hide
    827      */
    828     public void addLockoutResetCallback(final LockoutResetCallback callback) {
    829         if (mService != null) {
    830             try {
    831                 final PowerManager powerManager = mContext.getSystemService(PowerManager.class);
    832                 mService.addLockoutResetCallback(
    833                         new IFingerprintServiceLockoutResetCallback.Stub() {
    834 
    835                     @Override
    836                     public void onLockoutReset(long deviceId, IRemoteCallback serverCallback)
    837                             throws RemoteException {
    838                         try {
    839                             final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
    840                                     PowerManager.PARTIAL_WAKE_LOCK, "lockoutResetCallback");
    841                             wakeLock.acquire();
    842                             mHandler.post(() -> {
    843                                 try {
    844                                     callback.onLockoutReset();
    845                                 } finally {
    846                                     wakeLock.release();
    847                                 }
    848                             });
    849                         } finally {
    850                             serverCallback.sendResult(null /* data */);
    851                         }
    852                     }
    853                 });
    854             } catch (RemoteException e) {
    855                 throw e.rethrowFromSystemServer();
    856             }
    857         } else {
    858             Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
    859         }
    860     }
    861 
    862     private class MyHandler extends Handler {
    863         private MyHandler(Context context) {
    864             super(context.getMainLooper());
    865         }
    866 
    867         private MyHandler(Looper looper) {
    868             super(looper);
    869         }
    870 
    871         @Override
    872         public void handleMessage(android.os.Message msg) {
    873             switch(msg.what) {
    874                 case MSG_ENROLL_RESULT:
    875                     sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
    876                     break;
    877                 case MSG_ACQUIRED:
    878                     sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */,
    879                             msg.arg2 /* vendorCode */);
    880                     break;
    881                 case MSG_AUTHENTICATION_SUCCEEDED:
    882                     sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */);
    883                     break;
    884                 case MSG_AUTHENTICATION_FAILED:
    885                     sendAuthenticatedFailed();
    886                     break;
    887                 case MSG_ERROR:
    888                     sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */,
    889                             msg.arg2 /* vendorCode */);
    890                     break;
    891                 case MSG_REMOVED:
    892                     sendRemovedResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
    893                     break;
    894                 case MSG_ENUMERATED:
    895                     sendEnumeratedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
    896                             msg.arg2 /* groupId */);
    897                     break;
    898             }
    899         }
    900 
    901         private void sendRemovedResult(Fingerprint fingerprint, int remaining) {
    902             if (mRemovalCallback == null) {
    903                 return;
    904             }
    905             if (fingerprint == null) {
    906                 Log.e(TAG, "Received MSG_REMOVED, but fingerprint is null");
    907                 return;
    908             }
    909 
    910             int fingerId = fingerprint.getFingerId();
    911             int reqFingerId = mRemovalFingerprint.getFingerId();
    912             if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) {
    913                 Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
    914                 return;
    915             }
    916             int groupId = fingerprint.getGroupId();
    917             int reqGroupId = mRemovalFingerprint.getGroupId();
    918             if (groupId != reqGroupId) {
    919                 Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
    920                 return;
    921             }
    922 
    923             mRemovalCallback.onRemovalSucceeded(fingerprint, remaining);
    924         }
    925 
    926         private void sendEnumeratedResult(long deviceId, int fingerId, int groupId) {
    927             if (mEnumerateCallback != null) {
    928                 mEnumerateCallback.onEnumerate(new Fingerprint(null, groupId, fingerId, deviceId));
    929             }
    930         }
    931 
    932         private void sendErrorResult(long deviceId, int errMsgId, int vendorCode) {
    933             // emulate HAL 2.1 behavior and send real errMsgId
    934             final int clientErrMsgId = errMsgId == FINGERPRINT_ERROR_VENDOR
    935                     ? (vendorCode + FINGERPRINT_ERROR_VENDOR_BASE) : errMsgId;
    936             if (mEnrollmentCallback != null) {
    937                 mEnrollmentCallback.onEnrollmentError(clientErrMsgId,
    938                         getErrorString(errMsgId, vendorCode));
    939             } else if (mAuthenticationCallback != null) {
    940                 mAuthenticationCallback.onAuthenticationError(clientErrMsgId,
    941                         getErrorString(errMsgId, vendorCode));
    942             } else if (mRemovalCallback != null) {
    943                 mRemovalCallback.onRemovalError(mRemovalFingerprint, clientErrMsgId,
    944                         getErrorString(errMsgId, vendorCode));
    945             } else if (mEnumerateCallback != null) {
    946                 mEnumerateCallback.onEnumerateError(clientErrMsgId,
    947                         getErrorString(errMsgId, vendorCode));
    948             }
    949         }
    950 
    951         private void sendEnrollResult(Fingerprint fp, int remaining) {
    952             if (mEnrollmentCallback != null) {
    953                 mEnrollmentCallback.onEnrollmentProgress(remaining);
    954             }
    955         }
    956 
    957         private void sendAuthenticatedSucceeded(Fingerprint fp, int userId) {
    958             if (mAuthenticationCallback != null) {
    959                 final AuthenticationResult result =
    960                         new AuthenticationResult(mCryptoObject, fp, userId);
    961                 mAuthenticationCallback.onAuthenticationSucceeded(result);
    962             }
    963         }
    964 
    965         private void sendAuthenticatedFailed() {
    966             if (mAuthenticationCallback != null) {
    967                 mAuthenticationCallback.onAuthenticationFailed();
    968             }
    969         }
    970 
    971         private void sendAcquiredResult(long deviceId, int acquireInfo, int vendorCode) {
    972             if (mAuthenticationCallback != null) {
    973                 mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
    974             }
    975             final String msg = getAcquiredString(acquireInfo, vendorCode);
    976             if (msg == null) {
    977                 return;
    978             }
    979             // emulate HAL 2.1 behavior and send real acquiredInfo
    980             final int clientInfo = acquireInfo == FINGERPRINT_ACQUIRED_VENDOR
    981                     ? (vendorCode + FINGERPRINT_ACQUIRED_VENDOR_BASE) : acquireInfo;
    982             if (mEnrollmentCallback != null) {
    983                 mEnrollmentCallback.onEnrollmentHelp(clientInfo, msg);
    984             } else if (mAuthenticationCallback != null) {
    985                 mAuthenticationCallback.onAuthenticationHelp(clientInfo, msg);
    986             }
    987         }
    988     };
    989 
    990     /**
    991      * @hide
    992      */
    993     public FingerprintManager(Context context, IFingerprintService service) {
    994         mContext = context;
    995         mService = service;
    996         if (mService == null) {
    997             Slog.v(TAG, "FingerprintManagerService was null");
    998         }
    999         mHandler = new MyHandler(context);
   1000     }
   1001 
   1002     private int getCurrentUserId() {
   1003         try {
   1004             return ActivityManager.getService().getCurrentUser().id;
   1005         } catch (RemoteException e) {
   1006             throw e.rethrowFromSystemServer();
   1007         }
   1008     }
   1009 
   1010     private void cancelEnrollment() {
   1011         if (mService != null) try {
   1012             mService.cancelEnrollment(mToken);
   1013         } catch (RemoteException e) {
   1014             throw e.rethrowFromSystemServer();
   1015         }
   1016     }
   1017 
   1018     private void cancelAuthentication(CryptoObject cryptoObject) {
   1019         if (mService != null) try {
   1020             mService.cancelAuthentication(mToken, mContext.getOpPackageName());
   1021         } catch (RemoteException e) {
   1022             throw e.rethrowFromSystemServer();
   1023         }
   1024     }
   1025 
   1026     private String getErrorString(int errMsg, int vendorCode) {
   1027         switch (errMsg) {
   1028             case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
   1029                 return mContext.getString(
   1030                     com.android.internal.R.string.fingerprint_error_unable_to_process);
   1031             case FINGERPRINT_ERROR_HW_UNAVAILABLE:
   1032                 return mContext.getString(
   1033                     com.android.internal.R.string.fingerprint_error_hw_not_available);
   1034             case FINGERPRINT_ERROR_NO_SPACE:
   1035                 return mContext.getString(
   1036                     com.android.internal.R.string.fingerprint_error_no_space);
   1037             case FINGERPRINT_ERROR_TIMEOUT:
   1038                 return mContext.getString(com.android.internal.R.string.fingerprint_error_timeout);
   1039             case FINGERPRINT_ERROR_CANCELED:
   1040                 return mContext.getString(com.android.internal.R.string.fingerprint_error_canceled);
   1041             case FINGERPRINT_ERROR_LOCKOUT:
   1042                 return mContext.getString(com.android.internal.R.string.fingerprint_error_lockout);
   1043             case FINGERPRINT_ERROR_LOCKOUT_PERMANENT:
   1044                 return mContext.getString(
   1045                         com.android.internal.R.string.fingerprint_error_lockout_permanent);
   1046             case FINGERPRINT_ERROR_VENDOR: {
   1047                     String[] msgArray = mContext.getResources().getStringArray(
   1048                             com.android.internal.R.array.fingerprint_error_vendor);
   1049                     if (vendorCode < msgArray.length) {
   1050                         return msgArray[vendorCode];
   1051                     }
   1052                 }
   1053         }
   1054         Slog.w(TAG, "Invalid error message: " + errMsg + ", " + vendorCode);
   1055         return null;
   1056     }
   1057 
   1058     private String getAcquiredString(int acquireInfo, int vendorCode) {
   1059         switch (acquireInfo) {
   1060             case FINGERPRINT_ACQUIRED_GOOD:
   1061                 return null;
   1062             case FINGERPRINT_ACQUIRED_PARTIAL:
   1063                 return mContext.getString(
   1064                     com.android.internal.R.string.fingerprint_acquired_partial);
   1065             case FINGERPRINT_ACQUIRED_INSUFFICIENT:
   1066                 return mContext.getString(
   1067                     com.android.internal.R.string.fingerprint_acquired_insufficient);
   1068             case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
   1069                 return mContext.getString(
   1070                     com.android.internal.R.string.fingerprint_acquired_imager_dirty);
   1071             case FINGERPRINT_ACQUIRED_TOO_SLOW:
   1072                 return mContext.getString(
   1073                     com.android.internal.R.string.fingerprint_acquired_too_slow);
   1074             case FINGERPRINT_ACQUIRED_TOO_FAST:
   1075                 return mContext.getString(
   1076                     com.android.internal.R.string.fingerprint_acquired_too_fast);
   1077             case FINGERPRINT_ACQUIRED_VENDOR: {
   1078                     String[] msgArray = mContext.getResources().getStringArray(
   1079                             com.android.internal.R.array.fingerprint_acquired_vendor);
   1080                     if (vendorCode < msgArray.length) {
   1081                         return msgArray[vendorCode];
   1082                     }
   1083                 }
   1084         }
   1085         Slog.w(TAG, "Invalid acquired message: " + acquireInfo + ", " + vendorCode);
   1086         return null;
   1087     }
   1088 
   1089     private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
   1090 
   1091         @Override // binder call
   1092         public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
   1093             mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
   1094                     new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
   1095         }
   1096 
   1097         @Override // binder call
   1098         public void onAcquired(long deviceId, int acquireInfo, int vendorCode) {
   1099             mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode, deviceId).sendToTarget();
   1100         }
   1101 
   1102         @Override // binder call
   1103         public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) {
   1104             mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, fp).sendToTarget();
   1105         }
   1106 
   1107         @Override // binder call
   1108         public void onAuthenticationFailed(long deviceId) {
   1109             mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();
   1110         }
   1111 
   1112         @Override // binder call
   1113         public void onError(long deviceId, int error, int vendorCode) {
   1114             mHandler.obtainMessage(MSG_ERROR, error, vendorCode, deviceId).sendToTarget();
   1115         }
   1116 
   1117         @Override // binder call
   1118         public void onRemoved(long deviceId, int fingerId, int groupId, int remaining) {
   1119             mHandler.obtainMessage(MSG_REMOVED, remaining, 0,
   1120                     new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
   1121         }
   1122 
   1123         @Override // binder call
   1124         public void onEnumerated(long deviceId, int fingerId, int groupId, int remaining) {
   1125             // TODO: propagate remaining
   1126             mHandler.obtainMessage(MSG_ENUMERATED, fingerId, groupId, deviceId).sendToTarget();
   1127         }
   1128     };
   1129 
   1130 }
   1131