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.service.fingerprint;
     18 
     19 import android.app.ActivityManagerNative;
     20 import android.content.ComponentName;
     21 import android.content.ContentResolver;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.ServiceConnection;
     25 import android.os.Binder;
     26 import android.os.Handler;
     27 import android.os.IBinder;
     28 import android.os.RemoteException;
     29 import android.os.UserHandle;
     30 import android.provider.Settings;
     31 import android.util.Log;
     32 import android.util.Slog;
     33 
     34 /**
     35  * A class that coordinates access to the fingerprint hardware.
     36  * @hide
     37  */
     38 
     39 public class FingerprintManager {
     40     private static final String TAG = "FingerprintManager";
     41     private static final boolean DEBUG = true;
     42     private static final int MSG_ENROLL_RESULT = 100;
     43     private static final int MSG_ACQUIRED = 101;
     44     private static final int MSG_PROCESSED = 102;
     45     private static final int MSG_ERROR = 103;
     46     private static final int MSG_REMOVED = 104;
     47 
     48     // Errors generated by layers above HAL
     49     public static final int FINGERPRINT_ERROR_NO_RECEIVER = -10;
     50 
     51     // Message types.  Must agree with HAL (fingerprint.h)
     52     public static final int FINGERPRINT_ERROR = -1;
     53     public static final int FINGERPRINT_ACQUIRED = 1;
     54     public static final int FINGERPRINT_PROCESSED = 2;
     55     public static final int FINGERPRINT_TEMPLATE_ENROLLING = 3;
     56     public static final int FINGERPRINT_TEMPLATE_REMOVED = 4;
     57 
     58     // Error messages. Must agree with HAL (fingerprint.h)
     59     public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1;
     60     public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2;
     61     public static final int FINGERPRINT_ERROR_TIMEOUT = 3;
     62     public static final int FINGERPRINT_ERROR_NO_SPACE = 4;
     63 
     64     // FINGERPRINT_ACQUIRED messages.  Must agree with HAL (fingerprint.h)
     65     public static final int FINGERPRINT_ACQUIRED_GOOD = 0;
     66     public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1;
     67     public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2;
     68     public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 4;
     69     public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 8;
     70     public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 16;
     71 
     72     private IFingerprintService mService;
     73     private FingerprintManagerReceiver mClientReceiver;
     74     private Context mContext;
     75     private IBinder mToken = new Binder();
     76 
     77     private Handler mHandler = new Handler() {
     78         public void handleMessage(android.os.Message msg) {
     79             if (mClientReceiver != null) {
     80                 switch(msg.what) {
     81                     case MSG_ENROLL_RESULT:
     82                         mClientReceiver.onEnrollResult(msg.arg1, msg.arg2);
     83                         break;
     84                     case MSG_ACQUIRED:
     85                         mClientReceiver.onAcquired(msg.arg1);
     86                         break;
     87                     case MSG_PROCESSED:
     88                         mClientReceiver.onProcessed(msg.arg1);
     89                         break;
     90                     case MSG_ERROR:
     91                         mClientReceiver.onError(msg.arg1);
     92                         break;
     93                     case MSG_REMOVED:
     94                         mClientReceiver.onRemoved(msg.arg1);
     95                 }
     96             }
     97         }
     98     };
     99 
    100     /**
    101      * @hide
    102      */
    103     public FingerprintManager(Context context, IFingerprintService service) {
    104         mContext = context;
    105         mService = service;
    106         if (mService == null) {
    107             Slog.v(TAG, "FingerprintManagerService was null");
    108         }
    109     }
    110 
    111     private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
    112 
    113         public void onEnrollResult(int fingerprintId,  int remaining) {
    114             mHandler.obtainMessage(MSG_ENROLL_RESULT, fingerprintId, remaining).sendToTarget();
    115         }
    116 
    117         public void onAcquired(int acquireInfo) {
    118             mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0).sendToTarget();
    119         }
    120 
    121         public void onProcessed(int fingerprintId) {
    122             mHandler.obtainMessage(MSG_PROCESSED, fingerprintId, 0).sendToTarget();
    123         }
    124 
    125         public void onError(int error) {
    126             mHandler.obtainMessage(MSG_ERROR, error, 0).sendToTarget();
    127         }
    128 
    129         public void onRemoved(int fingerprintId) {
    130             mHandler.obtainMessage(MSG_REMOVED, fingerprintId, 0).sendToTarget();
    131         }
    132     };
    133 
    134     /**
    135      * Determine whether the user has at least one fingerprint enrolled and enabled.
    136      *
    137      * @return true if at least one is enrolled and enabled
    138      */
    139     public boolean enrolledAndEnabled() {
    140         ContentResolver res = mContext.getContentResolver();
    141         return Settings.Secure.getInt(res, "fingerprint_enabled", 0) != 0
    142                 && FingerprintUtils.getFingerprintIdsForUser(res, getCurrentUserId()).length > 0;
    143     }
    144 
    145     /**
    146      * Start the enrollment process.  Timeout dictates how long to wait for the user to
    147      * enroll a fingerprint.
    148      *
    149      * @param timeout
    150      */
    151     public void enroll(long timeout) {
    152         if (mServiceReceiver == null) {
    153             sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0);
    154             return;
    155         }
    156         if (mService != null) try {
    157             mService.enroll(mToken, timeout, getCurrentUserId());
    158         } catch (RemoteException e) {
    159             Log.v(TAG, "Remote exception while enrolling: ", e);
    160             sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
    161         }
    162     }
    163 
    164     /**
    165      * Remove the given fingerprintId from the system.  FingerprintId of 0 has special meaning
    166      * which is to delete all fingerprint data for the current user. Use with caution.
    167      * @param fingerprintId
    168      */
    169     public void remove(int fingerprintId) {
    170         if (mServiceReceiver == null) {
    171             sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0);
    172             return;
    173         }
    174         if (mService != null) {
    175             try {
    176                 mService.remove(mToken, fingerprintId, getCurrentUserId());
    177             } catch (RemoteException e) {
    178                 Log.v(TAG, "Remote exception during remove of fingerprintId: " + fingerprintId, e);
    179             }
    180         } else {
    181             Log.w(TAG, "remove(): Service not connected!");
    182             sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
    183         }
    184     }
    185 
    186     /**
    187      * Starts listening for fingerprint events.  When a finger is scanned or recognized, the
    188      * client will be notified via the callback.
    189      */
    190     public void startListening(FingerprintManagerReceiver receiver) {
    191         mClientReceiver = receiver;
    192         if (mService != null) {
    193             try {
    194                 mService.startListening(mToken, mServiceReceiver, getCurrentUserId());
    195             } catch (RemoteException e) {
    196                 Log.v(TAG, "Remote exception in startListening(): ", e);
    197             }
    198         } else {
    199             Log.w(TAG, "startListening(): Service not connected!");
    200             sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
    201         }
    202     }
    203 
    204     private int getCurrentUserId() {
    205         try {
    206             return ActivityManagerNative.getDefault().getCurrentUser().id;
    207         } catch (RemoteException e) {
    208             Log.w(TAG, "Failed to get current user id\n");
    209             return UserHandle.USER_NULL;
    210         }
    211     }
    212 
    213     /**
    214      * Stops the client from listening to fingerprint events.
    215      */
    216     public void stopListening() {
    217         if (mService != null) {
    218             try {
    219                 mService.stopListening(mToken, getCurrentUserId());
    220                 mClientReceiver = null;
    221             } catch (RemoteException e) {
    222                 Log.v(TAG, "Remote exception in stopListening(): ", e);
    223             }
    224         } else {
    225             Log.w(TAG, "stopListening(): Service not connected!");
    226             sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
    227         }
    228     }
    229 
    230     public void enrollCancel() {
    231         if (mServiceReceiver == null) {
    232             sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0);
    233             return;
    234         }
    235         if (mService != null) {
    236             try {
    237                 mService.enrollCancel(mToken, getCurrentUserId());
    238                 mClientReceiver = null;
    239             } catch (RemoteException e) {
    240                 Log.v(TAG, "Remote exception in enrollCancel(): ", e);
    241                 sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
    242             }
    243         } else {
    244             Log.w(TAG, "enrollCancel(): Service not connected!");
    245         }
    246     }
    247 
    248     private void sendError(int msg, int arg1, int arg2) {
    249         mHandler.obtainMessage(msg, arg1, arg2);
    250     }
    251 }