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