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 }