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 com.android.server.biometrics.fingerprint;
18 
19 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
20 import static android.Manifest.permission.MANAGE_BIOMETRIC;
21 import static android.Manifest.permission.MANAGE_FINGERPRINT;
22 import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
23 import static android.Manifest.permission.USE_BIOMETRIC;
24 import static android.Manifest.permission.USE_FINGERPRINT;
25 
26 import android.app.ActivityManager;
27 import android.app.AlarmManager;
28 import android.app.AppOpsManager;
29 import android.app.PendingIntent;
30 import android.content.BroadcastReceiver;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.IntentFilter;
34 import android.content.pm.PackageManager;
35 import android.content.pm.UserInfo;
36 import android.hardware.biometrics.BiometricAuthenticator;
37 import android.hardware.biometrics.BiometricConstants;
38 import android.hardware.biometrics.BiometricsProtoEnums;
39 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
40 import android.hardware.biometrics.IBiometricServiceReceiverInternal;
41 import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
42 import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback;
43 import android.hardware.fingerprint.Fingerprint;
44 import android.hardware.fingerprint.FingerprintManager;
45 import android.hardware.fingerprint.IFingerprintClientActiveCallback;
46 import android.hardware.fingerprint.IFingerprintService;
47 import android.hardware.fingerprint.IFingerprintServiceReceiver;
48 import android.os.Binder;
49 import android.os.Build;
50 import android.os.Environment;
51 import android.os.IBinder;
52 import android.os.RemoteException;
53 import android.os.SELinux;
54 import android.os.SystemClock;
55 import android.os.UserHandle;
56 import android.os.UserManager;
57 import android.util.Slog;
58 import android.util.SparseBooleanArray;
59 import android.util.SparseIntArray;
60 import android.util.proto.ProtoOutputStream;
61 
62 import com.android.internal.annotations.GuardedBy;
63 import com.android.internal.logging.MetricsLogger;
64 import com.android.internal.util.DumpUtils;
65 import com.android.server.SystemServerInitThreadPool;
66 import com.android.server.biometrics.AuthenticationClient;
67 import com.android.server.biometrics.BiometricServiceBase;
68 import com.android.server.biometrics.BiometricUtils;
69 import com.android.server.biometrics.ClientMonitor;
70 import com.android.server.biometrics.Constants;
71 import com.android.server.biometrics.EnumerateClient;
72 import com.android.server.biometrics.RemovalClient;
73 
74 import org.json.JSONArray;
75 import org.json.JSONException;
76 import org.json.JSONObject;
77 
78 import java.io.File;
79 import java.io.FileDescriptor;
80 import java.io.PrintWriter;
81 import java.util.ArrayList;
82 import java.util.Collections;
83 import java.util.List;
84 import java.util.concurrent.CopyOnWriteArrayList;
85 
86 /**
87  * A service to manage multiple clients that want to access the fingerprint HAL API.
88  * The service is responsible for maintaining a list of clients and dispatching all
89  * fingerprint-related events.
90  *
91  * @hide
92  */
93 public class FingerprintService extends BiometricServiceBase {
94 
95     protected static final String TAG = "FingerprintService";
96     private static final boolean DEBUG = true;
97     private static final String FP_DATA_DIR = "fpdata";
98     private static final String ACTION_LOCKOUT_RESET =
99             "com.android.server.biometrics.fingerprint.ACTION_LOCKOUT_RESET";
100     private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 5;
101     private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 20;
102     private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30 * 1000;
103     private static final String KEY_LOCKOUT_RESET_USER = "lockout_reset_user";
104 
105     private final class ResetFailedAttemptsForUserRunnable implements Runnable {
106         @Override
run()107         public void run() {
108             resetFailedAttemptsForUser(true /* clearAttemptCounter */,
109                     ActivityManager.getCurrentUser());
110         }
111     }
112 
113     private final class LockoutReceiver extends BroadcastReceiver {
114         @Override
onReceive(Context context, Intent intent)115         public void onReceive(Context context, Intent intent) {
116             Slog.v(getTag(), "Resetting lockout: " + intent.getAction());
117             if (getLockoutResetIntent().equals(intent.getAction())) {
118                 final int user = intent.getIntExtra(KEY_LOCKOUT_RESET_USER, 0);
119                 resetFailedAttemptsForUser(false /* clearAttemptCounter */, user);
120             }
121         }
122     }
123 
124     private final class FingerprintAuthClient extends AuthenticationClientImpl {
125         @Override
isFingerprint()126         protected boolean isFingerprint() {
127             return true;
128         }
129 
FingerprintAuthClient(Context context, DaemonWrapper daemon, long halDeviceId, IBinder token, ServiceListener listener, int targetUserId, int groupId, long opId, boolean restricted, String owner, int cookie, boolean requireConfirmation)130         public FingerprintAuthClient(Context context,
131                 DaemonWrapper daemon, long halDeviceId, IBinder token,
132                 ServiceListener listener, int targetUserId, int groupId, long opId,
133                 boolean restricted, String owner, int cookie,
134                 boolean requireConfirmation) {
135             super(context, daemon, halDeviceId, token, listener, targetUserId, groupId, opId,
136                     restricted, owner, cookie, requireConfirmation);
137         }
138 
139         @Override
statsModality()140         protected int statsModality() {
141             return FingerprintService.this.statsModality();
142         }
143 
144         @Override
resetFailedAttempts()145         public void resetFailedAttempts() {
146             resetFailedAttemptsForUser(true /* clearAttemptCounter */,
147                     ActivityManager.getCurrentUser());
148         }
149 
150         @Override
shouldFrameworkHandleLockout()151         public boolean shouldFrameworkHandleLockout() {
152             return true;
153         }
154 
155         @Override
wasUserDetected()156         public boolean wasUserDetected() {
157             // TODO: Return a proper value for devices that use ERROR_TIMEOUT
158             return false;
159         }
160 
161         @Override
handleFailedAttempt()162         public int handleFailedAttempt() {
163             final int currentUser = ActivityManager.getCurrentUser();
164             mFailedAttempts.put(currentUser, mFailedAttempts.get(currentUser, 0) + 1);
165             mTimedLockoutCleared.put(ActivityManager.getCurrentUser(), false);
166 
167             if (getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) {
168                 scheduleLockoutResetForUser(currentUser);
169             }
170 
171             return super.handleFailedAttempt();
172         }
173     }
174 
175     /**
176      * Receives the incoming binder calls from FingerprintManager.
177      */
178     private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
179         private static final int ENROLL_TIMEOUT_SEC = 60;
180 
181         /**
182          * The following methods contain common code which is shared in biometrics/common.
183          */
184 
185         @Override // Binder call
preEnroll(IBinder token)186         public long preEnroll(IBinder token) {
187             checkPermission(MANAGE_FINGERPRINT);
188             return startPreEnroll(token);
189         }
190 
191         @Override // Binder call
postEnroll(IBinder token)192         public int postEnroll(IBinder token) {
193             checkPermission(MANAGE_FINGERPRINT);
194             return startPostEnroll(token);
195         }
196 
197         @Override // Binder call
enroll(final IBinder token, final byte[] cryptoToken, final int userId, final IFingerprintServiceReceiver receiver, final int flags, final String opPackageName)198         public void enroll(final IBinder token, final byte[] cryptoToken, final int userId,
199                 final IFingerprintServiceReceiver receiver, final int flags,
200                 final String opPackageName) {
201             checkPermission(MANAGE_FINGERPRINT);
202 
203             final boolean restricted = isRestricted();
204             final int groupId = userId; // default group for fingerprint enrollment
205             final EnrollClientImpl client = new EnrollClientImpl(getContext(), mDaemonWrapper,
206                     mHalDeviceId, token, new ServiceListenerImpl(receiver), mCurrentUserId, groupId,
207                     cryptoToken, restricted, opPackageName, new int[0] /* disabledFeatures */,
208                     ENROLL_TIMEOUT_SEC) {
209                 @Override
210                 public boolean shouldVibrate() {
211                     return true;
212                 }
213 
214                 @Override
215                 protected int statsModality() {
216                     return FingerprintService.this.statsModality();
217                 }
218             };
219 
220             enrollInternal(client, userId);
221         }
222 
223         @Override // Binder call
cancelEnrollment(final IBinder token)224         public void cancelEnrollment(final IBinder token) {
225             checkPermission(MANAGE_FINGERPRINT);
226             cancelEnrollmentInternal(token);
227         }
228 
229         @Override // Binder call
authenticate(final IBinder token, final long opId, final int groupId, final IFingerprintServiceReceiver receiver, final int flags, final String opPackageName)230         public void authenticate(final IBinder token, final long opId, final int groupId,
231                 final IFingerprintServiceReceiver receiver, final int flags,
232                 final String opPackageName) {
233             updateActiveGroup(groupId, opPackageName);
234             final boolean restricted = isRestricted();
235             final AuthenticationClientImpl client = new FingerprintAuthClient(getContext(),
236                     mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver),
237                     mCurrentUserId, groupId, opId, restricted, opPackageName,
238                     0 /* cookie */, false /* requireConfirmation */);
239             authenticateInternal(client, opId, opPackageName);
240         }
241 
242         @Override // Binder call
prepareForAuthentication(IBinder token, long opId, int groupId, IBiometricServiceReceiverInternal wrapperReceiver, String opPackageName, int cookie, int callingUid, int callingPid, int callingUserId)243         public void prepareForAuthentication(IBinder token, long opId, int groupId,
244                 IBiometricServiceReceiverInternal wrapperReceiver, String opPackageName,
245                 int cookie, int callingUid, int callingPid, int callingUserId) {
246             checkPermission(MANAGE_BIOMETRIC);
247             updateActiveGroup(groupId, opPackageName);
248             final boolean restricted = true; // BiometricPrompt is always restricted
249             final AuthenticationClientImpl client = new FingerprintAuthClient(getContext(),
250                     mDaemonWrapper, mHalDeviceId, token,
251                     new BiometricPromptServiceListenerImpl(wrapperReceiver),
252                     mCurrentUserId, groupId, opId, restricted, opPackageName, cookie,
253                     false /* requireConfirmation */);
254             authenticateInternal(client, opId, opPackageName, callingUid, callingPid,
255                     callingUserId);
256         }
257 
258         @Override // Binder call
startPreparedClient(int cookie)259         public void startPreparedClient(int cookie) {
260             checkPermission(MANAGE_BIOMETRIC);
261             startCurrentClient(cookie);
262         }
263 
264 
265         @Override // Binder call
cancelAuthentication(final IBinder token, final String opPackageName)266         public void cancelAuthentication(final IBinder token, final String opPackageName) {
267             cancelAuthenticationInternal(token, opPackageName);
268         }
269 
270         @Override // Binder call
cancelAuthenticationFromService(final IBinder token, final String opPackageName, int callingUid, int callingPid, int callingUserId, boolean fromClient)271         public void cancelAuthenticationFromService(final IBinder token, final String opPackageName,
272                 int callingUid, int callingPid, int callingUserId, boolean fromClient) {
273             checkPermission(MANAGE_BIOMETRIC);
274             cancelAuthenticationInternal(token, opPackageName, callingUid, callingPid,
275                     callingUserId, fromClient);
276         }
277 
278         @Override // Binder call
setActiveUser(final int userId)279         public void setActiveUser(final int userId) {
280             checkPermission(MANAGE_FINGERPRINT);
281             setActiveUserInternal(userId);
282         }
283 
284         @Override // Binder call
remove(final IBinder token, final int fingerId, final int groupId, final int userId, final IFingerprintServiceReceiver receiver)285         public void remove(final IBinder token, final int fingerId, final int groupId,
286                 final int userId, final IFingerprintServiceReceiver receiver) {
287             checkPermission(MANAGE_FINGERPRINT);
288 
289             if (token == null) {
290                 Slog.w(TAG, "remove(): token is null");
291                 return;
292             }
293 
294             final boolean restricted = isRestricted();
295             final RemovalClient client = new RemovalClient(getContext(), getConstants(),
296                     mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver),
297                     fingerId, groupId, userId, restricted, token.toString(), getBiometricUtils()) {
298                 @Override
299                 protected int statsModality() {
300                     return FingerprintService.this.statsModality();
301                 }
302             };
303             removeInternal(client);
304         }
305 
306         @Override // Binder call
enumerate(final IBinder token, final int userId, final IFingerprintServiceReceiver receiver)307         public void enumerate(final IBinder token, final int userId,
308                 final IFingerprintServiceReceiver receiver) {
309             checkPermission(MANAGE_FINGERPRINT);
310 
311             final boolean restricted = isRestricted();
312             final EnumerateClient client = new EnumerateClient(getContext(), getConstants(),
313                     mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver), userId,
314                     userId, restricted, getContext().getOpPackageName()) {
315                 @Override
316                 protected int statsModality() {
317                     return FingerprintService.this.statsModality();
318                 }
319             };
320             enumerateInternal(client);
321         }
322 
323         @Override
addLockoutResetCallback(final IBiometricServiceLockoutResetCallback callback)324         public void addLockoutResetCallback(final IBiometricServiceLockoutResetCallback callback)
325                 throws RemoteException {
326             FingerprintService.super.addLockoutResetCallback(callback);
327         }
328 
329         @Override // Binder call
dump(FileDescriptor fd, PrintWriter pw, String[] args)330         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
331             if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) {
332                 return;
333             }
334 
335             final long ident = Binder.clearCallingIdentity();
336             try {
337                 if (args.length > 0 && "--proto".equals(args[0])) {
338                     dumpProto(fd);
339                 } else {
340                     dumpInternal(pw);
341                 }
342             } finally {
343                 Binder.restoreCallingIdentity(ident);
344             }
345         }
346 
347         /**
348          * The following methods don't use any common code from BiometricService
349          */
350 
351         // TODO: refactor out common code here
352         @Override // Binder call
isHardwareDetected(long deviceId, String opPackageName)353         public boolean isHardwareDetected(long deviceId, String opPackageName) {
354             if (!canUseBiometric(opPackageName, false /* foregroundOnly */,
355                     Binder.getCallingUid(), Binder.getCallingPid(),
356                     UserHandle.getCallingUserId())) {
357                 return false;
358             }
359 
360             final long token = Binder.clearCallingIdentity();
361             try {
362                 IBiometricsFingerprint daemon = getFingerprintDaemon();
363                 return daemon != null && mHalDeviceId != 0;
364             } finally {
365                 Binder.restoreCallingIdentity(token);
366             }
367         }
368 
369         @Override // Binder call
rename(final int fingerId, final int groupId, final String name)370         public void rename(final int fingerId, final int groupId, final String name) {
371             checkPermission(MANAGE_FINGERPRINT);
372             if (!isCurrentUserOrProfile(groupId)) {
373                 return;
374             }
375             mHandler.post(new Runnable() {
376                 @Override
377                 public void run() {
378                     getBiometricUtils().renameBiometricForUser(getContext(), groupId,
379                             fingerId, name);
380                 }
381             });
382         }
383 
384         @Override // Binder call
getEnrolledFingerprints(int userId, String opPackageName)385         public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) {
386             if (!canUseBiometric(opPackageName, false /* foregroundOnly */,
387                     Binder.getCallingUid(), Binder.getCallingPid(),
388                     UserHandle.getCallingUserId())) {
389                 return Collections.emptyList();
390             }
391 
392             return FingerprintService.this.getEnrolledTemplates(userId);
393         }
394 
395         @Override // Binder call
hasEnrolledFingerprints(int userId, String opPackageName)396         public boolean hasEnrolledFingerprints(int userId, String opPackageName) {
397             if (!canUseBiometric(opPackageName, false /* foregroundOnly */,
398                     Binder.getCallingUid(), Binder.getCallingPid(),
399                     UserHandle.getCallingUserId())) {
400                 return false;
401             }
402 
403             return FingerprintService.this.hasEnrolledBiometrics(userId);
404         }
405 
406         @Override // Binder call
getAuthenticatorId(String opPackageName)407         public long getAuthenticatorId(String opPackageName) {
408             // In this method, we're not checking whether the caller is permitted to use fingerprint
409             // API because current authenticator ID is leaked (in a more contrived way) via Android
410             // Keystore (android.security.keystore package): the user of that API can create a key
411             // which requires fingerprint authentication for its use, and then query the key's
412             // characteristics (hidden API) which returns, among other things, fingerprint
413             // authenticator ID which was active at key creation time.
414             //
415             // Reason: The part of Android Keystore which runs inside an app's process invokes this
416             // method in certain cases. Those cases are not always where the developer demonstrates
417             // explicit intent to use fingerprint functionality. Thus, to avoiding throwing an
418             // unexpected SecurityException this method does not check whether its caller is
419             // permitted to use fingerprint API.
420             //
421             // The permission check should be restored once Android Keystore no longer invokes this
422             // method from inside app processes.
423 
424             return FingerprintService.super.getAuthenticatorId(opPackageName);
425         }
426 
427         @Override // Binder call
resetTimeout(byte [] token)428         public void resetTimeout(byte [] token) {
429             checkPermission(RESET_FINGERPRINT_LOCKOUT);
430 
431             if (!FingerprintService.this.hasEnrolledBiometrics(mCurrentUserId)) {
432                 Slog.w(TAG, "Ignoring lockout reset, no templates enrolled");
433                 return;
434             }
435 
436             // TODO: confirm security token when we move timeout management into the HAL layer.
437             mHandler.post(mResetFailedAttemptsForCurrentUserRunnable);
438         }
439 
440         @Override
isClientActive()441         public boolean isClientActive() {
442             checkPermission(MANAGE_FINGERPRINT);
443             synchronized(FingerprintService.this) {
444                 return (getCurrentClient() != null) || (getPendingClient() != null);
445             }
446         }
447 
448         @Override
addClientActiveCallback(IFingerprintClientActiveCallback callback)449         public void addClientActiveCallback(IFingerprintClientActiveCallback callback) {
450             checkPermission(MANAGE_FINGERPRINT);
451             mClientActiveCallbacks.add(callback);
452         }
453 
454         @Override
removeClientActiveCallback(IFingerprintClientActiveCallback callback)455         public void removeClientActiveCallback(IFingerprintClientActiveCallback callback) {
456             checkPermission(MANAGE_FINGERPRINT);
457             mClientActiveCallbacks.remove(callback);
458         }
459     }
460 
461     /**
462      * Receives callbacks from the ClientMonitor implementations. The results are forwarded to
463      * BiometricPrompt.
464      */
465     private class BiometricPromptServiceListenerImpl extends BiometricServiceListener {
BiometricPromptServiceListenerImpl(IBiometricServiceReceiverInternal wrapperReceiver)466         BiometricPromptServiceListenerImpl(IBiometricServiceReceiverInternal wrapperReceiver) {
467             super(wrapperReceiver);
468         }
469 
470         @Override
onAcquired(long deviceId, int acquiredInfo, int vendorCode)471         public void onAcquired(long deviceId, int acquiredInfo, int vendorCode)
472                 throws RemoteException {
473             if (getWrapperReceiver() != null) {
474                 getWrapperReceiver().onAcquired(acquiredInfo, FingerprintManager.getAcquiredString(
475                             getContext(), acquiredInfo, vendorCode));
476             }
477         }
478 
479         @Override
onError(long deviceId, int error, int vendorCode, int cookie)480         public void onError(long deviceId, int error, int vendorCode, int cookie)
481                 throws RemoteException {
482             if (getWrapperReceiver() != null) {
483                 getWrapperReceiver().onError(cookie, error,
484                         FingerprintManager.getErrorString(getContext(), error, vendorCode));
485             }
486         }
487     }
488 
489     /**
490      * Receives callbacks from the ClientMonitor implementations. The results are forwarded to
491      * the FingerprintManager.
492      */
493     private class ServiceListenerImpl implements ServiceListener {
494         private IFingerprintServiceReceiver mFingerprintServiceReceiver;
495 
ServiceListenerImpl(IFingerprintServiceReceiver receiver)496         public ServiceListenerImpl(IFingerprintServiceReceiver receiver) {
497             mFingerprintServiceReceiver = receiver;
498         }
499 
500         @Override
onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining)501         public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining)
502                 throws RemoteException {
503             if (mFingerprintServiceReceiver != null) {
504                 final Fingerprint fp = (Fingerprint) identifier;
505                 mFingerprintServiceReceiver.onEnrollResult(fp.getDeviceId(), fp.getBiometricId(),
506                         fp.getGroupId(), remaining);
507             }
508         }
509 
510         @Override
onAcquired(long deviceId, int acquiredInfo, int vendorCode)511         public void onAcquired(long deviceId, int acquiredInfo, int vendorCode)
512                 throws RemoteException {
513             if (mFingerprintServiceReceiver != null) {
514                 mFingerprintServiceReceiver.onAcquired(deviceId, acquiredInfo, vendorCode);
515             }
516         }
517 
518         @Override
onAuthenticationSucceeded(long deviceId, BiometricAuthenticator.Identifier biometric, int userId)519         public void onAuthenticationSucceeded(long deviceId,
520                 BiometricAuthenticator.Identifier biometric, int userId)
521                 throws RemoteException {
522             if (mFingerprintServiceReceiver != null) {
523                 if (biometric == null || biometric instanceof Fingerprint) {
524                     mFingerprintServiceReceiver
525                             .onAuthenticationSucceeded(deviceId, (Fingerprint) biometric, userId);
526                 } else {
527                     Slog.e(TAG, "onAuthenticationSucceeded received non-fingerprint biometric");
528                 }
529             }
530         }
531 
532         @Override
onAuthenticationFailed(long deviceId)533         public void onAuthenticationFailed(long deviceId) throws RemoteException {
534             if (mFingerprintServiceReceiver != null) {
535                 mFingerprintServiceReceiver.onAuthenticationFailed(deviceId);
536             }
537         }
538 
539         @Override
onError(long deviceId, int error, int vendorCode, int cookie)540         public void onError(long deviceId, int error, int vendorCode, int cookie)
541                 throws RemoteException {
542             if (mFingerprintServiceReceiver != null) {
543                 mFingerprintServiceReceiver.onError(deviceId, error, vendorCode);
544             }
545         }
546 
547         @Override
onRemoved(BiometricAuthenticator.Identifier identifier, int remaining)548         public void onRemoved(BiometricAuthenticator.Identifier identifier, int remaining)
549                 throws RemoteException {
550             if (mFingerprintServiceReceiver != null) {
551                 final Fingerprint fp = (Fingerprint) identifier;
552                 mFingerprintServiceReceiver.onRemoved(fp.getDeviceId(), fp.getBiometricId(),
553                         fp.getGroupId(), remaining);
554             }
555         }
556 
557         @Override
onEnumerated(BiometricAuthenticator.Identifier identifier, int remaining)558         public void onEnumerated(BiometricAuthenticator.Identifier identifier, int remaining)
559                 throws RemoteException {
560             if (mFingerprintServiceReceiver != null) {
561                 final Fingerprint fp = (Fingerprint) identifier;
562                 mFingerprintServiceReceiver.onEnumerated(fp.getDeviceId(), fp.getBiometricId(),
563                         fp.getGroupId(), remaining);
564             }
565         }
566     }
567 
568     private final FingerprintConstants mFingerprintConstants = new FingerprintConstants();
569     private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks =
570             new CopyOnWriteArrayList<>();
571 
572     @GuardedBy("this")
573     private IBiometricsFingerprint mDaemon;
574     private final SparseBooleanArray mTimedLockoutCleared;
575     private final SparseIntArray mFailedAttempts;
576     private final AlarmManager mAlarmManager;
577     private final LockoutReceiver mLockoutReceiver = new LockoutReceiver();
578     protected final ResetFailedAttemptsForUserRunnable mResetFailedAttemptsForCurrentUserRunnable =
579             new ResetFailedAttemptsForUserRunnable();
580 
581     /**
582      * Receives callbacks from the HAL.
583      */
584     private IBiometricsFingerprintClientCallback mDaemonCallback =
585             new IBiometricsFingerprintClientCallback.Stub() {
586         @Override
587         public void onEnrollResult(final long deviceId, final int fingerId, final int groupId,
588                 final int remaining) {
589             mHandler.post(() -> {
590                 final Fingerprint fingerprint =
591                         new Fingerprint(getBiometricUtils().getUniqueName(getContext(), groupId),
592                                 groupId, fingerId, deviceId);
593                 FingerprintService.super.handleEnrollResult(fingerprint, remaining);
594             });
595         }
596 
597         @Override
598         public void onAcquired(final long deviceId, final int acquiredInfo, final int vendorCode) {
599             mHandler.post(() -> {
600                 FingerprintService.super.handleAcquired(deviceId, acquiredInfo, vendorCode);
601             });
602         }
603 
604         @Override
605         public void onAuthenticated(final long deviceId, final int fingerId, final int groupId,
606                 ArrayList<Byte> token) {
607             mHandler.post(() -> {
608                 Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId);
609                 FingerprintService.super.handleAuthenticated(fp, token);
610             });
611         }
612 
613         @Override
614         public void onError(final long deviceId, final int error, final int vendorCode) {
615             mHandler.post(() -> {
616                 FingerprintService.super.handleError(deviceId, error, vendorCode);
617                 // TODO: this chunk of code should be common to all biometric services
618                 if (error == BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE) {
619                     // If we get HW_UNAVAILABLE, try to connect again later...
620                     Slog.w(TAG, "Got ERROR_HW_UNAVAILABLE; try reconnecting next client.");
621                     synchronized (this) {
622                         mDaemon = null;
623                         mHalDeviceId = 0;
624                         mCurrentUserId = UserHandle.USER_NULL;
625                     }
626                 }
627             });
628         }
629 
630         @Override
631         public void onRemoved(final long deviceId, final int fingerId, final int groupId,
632                 final int remaining) {
633             mHandler.post(() -> {
634                 ClientMonitor client = getCurrentClient();
635                 final Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId);
636                 FingerprintService.super.handleRemoved(fp, remaining);
637             });
638         }
639 
640         @Override
641         public void onEnumerate(final long deviceId, final int fingerId, final int groupId,
642                 final int remaining) {
643             mHandler.post(() -> {
644                 final Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId);
645                 FingerprintService.super.handleEnumerate(fp, remaining);
646             });
647 
648         }
649     };
650 
651     /**
652      * Wraps the HAL-specific code and is passed to the ClientMonitor implementations so that they
653      * can be shared between the multiple biometric services.
654      */
655     private final DaemonWrapper mDaemonWrapper = new DaemonWrapper() {
656         @Override
657         public int authenticate(long operationId, int groupId) throws RemoteException {
658             IBiometricsFingerprint daemon = getFingerprintDaemon();
659             if (daemon == null) {
660                 Slog.w(TAG, "authenticate(): no fingerprint HAL!");
661                 return ERROR_ESRCH;
662             }
663             return daemon.authenticate(operationId, groupId);
664         }
665 
666         @Override
667         public int cancel() throws RemoteException {
668             IBiometricsFingerprint daemon = getFingerprintDaemon();
669             if (daemon == null) {
670                 Slog.w(TAG, "cancel(): no fingerprint HAL!");
671                 return ERROR_ESRCH;
672             }
673             return daemon.cancel();
674         }
675 
676         @Override
677         public int remove(int groupId, int biometricId) throws RemoteException {
678             IBiometricsFingerprint daemon = getFingerprintDaemon();
679             if (daemon == null) {
680                 Slog.w(TAG, "remove(): no fingerprint HAL!");
681                 return ERROR_ESRCH;
682             }
683             return daemon.remove(groupId, biometricId);
684         }
685 
686         @Override
687         public int enumerate() throws RemoteException {
688             IBiometricsFingerprint daemon = getFingerprintDaemon();
689             if (daemon == null) {
690                 Slog.w(TAG, "enumerate(): no fingerprint HAL!");
691                 return ERROR_ESRCH;
692             }
693             return daemon.enumerate();
694         }
695 
696         @Override
697         public int enroll(byte[] cryptoToken, int groupId, int timeout,
698                 ArrayList<Integer> disabledFeatures) throws RemoteException {
699             IBiometricsFingerprint daemon = getFingerprintDaemon();
700             if (daemon == null) {
701                 Slog.w(TAG, "enroll(): no fingerprint HAL!");
702                 return ERROR_ESRCH;
703             }
704             return daemon.enroll(cryptoToken, groupId, timeout);
705         }
706 
707         @Override
708         public void resetLockout(byte[] token) throws RemoteException {
709             // TODO: confirm security token when we move timeout management into the HAL layer.
710             Slog.e(TAG, "Not supported");
711             return;
712         }
713     };
714 
FingerprintService(Context context)715     public FingerprintService(Context context) {
716         super(context);
717         mTimedLockoutCleared = new SparseBooleanArray();
718         mFailedAttempts = new SparseIntArray();
719         mAlarmManager = context.getSystemService(AlarmManager.class);
720         context.registerReceiver(mLockoutReceiver, new IntentFilter(getLockoutResetIntent()),
721                 getLockoutBroadcastPermission(), null /* handler */);
722     }
723 
724     @Override
onStart()725     public void onStart() {
726         super.onStart();
727         publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
728         SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart");
729     }
730 
731     @Override
getTag()732     protected String getTag() {
733         return TAG;
734     }
735 
736     @Override
getDaemonWrapper()737     protected DaemonWrapper getDaemonWrapper() {
738         return mDaemonWrapper;
739     }
740 
741     @Override
getBiometricUtils()742     protected BiometricUtils getBiometricUtils() {
743         return FingerprintUtils.getInstance();
744     }
745 
746     @Override
getConstants()747     protected Constants getConstants() {
748         return mFingerprintConstants;
749     }
750 
751     @Override
hasReachedEnrollmentLimit(int userId)752     protected boolean hasReachedEnrollmentLimit(int userId) {
753         final int limit = getContext().getResources().getInteger(
754                 com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
755         final int enrolled = FingerprintService.this.getEnrolledTemplates(userId).size();
756         if (enrolled >= limit) {
757             Slog.w(TAG, "Too many fingerprints registered");
758             return true;
759         }
760         return false;
761     }
762 
763     @Override
serviceDied(long cookie)764     public void serviceDied(long cookie) {
765         super.serviceDied(cookie);
766         mDaemon = null;
767     }
768 
769     @Override
updateActiveGroup(int userId, String clientPackage)770     protected void updateActiveGroup(int userId, String clientPackage) {
771         IBiometricsFingerprint daemon = getFingerprintDaemon();
772 
773         if (daemon != null) {
774             try {
775                 userId = getUserOrWorkProfileId(clientPackage, userId);
776                 if (userId != mCurrentUserId) {
777                     int firstSdkInt = Build.VERSION.FIRST_SDK_INT;
778                     if (firstSdkInt < Build.VERSION_CODES.BASE) {
779                         Slog.e(TAG, "First SDK version " + firstSdkInt + " is invalid; must be " +
780                                 "at least VERSION_CODES.BASE");
781                     }
782                     File baseDir;
783                     if (firstSdkInt <= Build.VERSION_CODES.O_MR1) {
784                         baseDir = Environment.getUserSystemDirectory(userId);
785                     } else {
786                         baseDir = Environment.getDataVendorDeDirectory(userId);
787                     }
788 
789                     File fpDir = new File(baseDir, FP_DATA_DIR);
790                     if (!fpDir.exists()) {
791                         if (!fpDir.mkdir()) {
792                             Slog.v(TAG, "Cannot make directory: " + fpDir.getAbsolutePath());
793                             return;
794                         }
795                         // Calling mkdir() from this process will create a directory with our
796                         // permissions (inherited from the containing dir). This command fixes
797                         // the label.
798                         if (!SELinux.restorecon(fpDir)) {
799                             Slog.w(TAG, "Restorecons failed. Directory will have wrong label.");
800                             return;
801                         }
802                     }
803 
804                     daemon.setActiveGroup(userId, fpDir.getAbsolutePath());
805                     mCurrentUserId = userId;
806                 }
807                 mAuthenticatorIds.put(userId,
808                         hasEnrolledBiometrics(userId) ? daemon.getAuthenticatorId() : 0L);
809             } catch (RemoteException e) {
810                 Slog.e(TAG, "Failed to setActiveGroup():", e);
811             }
812         }
813     }
814 
815     @Override
getLockoutResetIntent()816     protected String getLockoutResetIntent() {
817         return ACTION_LOCKOUT_RESET;
818     }
819 
820     @Override
getLockoutBroadcastPermission()821     protected String getLockoutBroadcastPermission() {
822         return RESET_FINGERPRINT_LOCKOUT;
823     }
824 
825     @Override
getHalDeviceId()826     protected long getHalDeviceId() {
827         return mHalDeviceId;
828     }
829 
830     @Override
hasEnrolledBiometrics(int userId)831     protected boolean hasEnrolledBiometrics(int userId) {
832         if (userId != UserHandle.getCallingUserId()) {
833             checkPermission(INTERACT_ACROSS_USERS);
834         }
835         return getBiometricUtils().getBiometricsForUser(getContext(), userId).size() > 0;
836     }
837 
838     @Override
getManageBiometricPermission()839     protected String getManageBiometricPermission() {
840         return MANAGE_FINGERPRINT;
841     }
842 
843     @Override
checkUseBiometricPermission()844     protected void checkUseBiometricPermission() {
845         if (getContext().checkCallingPermission(USE_FINGERPRINT)
846                 != PackageManager.PERMISSION_GRANTED) {
847             checkPermission(USE_BIOMETRIC);
848         }
849     }
850 
851     @Override
checkAppOps(int uid, String opPackageName)852     protected boolean checkAppOps(int uid, String opPackageName) {
853         boolean appOpsOk = false;
854         if (mAppOps.noteOp(AppOpsManager.OP_USE_BIOMETRIC, uid, opPackageName)
855                 == AppOpsManager.MODE_ALLOWED) {
856             appOpsOk = true;
857         } else if (mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, uid, opPackageName)
858                 == AppOpsManager.MODE_ALLOWED) {
859             appOpsOk = true;
860         }
861         return appOpsOk;
862     }
863 
864     @Override
getEnrolledTemplates(int userId)865     protected List<Fingerprint> getEnrolledTemplates(int userId) {
866         if (userId != UserHandle.getCallingUserId()) {
867             checkPermission(INTERACT_ACROSS_USERS);
868         }
869         return getBiometricUtils().getBiometricsForUser(getContext(), userId);
870     }
871 
872     @Override
notifyClientActiveCallbacks(boolean isActive)873     protected void notifyClientActiveCallbacks(boolean isActive) {
874         List<IFingerprintClientActiveCallback> callbacks = mClientActiveCallbacks;
875         for (int i = 0; i < callbacks.size(); i++) {
876             try {
877                 callbacks.get(i).onClientActiveChanged(isActive);
878             } catch (RemoteException re) {
879                 // If the remote is dead, stop notifying it
880                 mClientActiveCallbacks.remove(callbacks.get(i));
881             }
882         }
883     }
884 
885     @Override
statsModality()886     protected int statsModality() {
887         return BiometricsProtoEnums.MODALITY_FINGERPRINT;
888     }
889 
890     @Override
getLockoutMode()891     protected int getLockoutMode() {
892         final int currentUser = ActivityManager.getCurrentUser();
893         final int failedAttempts = mFailedAttempts.get(currentUser, 0);
894         if (failedAttempts >= MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT) {
895             return AuthenticationClient.LOCKOUT_PERMANENT;
896         } else if (failedAttempts > 0
897                 && !mTimedLockoutCleared.get(currentUser, false)
898                 && (failedAttempts % MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED == 0)) {
899             return AuthenticationClient.LOCKOUT_TIMED;
900         }
901         return AuthenticationClient.LOCKOUT_NONE;
902     }
903 
904     /** Gets the fingerprint daemon */
getFingerprintDaemon()905     private synchronized IBiometricsFingerprint getFingerprintDaemon() {
906         if (mDaemon == null) {
907             Slog.v(TAG, "mDaemon was null, reconnect to fingerprint");
908             try {
909                 mDaemon = IBiometricsFingerprint.getService();
910             } catch (java.util.NoSuchElementException e) {
911                 // Service doesn't exist or cannot be opened. Logged below.
912             } catch (RemoteException e) {
913                 Slog.e(TAG, "Failed to get biometric interface", e);
914             }
915             if (mDaemon == null) {
916                 Slog.w(TAG, "fingerprint HIDL not available");
917                 return null;
918             }
919 
920             mDaemon.asBinder().linkToDeath(this, 0);
921 
922             try {
923                 mHalDeviceId = mDaemon.setNotify(mDaemonCallback);
924             } catch (RemoteException e) {
925                 Slog.e(TAG, "Failed to open fingerprint HAL", e);
926                 mDaemon = null; // try again later!
927             }
928 
929             if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
930             if (mHalDeviceId != 0) {
931                 loadAuthenticatorIds();
932                 updateActiveGroup(ActivityManager.getCurrentUser(), null);
933                 doTemplateCleanupForUser(ActivityManager.getCurrentUser());
934             } else {
935                 Slog.w(TAG, "Failed to open Fingerprint HAL!");
936                 MetricsLogger.count(getContext(), "fingerprintd_openhal_error", 1);
937                 mDaemon = null;
938             }
939         }
940         return mDaemon;
941     }
942 
startPreEnroll(IBinder token)943     private long startPreEnroll(IBinder token) {
944         IBiometricsFingerprint daemon = getFingerprintDaemon();
945         if (daemon == null) {
946             Slog.w(TAG, "startPreEnroll: no fingerprint HAL!");
947             return 0;
948         }
949         try {
950             return daemon.preEnroll();
951         } catch (RemoteException e) {
952             Slog.e(TAG, "startPreEnroll failed", e);
953         }
954         return 0;
955     }
956 
startPostEnroll(IBinder token)957     private int startPostEnroll(IBinder token) {
958         IBiometricsFingerprint daemon = getFingerprintDaemon();
959         if (daemon == null) {
960             Slog.w(TAG, "startPostEnroll: no fingerprint HAL!");
961             return 0;
962         }
963         try {
964             return daemon.postEnroll();
965         } catch (RemoteException e) {
966             Slog.e(TAG, "startPostEnroll failed", e);
967         }
968         return 0;
969     }
970 
971     // Attempt counter should only be cleared when Keyguard goes away or when
972     // a biometric is successfully authenticated. Lockout should eventually be done below the HAL.
973     // See AuthenticationClient#shouldFrameworkHandleLockout().
resetFailedAttemptsForUser(boolean clearAttemptCounter, int userId)974     private void resetFailedAttemptsForUser(boolean clearAttemptCounter, int userId) {
975         if (DEBUG && getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) {
976             Slog.v(getTag(), "Reset biometric lockout, clearAttemptCounter=" + clearAttemptCounter);
977         }
978         if (clearAttemptCounter) {
979             mFailedAttempts.put(userId, 0);
980         }
981         mTimedLockoutCleared.put(userId, true);
982         // If we're asked to reset failed attempts externally (i.e. from Keyguard),
983         // the alarm might still be pending; remove it.
984         cancelLockoutResetForUser(userId);
985         notifyLockoutResetMonitors();
986     }
987 
988 
cancelLockoutResetForUser(int userId)989     private void cancelLockoutResetForUser(int userId) {
990         mAlarmManager.cancel(getLockoutResetIntentForUser(userId));
991     }
992 
scheduleLockoutResetForUser(int userId)993     private void scheduleLockoutResetForUser(int userId) {
994         mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
995                 SystemClock.elapsedRealtime() + FAIL_LOCKOUT_TIMEOUT_MS,
996                 getLockoutResetIntentForUser(userId));
997     }
998 
getLockoutResetIntentForUser(int userId)999     private PendingIntent getLockoutResetIntentForUser(int userId) {
1000         return PendingIntent.getBroadcast(getContext(), userId,
1001                 new Intent(getLockoutResetIntent()).putExtra(KEY_LOCKOUT_RESET_USER, userId),
1002                 PendingIntent.FLAG_UPDATE_CURRENT);
1003     }
1004 
dumpInternal(PrintWriter pw)1005     private void dumpInternal(PrintWriter pw) {
1006         JSONObject dump = new JSONObject();
1007         try {
1008             dump.put("service", "Fingerprint Manager");
1009 
1010             JSONArray sets = new JSONArray();
1011             for (UserInfo user : UserManager.get(getContext()).getUsers()) {
1012                 final int userId = user.getUserHandle().getIdentifier();
1013                 final int N = getBiometricUtils().getBiometricsForUser(getContext(), userId).size();
1014                 PerformanceStats stats = mPerformanceMap.get(userId);
1015                 PerformanceStats cryptoStats = mCryptoPerformanceMap.get(userId);
1016                 JSONObject set = new JSONObject();
1017                 set.put("id", userId);
1018                 set.put("count", N);
1019                 set.put("accept", (stats != null) ? stats.accept : 0);
1020                 set.put("reject", (stats != null) ? stats.reject : 0);
1021                 set.put("acquire", (stats != null) ? stats.acquire : 0);
1022                 set.put("lockout", (stats != null) ? stats.lockout : 0);
1023                 set.put("permanentLockout", (stats != null) ? stats.permanentLockout : 0);
1024                 // cryptoStats measures statistics about secure fingerprint transactions
1025                 // (e.g. to unlock password storage, make secure purchases, etc.)
1026                 set.put("acceptCrypto", (cryptoStats != null) ? cryptoStats.accept : 0);
1027                 set.put("rejectCrypto", (cryptoStats != null) ? cryptoStats.reject : 0);
1028                 set.put("acquireCrypto", (cryptoStats != null) ? cryptoStats.acquire : 0);
1029                 set.put("lockoutCrypto", (cryptoStats != null) ? cryptoStats.lockout : 0);
1030                 set.put("permanentLockoutCrypto",
1031                     (cryptoStats != null) ? cryptoStats.permanentLockout : 0);
1032                 sets.put(set);
1033             }
1034 
1035             dump.put("prints", sets);
1036         } catch (JSONException e) {
1037             Slog.e(TAG, "dump formatting failure", e);
1038         }
1039         pw.println(dump);
1040         pw.println("HAL deaths since last reboot: " + mHALDeathCount);
1041     }
1042 
dumpProto(FileDescriptor fd)1043     private void dumpProto(FileDescriptor fd) {
1044         final ProtoOutputStream proto = new ProtoOutputStream(fd);
1045         for (UserInfo user : UserManager.get(getContext()).getUsers()) {
1046             final int userId = user.getUserHandle().getIdentifier();
1047 
1048             final long userToken = proto.start(FingerprintServiceDumpProto.USERS);
1049 
1050             proto.write(FingerprintUserStatsProto.USER_ID, userId);
1051             proto.write(FingerprintUserStatsProto.NUM_FINGERPRINTS,
1052                     getBiometricUtils().getBiometricsForUser(getContext(), userId).size());
1053 
1054             // Normal fingerprint authentications (e.g. lockscreen)
1055             final PerformanceStats normal = mPerformanceMap.get(userId);
1056             if (normal != null) {
1057                 final long countsToken = proto.start(FingerprintUserStatsProto.NORMAL);
1058                 proto.write(PerformanceStatsProto.ACCEPT, normal.accept);
1059                 proto.write(PerformanceStatsProto.REJECT, normal.reject);
1060                 proto.write(PerformanceStatsProto.ACQUIRE, normal.acquire);
1061                 proto.write(PerformanceStatsProto.LOCKOUT, normal.lockout);
1062                 proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, normal.permanentLockout);
1063                 proto.end(countsToken);
1064             }
1065 
1066             // Statistics about secure fingerprint transactions (e.g. to unlock password
1067             // storage, make secure purchases, etc.)
1068             final PerformanceStats crypto = mCryptoPerformanceMap.get(userId);
1069             if (crypto != null) {
1070                 final long countsToken = proto.start(FingerprintUserStatsProto.CRYPTO);
1071                 proto.write(PerformanceStatsProto.ACCEPT, crypto.accept);
1072                 proto.write(PerformanceStatsProto.REJECT, crypto.reject);
1073                 proto.write(PerformanceStatsProto.ACQUIRE, crypto.acquire);
1074                 proto.write(PerformanceStatsProto.LOCKOUT, crypto.lockout);
1075                 proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, crypto.permanentLockout);
1076                 proto.end(countsToken);
1077             }
1078 
1079             proto.end(userToken);
1080         }
1081         proto.flush();
1082         mPerformanceMap.clear();
1083         mCryptoPerformanceMap.clear();
1084     }
1085 }
1086