blob: ac488e303dd2c518380a82d985fa30a18d8f47b7 [file] [log] [blame]
Jim Millera75961472014-06-06 15:00:49 -07001/**
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 com.android.server.fingerprint;
18
Jim Miller9f0753f2015-03-23 23:59:22 -070019import android.content.ContentResolver;
Jim Millera75961472014-06-06 15:00:49 -070020import android.content.Context;
Jim Millera75961472014-06-06 15:00:49 -070021import android.os.Handler;
22import android.os.IBinder;
Jim Millerba67aee2015-02-20 16:21:26 -080023import android.os.Looper;
24import android.os.MessageQueue;
Jim Millera75961472014-06-06 15:00:49 -070025import android.os.RemoteException;
Jim Millera75961472014-06-06 15:00:49 -070026import android.util.ArrayMap;
27import android.util.Slog;
28
29import com.android.server.SystemService;
30
Jim Millerebbf2052015-03-31 17:24:34 -070031import android.hardware.fingerprint.FingerprintUtils;
32import android.hardware.fingerprint.Fingerprint;
33import android.hardware.fingerprint.FingerprintManager;
34import android.hardware.fingerprint.IFingerprintService;
35import android.hardware.fingerprint.IFingerprintServiceReceiver;
Jim Miller9f0753f2015-03-23 23:59:22 -070036
Jim Millerba67aee2015-02-20 16:21:26 -080037import static android.Manifest.permission.MANAGE_FINGERPRINT;
38import static android.Manifest.permission.USE_FINGERPRINT;
Jim Millera75961472014-06-06 15:00:49 -070039
Jim Millera75961472014-06-06 15:00:49 -070040import java.lang.ref.WeakReference;
Jim Miller9f0753f2015-03-23 23:59:22 -070041import java.util.ArrayList;
Jim Millerfe6439f2015-04-11 18:07:57 -070042import java.util.Arrays;
Jim Miller9f0753f2015-03-23 23:59:22 -070043import java.util.List;
Jim Millera75961472014-06-06 15:00:49 -070044
45/**
46 * A service to manage multiple clients that want to access the fingerprint HAL API.
47 * The service is responsible for maintaining a list of clients and dispatching all
48 * fingerprint -related events.
49 *
50 * @hide
51 */
52public class FingerprintService extends SystemService {
Jim Millerce7eb6d2015-04-03 19:29:13 -070053 private static final String TAG = "FingerprintService";
Jim Millera75961472014-06-06 15:00:49 -070054 private static final boolean DEBUG = true;
Jim Millerfe6439f2015-04-11 18:07:57 -070055 private ClientMonitor mAuthClient = null;
56 private ClientMonitor mEnrollClient = null;
57 private ClientMonitor mRemoveClient = null;
Jim Millera75961472014-06-06 15:00:49 -070058
59 private static final int MSG_NOTIFY = 10;
60
Jim Miller9f0753f2015-03-23 23:59:22 -070061 private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute
62
Jim Millerce7eb6d2015-04-03 19:29:13 -070063 // Message types. Used internally to dispatch messages to the correct callback.
64 // Must agree with the list in fingerprint.h
65 private static final int FINGERPRINT_ERROR = -1;
66 private static final int FINGERPRINT_ACQUIRED = 1;
Jim Millerce7eb6d2015-04-03 19:29:13 -070067 private static final int FINGERPRINT_TEMPLATE_ENROLLING = 3;
68 private static final int FINGERPRINT_TEMPLATE_REMOVED = 4;
69 private static final int FINGERPRINT_AUTHENTICATED = 5;
Jim Milleraf281ca2015-04-20 19:04:21 -070070 private static final long MS_PER_SEC = 1000;
71 private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
72 private static final int MAX_FAILED_ATTEMPTS = 5;
Jim Millerce7eb6d2015-04-03 19:29:13 -070073
Jim Millera75961472014-06-06 15:00:49 -070074 Handler mHandler = new Handler() {
75 public void handleMessage(android.os.Message msg) {
76 switch (msg.what) {
77 case MSG_NOTIFY:
Jim Miller9f0753f2015-03-23 23:59:22 -070078 FpHalMsg m = (FpHalMsg) msg.obj;
79 handleNotify(m.type, m.arg1, m.arg2, m.arg3);
Jim Millera75961472014-06-06 15:00:49 -070080 break;
81
82 default:
83 Slog.w(TAG, "Unknown message:" + msg.what);
84 }
85 }
86 };
87 private Context mContext;
Jim Millerba67aee2015-02-20 16:21:26 -080088 private int mHalDeviceId;
Jim Millerfe6439f2015-04-11 18:07:57 -070089 private int mFailedAttempts;
90 private final Runnable mLockoutReset = new Runnable() {
91 @Override
92 public void run() {
93 resetFailedAttempts();
94 }
95 };
Jim Millera75961472014-06-06 15:00:49 -070096
Jim Millera75961472014-06-06 15:00:49 -070097 public FingerprintService(Context context) {
98 super(context);
99 mContext = context;
Jim Millerba67aee2015-02-20 16:21:26 -0800100 nativeInit(Looper.getMainLooper().getQueue(), this);
Jim Millera75961472014-06-06 15:00:49 -0700101 }
102
103 // TODO: Move these into separate process
Jim Millerce7eb6d2015-04-03 19:29:13 -0700104 // JNI methods to communicate from FingerprintService to HAL
Jim Millerfe6439f2015-04-11 18:07:57 -0700105 static native int nativeEnroll(byte [] token, int groupId, int timeout);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700106 static native long nativePreEnroll();
107 static native int nativeStopEnrollment();
Jim Miller9f0753f2015-03-23 23:59:22 -0700108 static native int nativeAuthenticate(long sessionId, int groupId);
Jim Millerfe6439f2015-04-11 18:07:57 -0700109 static native int nativeStopAuthentication();
Jim Miller9f0753f2015-03-23 23:59:22 -0700110 static native int nativeRemove(int fingerId, int groupId);
Jim Millerba67aee2015-02-20 16:21:26 -0800111 static native int nativeOpenHal();
112 static native int nativeCloseHal();
113 static native void nativeInit(MessageQueue queue, FingerprintService service);
Jim Millera75961472014-06-06 15:00:49 -0700114
Jim Miller9f0753f2015-03-23 23:59:22 -0700115 static final class FpHalMsg {
116 int type; // Type of the message. One of the constants in fingerprint.h
117 int arg1; // optional arguments
118 int arg2;
119 int arg3;
120
121 FpHalMsg(int type, int arg1, int arg2, int arg3) {
122 this.type = type;
123 this.arg1 = arg1;
124 this.arg2 = arg2;
125 this.arg3 = arg3;
126 }
Jim Millera75961472014-06-06 15:00:49 -0700127 }
128
Jim Millerce7eb6d2015-04-03 19:29:13 -0700129 /**
130 * Called from JNI to communicate messages from fingerprint HAL.
131 */
Jim Miller9f0753f2015-03-23 23:59:22 -0700132 void notify(int type, int arg1, int arg2, int arg3) {
133 mHandler.obtainMessage(MSG_NOTIFY, new FpHalMsg(type, arg1, arg2, arg3)).sendToTarget();
134 }
135
136 void handleNotify(int type, int arg1, int arg2, int arg3) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700137 Slog.v(TAG, "handleNotify(type=" + type + ", arg1=" + arg1 + ", arg2=" + arg2 + ")"
138 + ", mAuthClients = " + mAuthClient + ", mEnrollClient = " + mEnrollClient);
139 if (mEnrollClient != null) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700140 final IBinder token = mEnrollClient.token;
Jim Miller13041372015-04-16 14:48:55 -0700141 if (dispatchNotify(mEnrollClient, type, arg1, arg2, arg3)) {
142 stopEnrollment(token, false);
143 removeClient(mEnrollClient);
Jim Millera75961472014-06-06 15:00:49 -0700144 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700145 }
146 if (mAuthClient != null) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700147 final IBinder token = mAuthClient.token;
Jim Miller13041372015-04-16 14:48:55 -0700148 if (dispatchNotify(mAuthClient, type, arg1, arg2, arg3)) {
149 stopAuthentication(token, false);
150 removeClient(mAuthClient);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700151 }
152 }
153 if (mRemoveClient != null) {
Jim Miller13041372015-04-16 14:48:55 -0700154 if (dispatchNotify(mRemoveClient, type, arg1, arg2, arg3)) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700155 removeClient(mRemoveClient);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700156 }
157 }
158 }
159
Jim Miller13041372015-04-16 14:48:55 -0700160 /*
161 * Dispatch notify events to clients.
162 *
163 * @return true if the operation is done, i.e. authentication completed
164 */
165 boolean dispatchNotify(ClientMonitor clientMonitor, int type, int arg1, int arg2, int arg3) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700166 ContentResolver contentResolver = mContext.getContentResolver();
167 boolean operationCompleted = false;
Jim Miller13041372015-04-16 14:48:55 -0700168 int fpId;
169 int groupId;
170 int remaining;
171 int acquireInfo;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700172 switch (type) {
173 case FINGERPRINT_ERROR:
Jim Miller13041372015-04-16 14:48:55 -0700174 fpId = arg1;
175 operationCompleted = clientMonitor.sendError(fpId);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700176 break;
177 case FINGERPRINT_ACQUIRED:
Jim Miller13041372015-04-16 14:48:55 -0700178 acquireInfo = arg1;
179 operationCompleted = clientMonitor.sendAcquired(acquireInfo);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700180 break;
Jim Millerfe6439f2015-04-11 18:07:57 -0700181 case FINGERPRINT_AUTHENTICATED:
Jim Miller13041372015-04-16 14:48:55 -0700182 fpId = arg1;
183 groupId = arg2;
184 operationCompleted = clientMonitor.sendAuthenticated(fpId, groupId);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700185 break;
186 case FINGERPRINT_TEMPLATE_ENROLLING:
Jim Miller13041372015-04-16 14:48:55 -0700187 fpId = arg1;
188 groupId = arg2;
189 remaining = arg3;
190 operationCompleted = clientMonitor.sendEnrollResult(fpId, groupId, remaining);
191 if (remaining == 0) {
192 addTemplateForUser(clientMonitor, contentResolver, fpId);
193 operationCompleted = true; // enroll completed
Jim Millera75961472014-06-06 15:00:49 -0700194 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700195 break;
196 case FINGERPRINT_TEMPLATE_REMOVED:
Jim Miller13041372015-04-16 14:48:55 -0700197 fpId = arg1;
198 groupId = arg2;
199 operationCompleted = clientMonitor.sendRemoved(fpId, groupId);
200 if (fpId != 0) {
201 removeTemplateForUser(clientMonitor, contentResolver, fpId);
Jim Millera75961472014-06-06 15:00:49 -0700202 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700203 break;
204 }
205 return operationCompleted;
206 }
207
Jim Millerfe6439f2015-04-11 18:07:57 -0700208 private void removeClient(ClientMonitor clientMonitor) {
209 if (clientMonitor == null) return;
210 clientMonitor.destroy();
211 if (clientMonitor == mAuthClient) {
212 mAuthClient = null;
213 } else if (clientMonitor == mEnrollClient) {
214 mEnrollClient = null;
215 } else if (clientMonitor == mRemoveClient) {
216 mRemoveClient = null;
217 }
218 }
219
220 private boolean inLockoutMode() {
221 return mFailedAttempts > MAX_FAILED_ATTEMPTS;
222 }
223
224 private void resetFailedAttempts() {
Jim Miller13041372015-04-16 14:48:55 -0700225 if (DEBUG && inLockoutMode()) {
226 Slog.v(TAG, "Reset fingerprint lockout");
227 }
Jim Millerfe6439f2015-04-11 18:07:57 -0700228 mFailedAttempts = 0;
229 }
230
231 private boolean handleFailedAttempt(ClientMonitor clientMonitor) {
232 mFailedAttempts++;
233 if (mFailedAttempts > MAX_FAILED_ATTEMPTS) {
234 // Failing multiple times will continue to push out the lockout time.
235 mHandler.removeCallbacks(mLockoutReset);
236 mHandler.postDelayed(mLockoutReset, FAIL_LOCKOUT_TIMEOUT_MS);
237 if (clientMonitor != null
238 && !clientMonitor.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) {
239 Slog.w(TAG, "Cannot send lockout message to client");
240 }
241 return true;
242 }
243 return false;
244 }
245
246 private void removeTemplateForUser(ClientMonitor clientMonitor, ContentResolver contentResolver,
Jim Millerce7eb6d2015-04-03 19:29:13 -0700247 final int fingerId) {
248 FingerprintUtils.removeFingerprintIdForUser(fingerId, contentResolver,
Jim Millerfe6439f2015-04-11 18:07:57 -0700249 clientMonitor.userId);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700250 }
251
Jim Millerfe6439f2015-04-11 18:07:57 -0700252 private void addTemplateForUser(ClientMonitor clientMonitor, ContentResolver contentResolver,
Jim Millerce7eb6d2015-04-03 19:29:13 -0700253 final int fingerId) {
254 FingerprintUtils.addFingerprintIdForUser(contentResolver, fingerId,
Jim Millerfe6439f2015-04-11 18:07:57 -0700255 clientMonitor.userId);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700256 }
257
Jim Millerfe6439f2015-04-11 18:07:57 -0700258 void startEnrollment(IBinder token, byte[] cryptoToken, int groupId,
259 IFingerprintServiceReceiver receiver, int flags) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700260 stopPendingOperations();
Jim Millerfe6439f2015-04-11 18:07:57 -0700261 mEnrollClient = new ClientMonitor(token, receiver, groupId);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700262 final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
Jim Millerfe6439f2015-04-11 18:07:57 -0700263 final int result = nativeEnroll(cryptoToken, groupId, timeout);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700264 if (result != 0) {
265 Slog.w(TAG, "startEnroll failed, result=" + result);
Jim Millera75961472014-06-06 15:00:49 -0700266 }
267 }
268
Jim Millerce7eb6d2015-04-03 19:29:13 -0700269 public long startPreEnroll(IBinder token) {
270 return nativePreEnroll();
271 }
272
273 private void stopPendingOperations() {
274 if (mEnrollClient != null) {
Jim Miller13041372015-04-16 14:48:55 -0700275 stopEnrollment(mEnrollClient.token, true);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700276 }
277 if (mAuthClient != null) {
Jim Miller13041372015-04-16 14:48:55 -0700278 stopAuthentication(mAuthClient.token, true);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700279 }
280 // mRemoveClient is allowed to continue
281 }
282
Jim Miller13041372015-04-16 14:48:55 -0700283 void stopEnrollment(IBinder token, boolean notify) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700284 final ClientMonitor client = mEnrollClient;
285 if (client == null || client.token != token) return;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700286 int result = nativeStopEnrollment();
Jim Miller13041372015-04-16 14:48:55 -0700287 if (notify) {
288 client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
289 }
Jim Millerfe6439f2015-04-11 18:07:57 -0700290 removeClient(mEnrollClient);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700291 if (result != 0) {
292 Slog.w(TAG, "startEnrollCancel failed, result=" + result);
Jim Miller9f0753f2015-03-23 23:59:22 -0700293 }
294 }
295
Jim Millerce7eb6d2015-04-03 19:29:13 -0700296 void startAuthentication(IBinder token, long opId, int groupId,
297 IFingerprintServiceReceiver receiver, int flags) {
298 stopPendingOperations();
Jim Millerfe6439f2015-04-11 18:07:57 -0700299 mAuthClient = new ClientMonitor(token, receiver, groupId);
300 if (inLockoutMode()) {
301 Slog.v(TAG, "In lockout mode; disallowing authentication");
302 if (!mAuthClient.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) {
303 Slog.w(TAG, "Cannot send timeout message to client");
304 }
305 mAuthClient = null;
306 return;
307 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700308 final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
309 final int result = nativeAuthenticate(opId, groupId);
310 if (result != 0) {
311 Slog.w(TAG, "startAuthentication failed, result=" + result);
Jim Millera75961472014-06-06 15:00:49 -0700312 }
313 }
314
Jim Miller13041372015-04-16 14:48:55 -0700315 void stopAuthentication(IBinder token, boolean notify) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700316 final ClientMonitor client = mAuthClient;
317 if (client == null || client.token != token) return;
318 int result = nativeStopAuthentication();
Jim Miller13041372015-04-16 14:48:55 -0700319 if (notify) {
320 client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
321 }
Jim Millerfe6439f2015-04-11 18:07:57 -0700322 removeClient(mAuthClient);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700323 if (result != 0) {
324 Slog.w(TAG, "stopAuthentication failed, result=" + result);
Jim Millera75961472014-06-06 15:00:49 -0700325 }
326 }
327
Jim Millerce7eb6d2015-04-03 19:29:13 -0700328 void startRemove(IBinder token, int fingerId, int userId,
329 IFingerprintServiceReceiver receiver) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700330 mRemoveClient = new ClientMonitor(token, receiver, userId);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700331 // The fingerprint template ids will be removed when we get confirmation from the HAL
332 final int result = nativeRemove(fingerId, userId);
333 if (result != 0) {
334 Slog.w(TAG, "startRemove with id = " + fingerId + " failed with result=" + result);
Jim Millera75961472014-06-06 15:00:49 -0700335 }
336 }
337
Jim Miller9f0753f2015-03-23 23:59:22 -0700338 public List<Fingerprint> getEnrolledFingerprints(int groupId) {
339 ContentResolver resolver = mContext.getContentResolver();
340 int[] ids = FingerprintUtils.getFingerprintIdsForUser(resolver, groupId);
341 List<Fingerprint> result = new ArrayList<Fingerprint>();
342 for (int i = 0; i < ids.length; i++) {
343 // TODO: persist names in Settings
344 CharSequence name = "Finger" + ids[i];
345 final int group = 0; // TODO
346 final int fingerId = ids[i];
347 final long deviceId = 0; // TODO
348 Fingerprint item = new Fingerprint(name, 0, ids[i], 0);
349 result.add(item);
350 }
351 return result;
352 }
353
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700354 public boolean hasEnrolledFingerprints(int groupId) {
355 ContentResolver resolver = mContext.getContentResolver();
356 return FingerprintUtils.getFingerprintIdsForUser(resolver, groupId).length > 0;
357 }
358
Jim Millerba67aee2015-02-20 16:21:26 -0800359 void checkPermission(String permission) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700360 getContext().enforceCallingOrSelfPermission(permission,
361 "Must have " + permission + " permission.");
Jim Millera75961472014-06-06 15:00:49 -0700362 }
363
Jim Millerfe6439f2015-04-11 18:07:57 -0700364 private class ClientMonitor implements IBinder.DeathRecipient {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700365 IBinder token;
Jim Millerfe6439f2015-04-11 18:07:57 -0700366 WeakReference<IFingerprintServiceReceiver> receiver;
367 int userId;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700368
Jim Millerfe6439f2015-04-11 18:07:57 -0700369 public ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, int userId) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700370 this.token = token;
Jim Millerfe6439f2015-04-11 18:07:57 -0700371 this.receiver = new WeakReference<IFingerprintServiceReceiver>(receiver);
372 this.userId = userId;
373 try {
374 token.linkToDeath(this, 0);
375 } catch (RemoteException e) {
376 Slog.w(TAG, "caught remote exception in linkToDeath: ", e);
377 }
378 }
379
380 public void destroy() {
381 if (token != null) {
382 token.unlinkToDeath(this, 0);
383 token = null;
384 }
385 receiver = null;
386 }
387
388 public void binderDied() {
389 token = null;
390 removeClient(this);
391 }
392
393 protected void finalize() throws Throwable {
394 try {
395 if (token != null) {
396 if (DEBUG) Slog.w(TAG, "removing leaked reference: " + token);
397 removeClient(this);
398 }
399 } finally {
400 super.finalize();
401 }
402 }
403
Jim Miller13041372015-04-16 14:48:55 -0700404 /*
405 * @return true if we're done.
406 */
Jim Millerfe6439f2015-04-11 18:07:57 -0700407 private boolean sendRemoved(int fingerId, int groupId) {
408 IFingerprintServiceReceiver rx = receiver.get();
Jim Miller13041372015-04-16 14:48:55 -0700409 if (rx == null) return true; // client not listening
410 try {
411 rx.onRemoved(mHalDeviceId, fingerId, groupId);
412 return fingerId == 0;
413 } catch (RemoteException e) {
414 Slog.w(TAG, "Failed to notify Removed:", e);
Jim Millerfe6439f2015-04-11 18:07:57 -0700415 }
Jim Millerfe6439f2015-04-11 18:07:57 -0700416 return false;
417 }
418
Jim Miller13041372015-04-16 14:48:55 -0700419 /*
420 * @return true if we're done.
421 */
Jim Millerfe6439f2015-04-11 18:07:57 -0700422 private boolean sendEnrollResult(int fpId, int groupId, int remaining) {
423 IFingerprintServiceReceiver rx = receiver.get();
Jim Miller13041372015-04-16 14:48:55 -0700424 if (rx == null) return true; // client not listening
Jim Milleraf281ca2015-04-20 19:04:21 -0700425 FingerprintUtils.vibrateFingerprintSuccess(getContext());
Jim Miller13041372015-04-16 14:48:55 -0700426 try {
427 rx.onEnrollResult(mHalDeviceId, fpId, groupId, remaining);
428 return remaining == 0;
429 } catch (RemoteException e) {
430 Slog.w(TAG, "Failed to notify EnrollResult:", e);
431 return true;
Jim Millerfe6439f2015-04-11 18:07:57 -0700432 }
Jim Millerfe6439f2015-04-11 18:07:57 -0700433 }
434
Jim Miller13041372015-04-16 14:48:55 -0700435 /*
436 * @return true if we're done.
437 */
Jim Millerfe6439f2015-04-11 18:07:57 -0700438 private boolean sendAuthenticated(int fpId, int groupId) {
439 IFingerprintServiceReceiver rx = receiver.get();
Jim Miller13041372015-04-16 14:48:55 -0700440 boolean result = false;
Jim Millerfe6439f2015-04-11 18:07:57 -0700441 if (rx != null) {
442 try {
443 rx.onAuthenticated(mHalDeviceId, fpId, groupId);
Jim Millerfe6439f2015-04-11 18:07:57 -0700444 } catch (RemoteException e) {
Jim Miller13041372015-04-16 14:48:55 -0700445 Slog.w(TAG, "Failed to notify Authenticated:", e);
446 result = true; // client failed
Jim Millerfe6439f2015-04-11 18:07:57 -0700447 }
Jim Miller13041372015-04-16 14:48:55 -0700448 } else {
449 result = true; // client not listening
Jim Millerfe6439f2015-04-11 18:07:57 -0700450 }
Jim Miller13041372015-04-16 14:48:55 -0700451 if (fpId <= 0) {
Jim Milleraf281ca2015-04-20 19:04:21 -0700452 FingerprintUtils.vibrateFingerprintError(getContext());
Jim Miller13041372015-04-16 14:48:55 -0700453 result |= handleFailedAttempt(this);
454 } else {
Jim Milleraf281ca2015-04-20 19:04:21 -0700455 FingerprintUtils.vibrateFingerprintSuccess(getContext());
Jim Miller13041372015-04-16 14:48:55 -0700456 result |= true; // we have a valid fingerprint
457 mLockoutReset.run();
458 }
459 return result;
Jim Millerfe6439f2015-04-11 18:07:57 -0700460 }
461
Jim Miller13041372015-04-16 14:48:55 -0700462 /*
463 * @return true if we're done.
464 */
Jim Millerfe6439f2015-04-11 18:07:57 -0700465 private boolean sendAcquired(int acquiredInfo) {
466 IFingerprintServiceReceiver rx = receiver.get();
Jim Miller13041372015-04-16 14:48:55 -0700467 if (rx == null) return true; // client not listening
468 try {
469 rx.onAcquired(mHalDeviceId, acquiredInfo);
470 return false; // acquisition continues...
471 } catch (RemoteException e) {
472 Slog.w(TAG, "Failed to invoke sendAcquired:", e);
473 return true; // client failed
Jim Millerfe6439f2015-04-11 18:07:57 -0700474 }
Jim Millerfe6439f2015-04-11 18:07:57 -0700475 }
476
Jim Miller13041372015-04-16 14:48:55 -0700477 /*
478 * @return true if we're done.
479 */
Jim Millerfe6439f2015-04-11 18:07:57 -0700480 private boolean sendError(int error) {
481 IFingerprintServiceReceiver rx = receiver.get();
482 if (rx != null) {
483 try {
484 rx.onError(mHalDeviceId, error);
Jim Millerfe6439f2015-04-11 18:07:57 -0700485 } catch (RemoteException e) {
Jim Miller13041372015-04-16 14:48:55 -0700486 Slog.w(TAG, "Failed to invoke sendError:", e);
Jim Millerfe6439f2015-04-11 18:07:57 -0700487 }
488 }
Jim Miller13041372015-04-16 14:48:55 -0700489 return true; // errors always terminate progress
Jim Millerce7eb6d2015-04-03 19:29:13 -0700490 }
491 }
492
Jim Millera75961472014-06-06 15:00:49 -0700493 private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
Jim Miller9f0753f2015-03-23 23:59:22 -0700494 @Override
Jim Millerce7eb6d2015-04-03 19:29:13 -0700495 public long preEnroll(IBinder token) {
Jim Millerba67aee2015-02-20 16:21:26 -0800496 checkPermission(MANAGE_FINGERPRINT);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700497 return startPreEnroll(token);
Jim Millera75961472014-06-06 15:00:49 -0700498 }
499
Jim Millerebbf2052015-03-31 17:24:34 -0700500 @Override
Jim Miller9f0753f2015-03-23 23:59:22 -0700501 // Binder call
Jim Millerfe6439f2015-04-11 18:07:57 -0700502 public void enroll(final IBinder token, final byte[] cryptoToken, final int groupId,
Jim Millerce7eb6d2015-04-03 19:29:13 -0700503 final IFingerprintServiceReceiver receiver, final int flags) {
504 checkPermission(MANAGE_FINGERPRINT);
Jim Millerfe6439f2015-04-11 18:07:57 -0700505 final byte [] cryptoClone = Arrays.copyOf(cryptoToken, cryptoToken.length);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700506 mHandler.post(new Runnable() {
507 @Override
508 public void run() {
Jim Millerfe6439f2015-04-11 18:07:57 -0700509 startEnrollment(token, cryptoClone, groupId, receiver, flags);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700510 }
511 });
512 }
513
514 @Override
515 // Binder call
516 public void cancelEnrollment(final IBinder token) {
517 checkPermission(MANAGE_FINGERPRINT);
518 mHandler.post(new Runnable() {
519 @Override
520 public void run() {
Jim Miller13041372015-04-16 14:48:55 -0700521 stopEnrollment(token, true);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700522 }
523 });
524 }
525
526 @Override
527 // Binder call
528 public void authenticate(final IBinder token, final long opId, final int groupId,
529 final IFingerprintServiceReceiver receiver, final int flags) {
Jim Millera75961472014-06-06 15:00:49 -0700530 checkPermission(USE_FINGERPRINT);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700531 mHandler.post(new Runnable() {
532 @Override
533 public void run() {
534 startAuthentication(token, opId, groupId, receiver, flags);
535 }
536 });
537 }
538
539 @Override
540
541 // Binder call
542 public void cancelAuthentication(final IBinder token) {
543 checkPermission(USE_FINGERPRINT);
544 mHandler.post(new Runnable() {
545 @Override
546 public void run() {
Jim Miller13041372015-04-16 14:48:55 -0700547 stopAuthentication(token, true);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700548 }
549 });
Jim Millerba67aee2015-02-20 16:21:26 -0800550 }
Jim Miller99d60192015-03-11 17:41:58 -0700551
552 @Override
Jim Miller9f0753f2015-03-23 23:59:22 -0700553 // Binder call
Jim Millerce7eb6d2015-04-03 19:29:13 -0700554 public void remove(final IBinder token, final int fingerId, final int groupId,
555 final IFingerprintServiceReceiver receiver) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700556 checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
Jim Millerce7eb6d2015-04-03 19:29:13 -0700557 mHandler.post(new Runnable() {
558 @Override
559 public void run() {
560 startRemove(token, fingerId, groupId, receiver);
561 }
562 });
Jim Miller9f0753f2015-03-23 23:59:22 -0700563
Jim Miller9f0753f2015-03-23 23:59:22 -0700564 }
565
566 @Override
567 // Binder call
568 public boolean isHardwareDetected(long deviceId) {
569 checkPermission(USE_FINGERPRINT);
570 return mHalDeviceId != 0; // TODO
571 }
572
573 @Override
574 // Binder call
Jim Millerce7eb6d2015-04-03 19:29:13 -0700575 public void rename(final int fingerId, final int groupId, final String name) {
Jim Miller99d60192015-03-11 17:41:58 -0700576 checkPermission(MANAGE_FINGERPRINT);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700577 mHandler.post(new Runnable() {
578 @Override
579 public void run() {
580 Slog.w(TAG, "rename id=" + fingerId + ",gid=" + groupId + ",name=" + name);
581 }
582 });
Jim Miller99d60192015-03-11 17:41:58 -0700583 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700584
585 @Override
586 // Binder call
587 public List<Fingerprint> getEnrolledFingerprints(int groupId) {
588 checkPermission(USE_FINGERPRINT);
589 return FingerprintService.this.getEnrolledFingerprints(groupId);
590 }
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700591
592 @Override
593 // Binder call
594 public boolean hasEnrolledFingerprints(int groupId) {
595 checkPermission(USE_FINGERPRINT);
596 return FingerprintService.this.hasEnrolledFingerprints(groupId);
597 }
Jim Millera75961472014-06-06 15:00:49 -0700598 }
599
600 @Override
601 public void onStart() {
Jim Miller9f0753f2015-03-23 23:59:22 -0700602 publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
603 mHalDeviceId = nativeOpenHal();
604 if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
Jim Millera75961472014-06-06 15:00:49 -0700605 }
606
607}