blob: 0ca0c0e5ad278da67baf3d2abdde2863ca7a1813 [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;
70
Jim Millera75961472014-06-06 15:00:49 -070071 Handler mHandler = new Handler() {
72 public void handleMessage(android.os.Message msg) {
73 switch (msg.what) {
74 case MSG_NOTIFY:
Jim Miller9f0753f2015-03-23 23:59:22 -070075 FpHalMsg m = (FpHalMsg) msg.obj;
76 handleNotify(m.type, m.arg1, m.arg2, m.arg3);
Jim Millera75961472014-06-06 15:00:49 -070077 break;
78
79 default:
80 Slog.w(TAG, "Unknown message:" + msg.what);
81 }
82 }
83 };
84 private Context mContext;
Jim Millerba67aee2015-02-20 16:21:26 -080085 private int mHalDeviceId;
Jim Millerfe6439f2015-04-11 18:07:57 -070086 private int mFailedAttempts;
87 private final Runnable mLockoutReset = new Runnable() {
88 @Override
89 public void run() {
90 resetFailedAttempts();
91 }
92 };
Jim Millera75961472014-06-06 15:00:49 -070093
94 private static final int STATE_IDLE = 0;
Jim Miller9f0753f2015-03-23 23:59:22 -070095 private static final int STATE_AUTHENTICATING = 1;
Jim Millera75961472014-06-06 15:00:49 -070096 private static final int STATE_ENROLLING = 2;
97 private static final int STATE_REMOVING = 3;
98 private static final long MS_PER_SEC = 1000;
Jim Millerfe6439f2015-04-11 18:07:57 -070099 private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
100 private static final int MAX_FAILED_ATTEMPTS = 5;
Jim Millera75961472014-06-06 15:00:49 -0700101
102 public FingerprintService(Context context) {
103 super(context);
104 mContext = context;
Jim Millerba67aee2015-02-20 16:21:26 -0800105 nativeInit(Looper.getMainLooper().getQueue(), this);
Jim Millera75961472014-06-06 15:00:49 -0700106 }
107
108 // TODO: Move these into separate process
Jim Millerce7eb6d2015-04-03 19:29:13 -0700109 // JNI methods to communicate from FingerprintService to HAL
Jim Millerfe6439f2015-04-11 18:07:57 -0700110 static native int nativeEnroll(byte [] token, int groupId, int timeout);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700111 static native long nativePreEnroll();
112 static native int nativeStopEnrollment();
Jim Miller9f0753f2015-03-23 23:59:22 -0700113 static native int nativeAuthenticate(long sessionId, int groupId);
Jim Millerfe6439f2015-04-11 18:07:57 -0700114 static native int nativeStopAuthentication();
Jim Miller9f0753f2015-03-23 23:59:22 -0700115 static native int nativeRemove(int fingerId, int groupId);
Jim Millerba67aee2015-02-20 16:21:26 -0800116 static native int nativeOpenHal();
117 static native int nativeCloseHal();
118 static native void nativeInit(MessageQueue queue, FingerprintService service);
Jim Millera75961472014-06-06 15:00:49 -0700119
Jim Miller9f0753f2015-03-23 23:59:22 -0700120 static final class FpHalMsg {
121 int type; // Type of the message. One of the constants in fingerprint.h
122 int arg1; // optional arguments
123 int arg2;
124 int arg3;
125
126 FpHalMsg(int type, int arg1, int arg2, int arg3) {
127 this.type = type;
128 this.arg1 = arg1;
129 this.arg2 = arg2;
130 this.arg3 = arg3;
131 }
Jim Millera75961472014-06-06 15:00:49 -0700132 }
133
Jim Millerce7eb6d2015-04-03 19:29:13 -0700134 /**
135 * Called from JNI to communicate messages from fingerprint HAL.
136 */
Jim Miller9f0753f2015-03-23 23:59:22 -0700137 void notify(int type, int arg1, int arg2, int arg3) {
138 mHandler.obtainMessage(MSG_NOTIFY, new FpHalMsg(type, arg1, arg2, arg3)).sendToTarget();
139 }
140
141 void handleNotify(int type, int arg1, int arg2, int arg3) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700142 Slog.v(TAG, "handleNotify(type=" + type + ", arg1=" + arg1 + ", arg2=" + arg2 + ")"
143 + ", mAuthClients = " + mAuthClient + ", mEnrollClient = " + mEnrollClient);
144 if (mEnrollClient != null) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700145 final IBinder token = mEnrollClient.token;
146 if (doNotify(mEnrollClient, type, arg1, arg2, arg3)) {
147 stopEnrollment(token);
Jim Millera75961472014-06-06 15:00:49 -0700148 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700149 }
150 if (mAuthClient != null) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700151 final IBinder token = mAuthClient.token;
152 if (doNotify(mAuthClient, type, arg1, arg2, arg3)) {
153 stopAuthentication(token);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700154 }
155 }
156 if (mRemoveClient != null) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700157 if (doNotify(mRemoveClient, type, arg1, arg2, arg3)) {
158 removeClient(mRemoveClient);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700159 }
160 }
161 }
162
163 // Returns true if the operation is done, i.e. authentication completed
Jim Millerfe6439f2015-04-11 18:07:57 -0700164 boolean doNotify(ClientMonitor clientMonitor, int type, int arg1, int arg2, int arg3) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700165 ContentResolver contentResolver = mContext.getContentResolver();
166 boolean operationCompleted = false;
167 switch (type) {
168 case FINGERPRINT_ERROR:
Jim Millerfe6439f2015-04-11 18:07:57 -0700169 {
170 final int error = arg1;
171 clientMonitor.sendError(error);
172 removeClient(clientMonitor);
173 operationCompleted = true; // any error means the operation is done
Jim Millera75961472014-06-06 15:00:49 -0700174 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700175 break;
176 case FINGERPRINT_ACQUIRED:
Jim Millerfe6439f2015-04-11 18:07:57 -0700177 clientMonitor.sendAcquired(arg1 /* acquireInfo */);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700178 break;
Jim Millerfe6439f2015-04-11 18:07:57 -0700179 case FINGERPRINT_AUTHENTICATED:
180 {
181 final int fpId = arg1;
182 final int groupId = arg2;
183 clientMonitor.sendAuthenticated(fpId, groupId);
184 if (fpId == 0) {
185 if (clientMonitor == mAuthClient) {
186 operationCompleted = handleFailedAttempt(clientMonitor);
187 }
188 } else {
189 mLockoutReset.run(); // a valid fingerprint resets lockout
190 }
191 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700192 break;
193 case FINGERPRINT_TEMPLATE_ENROLLING:
194 {
195 final int fpId = arg1;
Jim Miller9f0753f2015-03-23 23:59:22 -0700196 final int groupId = arg2;
197 final int remaining = arg3;
Jim Millerfe6439f2015-04-11 18:07:57 -0700198 clientMonitor.sendEnrollResult(fpId, groupId, remaining);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700199 if (remaining == 0) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700200 addTemplateForUser(clientMonitor, contentResolver, fpId);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700201 operationCompleted = true; // enroll completed
Jim Millera75961472014-06-06 15:00:49 -0700202 }
Jim Millera75961472014-06-06 15:00:49 -0700203 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700204 break;
205 case FINGERPRINT_TEMPLATE_REMOVED:
206 {
207 final int fingerId = arg1;
208 final int groupId = arg2;
Jim Millerfe6439f2015-04-11 18:07:57 -0700209 removeTemplateForUser(clientMonitor, contentResolver, fingerId);
Jim Miller9f0753f2015-03-23 23:59:22 -0700210 if (fingerId == 0) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700211 operationCompleted = true; // remove completed
212 } else {
Jim Millerfe6439f2015-04-11 18:07:57 -0700213 clientMonitor.sendRemoved(fingerId, groupId);
Jim Miller9f0753f2015-03-23 23:59:22 -0700214 }
Jim Millera75961472014-06-06 15:00:49 -0700215 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700216 break;
217 }
218 return operationCompleted;
219 }
220
Jim Millerfe6439f2015-04-11 18:07:57 -0700221 private void removeClient(ClientMonitor clientMonitor) {
222 if (clientMonitor == null) return;
223 clientMonitor.destroy();
224 if (clientMonitor == mAuthClient) {
225 mAuthClient = null;
226 } else if (clientMonitor == mEnrollClient) {
227 mEnrollClient = null;
228 } else if (clientMonitor == mRemoveClient) {
229 mRemoveClient = null;
230 }
231 }
232
233 private boolean inLockoutMode() {
234 return mFailedAttempts > MAX_FAILED_ATTEMPTS;
235 }
236
237 private void resetFailedAttempts() {
238 if (DEBUG) Slog.v(TAG, "Reset fingerprint lockout");
239 mFailedAttempts = 0;
240 }
241
242 private boolean handleFailedAttempt(ClientMonitor clientMonitor) {
243 mFailedAttempts++;
244 if (mFailedAttempts > MAX_FAILED_ATTEMPTS) {
245 // Failing multiple times will continue to push out the lockout time.
246 mHandler.removeCallbacks(mLockoutReset);
247 mHandler.postDelayed(mLockoutReset, FAIL_LOCKOUT_TIMEOUT_MS);
248 if (clientMonitor != null
249 && !clientMonitor.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) {
250 Slog.w(TAG, "Cannot send lockout message to client");
251 }
252 return true;
253 }
254 return false;
255 }
256
257 private void removeTemplateForUser(ClientMonitor clientMonitor, ContentResolver contentResolver,
Jim Millerce7eb6d2015-04-03 19:29:13 -0700258 final int fingerId) {
259 FingerprintUtils.removeFingerprintIdForUser(fingerId, contentResolver,
Jim Millerfe6439f2015-04-11 18:07:57 -0700260 clientMonitor.userId);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700261 }
262
Jim Millerfe6439f2015-04-11 18:07:57 -0700263 private void addTemplateForUser(ClientMonitor clientMonitor, ContentResolver contentResolver,
Jim Millerce7eb6d2015-04-03 19:29:13 -0700264 final int fingerId) {
265 FingerprintUtils.addFingerprintIdForUser(contentResolver, fingerId,
Jim Millerfe6439f2015-04-11 18:07:57 -0700266 clientMonitor.userId);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700267 }
268
Jim Millerfe6439f2015-04-11 18:07:57 -0700269 void startEnrollment(IBinder token, byte[] cryptoToken, int groupId,
270 IFingerprintServiceReceiver receiver, int flags) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700271 stopPendingOperations();
Jim Millerfe6439f2015-04-11 18:07:57 -0700272 mEnrollClient = new ClientMonitor(token, receiver, groupId);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700273 final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
Jim Millerfe6439f2015-04-11 18:07:57 -0700274 final int result = nativeEnroll(cryptoToken, groupId, timeout);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700275 if (result != 0) {
276 Slog.w(TAG, "startEnroll failed, result=" + result);
Jim Millera75961472014-06-06 15:00:49 -0700277 }
278 }
279
Jim Millerce7eb6d2015-04-03 19:29:13 -0700280 public long startPreEnroll(IBinder token) {
281 return nativePreEnroll();
282 }
283
284 private void stopPendingOperations() {
285 if (mEnrollClient != null) {
286 stopEnrollment(mEnrollClient.token);
287 }
288 if (mAuthClient != null) {
289 stopAuthentication(mAuthClient.token);
290 }
291 // mRemoveClient is allowed to continue
292 }
293
294 void stopEnrollment(IBinder token) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700295 final ClientMonitor client = mEnrollClient;
296 if (client == null || client.token != token) return;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700297 int result = nativeStopEnrollment();
Jim Millerfe6439f2015-04-11 18:07:57 -0700298 client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
299 removeClient(mEnrollClient);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700300 if (result != 0) {
301 Slog.w(TAG, "startEnrollCancel failed, result=" + result);
Jim Miller9f0753f2015-03-23 23:59:22 -0700302 }
303 }
304
Jim Millerce7eb6d2015-04-03 19:29:13 -0700305 void startAuthentication(IBinder token, long opId, int groupId,
306 IFingerprintServiceReceiver receiver, int flags) {
307 stopPendingOperations();
Jim Millerfe6439f2015-04-11 18:07:57 -0700308 mAuthClient = new ClientMonitor(token, receiver, groupId);
309 if (inLockoutMode()) {
310 Slog.v(TAG, "In lockout mode; disallowing authentication");
311 if (!mAuthClient.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) {
312 Slog.w(TAG, "Cannot send timeout message to client");
313 }
314 mAuthClient = null;
315 return;
316 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700317 final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
318 final int result = nativeAuthenticate(opId, groupId);
319 if (result != 0) {
320 Slog.w(TAG, "startAuthentication failed, result=" + result);
Jim Millera75961472014-06-06 15:00:49 -0700321 }
322 }
323
Jim Millerce7eb6d2015-04-03 19:29:13 -0700324 void stopAuthentication(IBinder token) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700325 final ClientMonitor client = mAuthClient;
326 if (client == null || client.token != token) return;
327 int result = nativeStopAuthentication();
328 client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
329 removeClient(mAuthClient);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700330 if (result != 0) {
331 Slog.w(TAG, "stopAuthentication failed, result=" + result);
Jim Millera75961472014-06-06 15:00:49 -0700332 }
333 }
334
Jim Millerce7eb6d2015-04-03 19:29:13 -0700335 void startRemove(IBinder token, int fingerId, int userId,
336 IFingerprintServiceReceiver receiver) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700337 mRemoveClient = new ClientMonitor(token, receiver, userId);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700338 // The fingerprint template ids will be removed when we get confirmation from the HAL
339 final int result = nativeRemove(fingerId, userId);
340 if (result != 0) {
341 Slog.w(TAG, "startRemove with id = " + fingerId + " failed with result=" + result);
Jim Millera75961472014-06-06 15:00:49 -0700342 }
343 }
344
Jim Miller9f0753f2015-03-23 23:59:22 -0700345 public List<Fingerprint> getEnrolledFingerprints(int groupId) {
346 ContentResolver resolver = mContext.getContentResolver();
347 int[] ids = FingerprintUtils.getFingerprintIdsForUser(resolver, groupId);
348 List<Fingerprint> result = new ArrayList<Fingerprint>();
349 for (int i = 0; i < ids.length; i++) {
350 // TODO: persist names in Settings
351 CharSequence name = "Finger" + ids[i];
352 final int group = 0; // TODO
353 final int fingerId = ids[i];
354 final long deviceId = 0; // TODO
355 Fingerprint item = new Fingerprint(name, 0, ids[i], 0);
356 result.add(item);
357 }
358 return result;
359 }
360
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700361 public boolean hasEnrolledFingerprints(int groupId) {
362 ContentResolver resolver = mContext.getContentResolver();
363 return FingerprintUtils.getFingerprintIdsForUser(resolver, groupId).length > 0;
364 }
365
Jim Millerba67aee2015-02-20 16:21:26 -0800366 void checkPermission(String permission) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700367 getContext().enforceCallingOrSelfPermission(permission,
368 "Must have " + permission + " permission.");
Jim Millera75961472014-06-06 15:00:49 -0700369 }
370
Jim Millerfe6439f2015-04-11 18:07:57 -0700371 private class ClientMonitor implements IBinder.DeathRecipient {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700372 IBinder token;
Jim Millerfe6439f2015-04-11 18:07:57 -0700373 WeakReference<IFingerprintServiceReceiver> receiver;
374 int userId;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700375
Jim Millerfe6439f2015-04-11 18:07:57 -0700376 public ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, int userId) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700377 this.token = token;
Jim Millerfe6439f2015-04-11 18:07:57 -0700378 this.receiver = new WeakReference<IFingerprintServiceReceiver>(receiver);
379 this.userId = userId;
380 try {
381 token.linkToDeath(this, 0);
382 } catch (RemoteException e) {
383 Slog.w(TAG, "caught remote exception in linkToDeath: ", e);
384 }
385 }
386
387 public void destroy() {
388 if (token != null) {
389 token.unlinkToDeath(this, 0);
390 token = null;
391 }
392 receiver = null;
393 }
394
395 public void binderDied() {
396 token = null;
397 removeClient(this);
398 }
399
400 protected void finalize() throws Throwable {
401 try {
402 if (token != null) {
403 if (DEBUG) Slog.w(TAG, "removing leaked reference: " + token);
404 removeClient(this);
405 }
406 } finally {
407 super.finalize();
408 }
409 }
410
411 private boolean sendRemoved(int fingerId, int groupId) {
412 IFingerprintServiceReceiver rx = receiver.get();
413 if (rx != null) {
414 try {
415 rx.onRemoved(mHalDeviceId, fingerId, groupId);
416 return true;
417 } catch (RemoteException e) {
418 if (DEBUG) Slog.v(TAG, "Failed to invoke sendRemoved:", e);
419 }
420 }
421 removeClient(this);
422 return false;
423 }
424
425 private boolean sendEnrollResult(int fpId, int groupId, int remaining) {
426 IFingerprintServiceReceiver rx = receiver.get();
427 if (rx != null) {
428 try {
429 rx.onEnrollResult(mHalDeviceId, fpId, groupId, remaining);
430 return true;
431 } catch (RemoteException e) {
432 if (DEBUG) Slog.v(TAG, "Failed to invoke sendEnrollResult:", e);
433 }
434 }
435 removeClient(this);
436 return false;
437 }
438
439 private boolean sendAuthenticated(int fpId, int groupId) {
440 IFingerprintServiceReceiver rx = receiver.get();
441 if (rx != null) {
442 try {
443 rx.onAuthenticated(mHalDeviceId, fpId, groupId);
444 return true;
445 } catch (RemoteException e) {
446 if (DEBUG) Slog.v(TAG, "Failed to invoke sendProcessed:", e);
447 }
448 }
449 removeClient(this);
450 return false;
451 }
452
453 private boolean sendAcquired(int acquiredInfo) {
454 IFingerprintServiceReceiver rx = receiver.get();
455 if (rx != null) {
456 try {
457 rx.onAcquired(mHalDeviceId, acquiredInfo);
458 return true;
459 } catch (RemoteException e) {
460 if (DEBUG) Slog.v(TAG, "Failed to invoke sendAcquired:", e);
461 }
462 }
463 removeClient(this);
464 return false;
465 }
466
467 private boolean sendError(int error) {
468 IFingerprintServiceReceiver rx = receiver.get();
469 if (rx != null) {
470 try {
471 rx.onError(mHalDeviceId, error);
472 return true;
473 } catch (RemoteException e) {
474 if (DEBUG) Slog.v(TAG, "Failed to invoke sendError:", e);
475 }
476 }
477 removeClient(this);
478 return false;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700479 }
480 }
481
Jim Millera75961472014-06-06 15:00:49 -0700482 private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
Jim Miller9f0753f2015-03-23 23:59:22 -0700483 @Override
Jim Millerce7eb6d2015-04-03 19:29:13 -0700484 public long preEnroll(IBinder token) {
Jim Millerba67aee2015-02-20 16:21:26 -0800485 checkPermission(MANAGE_FINGERPRINT);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700486 return startPreEnroll(token);
Jim Millera75961472014-06-06 15:00:49 -0700487 }
488
Jim Millerebbf2052015-03-31 17:24:34 -0700489 @Override
Jim Miller9f0753f2015-03-23 23:59:22 -0700490 // Binder call
Jim Millerfe6439f2015-04-11 18:07:57 -0700491 public void enroll(final IBinder token, final byte[] cryptoToken, final int groupId,
Jim Millerce7eb6d2015-04-03 19:29:13 -0700492 final IFingerprintServiceReceiver receiver, final int flags) {
493 checkPermission(MANAGE_FINGERPRINT);
Jim Millerfe6439f2015-04-11 18:07:57 -0700494 final byte [] cryptoClone = Arrays.copyOf(cryptoToken, cryptoToken.length);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700495 mHandler.post(new Runnable() {
496 @Override
497 public void run() {
Jim Millerfe6439f2015-04-11 18:07:57 -0700498 startEnrollment(token, cryptoClone, groupId, receiver, flags);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700499 }
500 });
501 }
502
503 @Override
504 // Binder call
505 public void cancelEnrollment(final IBinder token) {
506 checkPermission(MANAGE_FINGERPRINT);
507 mHandler.post(new Runnable() {
508 @Override
509 public void run() {
510 stopEnrollment(token);
511 }
512 });
513 }
514
515 @Override
516 // Binder call
517 public void authenticate(final IBinder token, final long opId, final int groupId,
518 final IFingerprintServiceReceiver receiver, final int flags) {
Jim Millera75961472014-06-06 15:00:49 -0700519 checkPermission(USE_FINGERPRINT);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700520 mHandler.post(new Runnable() {
521 @Override
522 public void run() {
523 startAuthentication(token, opId, groupId, receiver, flags);
524 }
525 });
526 }
527
528 @Override
529
530 // Binder call
531 public void cancelAuthentication(final IBinder token) {
532 checkPermission(USE_FINGERPRINT);
533 mHandler.post(new Runnable() {
534 @Override
535 public void run() {
536 stopAuthentication(token);
537 }
538 });
Jim Millerba67aee2015-02-20 16:21:26 -0800539 }
Jim Miller99d60192015-03-11 17:41:58 -0700540
541 @Override
Jim Miller9f0753f2015-03-23 23:59:22 -0700542 // Binder call
Jim Millerce7eb6d2015-04-03 19:29:13 -0700543 public void remove(final IBinder token, final int fingerId, final int groupId,
544 final IFingerprintServiceReceiver receiver) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700545 checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
Jim Millerce7eb6d2015-04-03 19:29:13 -0700546 mHandler.post(new Runnable() {
547 @Override
548 public void run() {
549 startRemove(token, fingerId, groupId, receiver);
550 }
551 });
Jim Miller9f0753f2015-03-23 23:59:22 -0700552
Jim Miller9f0753f2015-03-23 23:59:22 -0700553 }
554
555 @Override
556 // Binder call
557 public boolean isHardwareDetected(long deviceId) {
558 checkPermission(USE_FINGERPRINT);
559 return mHalDeviceId != 0; // TODO
560 }
561
562 @Override
563 // Binder call
Jim Millerce7eb6d2015-04-03 19:29:13 -0700564 public void rename(final int fingerId, final int groupId, final String name) {
Jim Miller99d60192015-03-11 17:41:58 -0700565 checkPermission(MANAGE_FINGERPRINT);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700566 mHandler.post(new Runnable() {
567 @Override
568 public void run() {
569 Slog.w(TAG, "rename id=" + fingerId + ",gid=" + groupId + ",name=" + name);
570 }
571 });
Jim Miller99d60192015-03-11 17:41:58 -0700572 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700573
574 @Override
575 // Binder call
576 public List<Fingerprint> getEnrolledFingerprints(int groupId) {
577 checkPermission(USE_FINGERPRINT);
578 return FingerprintService.this.getEnrolledFingerprints(groupId);
579 }
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700580
581 @Override
582 // Binder call
583 public boolean hasEnrolledFingerprints(int groupId) {
584 checkPermission(USE_FINGERPRINT);
585 return FingerprintService.this.hasEnrolledFingerprints(groupId);
586 }
Jim Millera75961472014-06-06 15:00:49 -0700587 }
588
589 @Override
590 public void onStart() {
Jim Miller9f0753f2015-03-23 23:59:22 -0700591 publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
592 mHalDeviceId = nativeOpenHal();
593 if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
Jim Millera75961472014-06-06 15:00:49 -0700594 }
595
596}