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