• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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;
18 
19 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
20 
21 import android.app.ActivityManager;
22 import android.app.ActivityTaskManager;
23 import android.app.AppOpsManager;
24 import android.app.IActivityTaskManager;
25 import android.app.SynchronousUserSwitchObserver;
26 import android.app.TaskStackListener;
27 import android.content.ComponentName;
28 import android.content.Context;
29 import android.content.pm.PackageManager;
30 import android.content.pm.UserInfo;
31 import android.hardware.biometrics.BiometricAuthenticator;
32 import android.hardware.biometrics.BiometricConstants;
33 import android.hardware.biometrics.BiometricsProtoEnums;
34 import android.hardware.biometrics.IBiometricService;
35 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
36 import android.hardware.biometrics.IBiometricServiceReceiverInternal;
37 import android.hardware.fingerprint.Fingerprint;
38 import android.os.Binder;
39 import android.os.Bundle;
40 import android.os.DeadObjectException;
41 import android.os.Handler;
42 import android.os.IBinder;
43 import android.os.IHwBinder;
44 import android.os.IRemoteCallback;
45 import android.os.PowerManager;
46 import android.os.Process;
47 import android.os.RemoteException;
48 import android.os.ServiceManager;
49 import android.os.SystemClock;
50 import android.os.UserHandle;
51 import android.os.UserManager;
52 import android.util.Slog;
53 import android.util.StatsLog;
54 
55 import com.android.internal.logging.MetricsLogger;
56 import com.android.internal.statusbar.IStatusBarService;
57 import com.android.server.SystemService;
58 
59 import java.util.ArrayList;
60 import java.util.Collections;
61 import java.util.HashMap;
62 import java.util.List;
63 import java.util.Map;
64 
65 /**
66  * Abstract base class containing all of the business logic for biometric services, e.g.
67  * Fingerprint, Face, Iris.
68  *
69  * @hide
70  */
71 public abstract class BiometricServiceBase extends SystemService
72         implements IHwBinder.DeathRecipient {
73 
74     protected static final boolean DEBUG = true;
75 
76     private static final boolean CLEANUP_UNKNOWN_TEMPLATES = true;
77     private static final String KEY_LOCKOUT_RESET_USER = "lockout_reset_user";
78     private static final int MSG_USER_SWITCHING = 10;
79     private static final long CANCEL_TIMEOUT_LIMIT = 3000; // max wait for onCancel() from HAL,in ms
80 
81     private final Context mContext;
82     private final String mKeyguardPackage;
83     private final IActivityTaskManager mActivityTaskManager;
84     private final PowerManager mPowerManager;
85     private final UserManager mUserManager;
86     private final MetricsLogger mMetricsLogger;
87     private final BiometricTaskStackListener mTaskStackListener = new BiometricTaskStackListener();
88     private final ResetClientStateRunnable mResetClientState = new ResetClientStateRunnable();
89     private final ArrayList<LockoutResetMonitor> mLockoutMonitors = new ArrayList<>();
90 
91     protected final IStatusBarService mStatusBarService;
92     protected final Map<Integer, Long> mAuthenticatorIds =
93             Collections.synchronizedMap(new HashMap<>());
94     protected final AppOpsManager mAppOps;
95     protected final H mHandler = new H();
96 
97     private final IBinder mToken = new Binder(); // Used for internal enumeration
98     private final ArrayList<UserTemplate> mUnknownHALTemplates = new ArrayList<>();
99 
100     private IBiometricService mBiometricService;
101     private ClientMonitor mCurrentClient;
102     private ClientMonitor mPendingClient;
103     private PerformanceStats mPerformanceStats;
104     protected int mCurrentUserId = UserHandle.USER_NULL;
105     protected long mHalDeviceId;
106     // Tracks if the current authentication makes use of CryptoObjects.
107     protected boolean mIsCrypto;
108     // Normal authentications are tracked by mPerformanceMap.
109     protected HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>();
110     // Transactions that make use of CryptoObjects are tracked by mCryptoPerformaceMap.
111     protected HashMap<Integer, PerformanceStats> mCryptoPerformanceMap = new HashMap<>();
112     protected int mHALDeathCount;
113 
114     protected class PerformanceStats {
115         public int accept; // number of accepted biometrics
116         public int reject; // number of rejected biometrics
117         public int acquire; // total number of acquisitions. Should be >= accept+reject due to poor
118         // image acquisition in some cases (too fast, too slow, dirty sensor, etc.)
119         public int lockout; // total number of lockouts
120         public int permanentLockout; // total number of permanent lockouts
121     }
122 
123     /**
124      * @return the log tag.
125      */
getTag()126     protected abstract String getTag();
127 
128     /**
129      * @return wrapper for the HAL
130      */
getDaemonWrapper()131     protected abstract DaemonWrapper getDaemonWrapper();
132 
133     /**
134      * @return the biometric utilities for a specific implementation.
135      */
getBiometricUtils()136     protected abstract BiometricUtils getBiometricUtils();
137 
138     /**
139      * @return the metrics constants for a biometric implementation.
140      */
getConstants()141     protected abstract Constants getConstants();
142 
143     /**
144      * @param userId
145      * @return true if the enrollment limit has been reached.
146      */
hasReachedEnrollmentLimit(int userId)147     protected abstract boolean hasReachedEnrollmentLimit(int userId);
148 
149     /**
150      * Notifies the HAL that the user has changed.
151      * @param userId
152      * @param clientPackage
153      */
updateActiveGroup(int userId, String clientPackage)154     protected abstract void updateActiveGroup(int userId, String clientPackage);
155 
156     /**
157      * @return The protected intent to reset lockout for a specific biometric.
158      */
getLockoutResetIntent()159     protected abstract String getLockoutResetIntent();
160 
161     /**
162      * @return The permission the sender is required to have in order for the lockout reset intent
163      *         to be received by the BiometricService implementation.
164      */
getLockoutBroadcastPermission()165     protected abstract String getLockoutBroadcastPermission();
166 
167     /**
168      * @return The HAL ID.
169      */
getHalDeviceId()170     protected abstract long getHalDeviceId();
171 
172     /**
173      * @param userId
174      * @return Returns true if the user has any enrolled biometrics.
175      */
hasEnrolledBiometrics(int userId)176     protected abstract boolean hasEnrolledBiometrics(int userId);
177 
178     /**
179      * @return Returns the MANAGE_* permission string, which is required for enrollment, removal
180      * etc.
181      */
getManageBiometricPermission()182     protected abstract String getManageBiometricPermission();
183 
184     /**
185      * Checks if the caller has permission to use the biometric service - throws a SecurityException
186      * if not.
187      */
checkUseBiometricPermission()188     protected abstract void checkUseBiometricPermission();
189 
190     /**
191      * Checks if the caller passes the app ops check
192      */
checkAppOps(int uid, String opPackageName)193     protected abstract boolean checkAppOps(int uid, String opPackageName);
194 
getEnrolledTemplates( int userId)195     protected abstract List<? extends BiometricAuthenticator.Identifier> getEnrolledTemplates(
196             int userId);
197 
198     /**
199      * Notifies clients of any change in the biometric state (active / idle). This is mainly for
200      * Fingerprint navigation gestures.
201      * @param isActive
202      */
notifyClientActiveCallbacks(boolean isActive)203     protected void notifyClientActiveCallbacks(boolean isActive) {}
204 
statsModality()205     protected abstract int statsModality();
206 
207     /**
208      * @return one of the AuthenticationClient LOCKOUT constants
209      */
getLockoutMode()210     protected abstract int getLockoutMode();
211 
212     protected abstract class AuthenticationClientImpl extends AuthenticationClient {
213 
214         // Used to check if the public API that was invoked was from FingerprintManager. Only
215         // to be overridden by FingerprintService.
isFingerprint()216         protected boolean isFingerprint() {
217             return false;
218         }
219 
AuthenticationClientImpl(Context context, DaemonWrapper daemon, long halDeviceId, IBinder token, ServiceListener listener, int targetUserId, int groupId, long opId, boolean restricted, String owner, int cookie, boolean requireConfirmation)220         public AuthenticationClientImpl(Context context, DaemonWrapper daemon, long halDeviceId,
221                 IBinder token, ServiceListener listener, int targetUserId, int groupId, long opId,
222                 boolean restricted, String owner, int cookie, boolean requireConfirmation) {
223             super(context, getConstants(), daemon, halDeviceId, token, listener, targetUserId,
224                     groupId, opId, restricted, owner, cookie, requireConfirmation);
225         }
226 
227         @Override
statsClient()228         protected int statsClient() {
229             if (isKeyguard(getOwnerString())) {
230                 return BiometricsProtoEnums.CLIENT_KEYGUARD;
231             } else if (isBiometricPrompt()) {
232                 return BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT;
233             } else if (isFingerprint()) {
234                 return BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER;
235             } else {
236                 return BiometricsProtoEnums.CLIENT_UNKNOWN;
237             }
238         }
239 
240         @Override
onStart()241         public void onStart() {
242             try {
243                 mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
244             } catch (RemoteException e) {
245                 Slog.e(getTag(), "Could not register task stack listener", e);
246             }
247         }
248 
249         @Override
onStop()250         public void onStop() {
251             try {
252                 mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
253             } catch (RemoteException e) {
254                 Slog.e(getTag(), "Could not unregister task stack listener", e);
255             }
256         }
257 
258         @Override
notifyUserActivity()259         public void notifyUserActivity() {
260             userActivity();
261         }
262 
263         @Override
handleFailedAttempt()264         public int handleFailedAttempt() {
265             final int lockoutMode = getLockoutMode();
266             if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) {
267                 mPerformanceStats.permanentLockout++;
268             } else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) {
269                 mPerformanceStats.lockout++;
270             }
271 
272             // Failing multiple times will continue to push out the lockout time
273             if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
274                 return lockoutMode;
275             }
276             return AuthenticationClient.LOCKOUT_NONE;
277         }
278     }
279 
280     protected abstract class EnrollClientImpl extends EnrollClient {
281 
EnrollClientImpl(Context context, DaemonWrapper daemon, long halDeviceId, IBinder token, ServiceListener listener, int userId, int groupId, byte[] cryptoToken, boolean restricted, String owner, final int[] disabledFeatures)282         public EnrollClientImpl(Context context, DaemonWrapper daemon, long halDeviceId,
283                 IBinder token, ServiceListener listener, int userId, int groupId,
284                 byte[] cryptoToken, boolean restricted, String owner,
285                 final int[] disabledFeatures) {
286             super(context, getConstants(), daemon, halDeviceId, token, listener,
287                     userId, groupId, cryptoToken, restricted, owner, getBiometricUtils(),
288                     disabledFeatures);
289         }
290 
291         @Override
notifyUserActivity()292         public void notifyUserActivity() {
293             userActivity();
294         }
295     }
296 
297     /**
298      * An internal class to help clean up unknown templates in HAL and Framework
299      */
300     private final class InternalRemovalClient extends RemovalClient {
InternalRemovalClient(Context context, DaemonWrapper daemon, long halDeviceId, IBinder token, ServiceListener listener, int templateId, int groupId, int userId, boolean restricted, String owner)301         InternalRemovalClient(Context context,
302                 DaemonWrapper daemon, long halDeviceId, IBinder token,
303                 ServiceListener listener, int templateId, int groupId, int userId,
304                 boolean restricted, String owner) {
305             super(context, getConstants(), daemon, halDeviceId, token, listener, templateId, groupId,
306                     userId, restricted, owner, getBiometricUtils());
307         }
308 
309         @Override
statsModality()310         protected int statsModality() {
311             return BiometricServiceBase.this.statsModality();
312         }
313     }
314 
315     /**
316      * Internal class to help clean up unknown templates in the HAL and Framework
317      */
318     private final class InternalEnumerateClient extends EnumerateClient {
319 
320         private BiometricUtils mUtils;
321         // List of templates that are known to the Framework. Remove from this list when enumerate
322         // returns a template that contains a match.
323         private List<? extends BiometricAuthenticator.Identifier> mEnrolledList;
324         // List of templates to remove from the HAL
325         private List<BiometricAuthenticator.Identifier> mUnknownHALTemplates = new ArrayList<>();
326 
InternalEnumerateClient(Context context, DaemonWrapper daemon, long halDeviceId, IBinder token, ServiceListener listener, int groupId, int userId, boolean restricted, String owner, List<? extends BiometricAuthenticator.Identifier> enrolledList, BiometricUtils utils)327         InternalEnumerateClient(Context context,
328                 DaemonWrapper daemon, long halDeviceId, IBinder token,
329                 ServiceListener listener, int groupId, int userId, boolean restricted,
330                 String owner, List<? extends BiometricAuthenticator.Identifier> enrolledList,
331                 BiometricUtils utils) {
332             super(context, getConstants(), daemon, halDeviceId, token, listener, groupId, userId,
333                     restricted, owner);
334             mEnrolledList = enrolledList;
335             mUtils = utils;
336         }
337 
handleEnumeratedTemplate(BiometricAuthenticator.Identifier identifier)338         private void handleEnumeratedTemplate(BiometricAuthenticator.Identifier identifier) {
339             if (identifier == null) {
340                 return;
341             }
342             Slog.v(getTag(), "handleEnumeratedTemplate: " + identifier.getBiometricId());
343             boolean matched = false;
344             for (int i = 0; i < mEnrolledList.size(); i++) {
345                 if (mEnrolledList.get(i).getBiometricId() == identifier.getBiometricId()) {
346                     mEnrolledList.remove(i);
347                     matched = true;
348                     break;
349                 }
350             }
351 
352             // TemplateId 0 means no templates in HAL
353             if (!matched && identifier.getBiometricId() != 0) {
354                 mUnknownHALTemplates.add(identifier);
355             }
356             Slog.v(getTag(), "Matched: " + matched);
357         }
358 
doTemplateCleanup()359         private void doTemplateCleanup() {
360             if (mEnrolledList == null) {
361                 return;
362             }
363 
364             // At this point, mEnrolledList only contains templates known to the framework and
365             // not the HAL.
366             for (int i = 0; i < mEnrolledList.size(); i++) {
367                 BiometricAuthenticator.Identifier identifier = mEnrolledList.get(i);
368                 Slog.e(getTag(), "doTemplateCleanup(): Removing dangling template from framework: "
369                         + identifier.getBiometricId() + " "
370                         + identifier.getName());
371                 mUtils.removeBiometricForUser(getContext(),
372                         getTargetUserId(), identifier.getBiometricId());
373                 StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
374                         statsModality(),
375                         BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK);
376             }
377             mEnrolledList.clear();
378         }
379 
getUnknownHALTemplates()380         public List<BiometricAuthenticator.Identifier> getUnknownHALTemplates() {
381             return mUnknownHALTemplates;
382         }
383 
384         @Override
onEnumerationResult(BiometricAuthenticator.Identifier identifier, int remaining)385         public boolean onEnumerationResult(BiometricAuthenticator.Identifier identifier,
386                 int remaining) {
387             handleEnumeratedTemplate(identifier);
388             if (remaining == 0) {
389                 doTemplateCleanup();
390             }
391             return remaining == 0;
392         }
393 
394         @Override
statsModality()395         protected int statsModality() {
396             return BiometricServiceBase.this.statsModality();
397         }
398     }
399 
400     /**
401      * Wraps the callback interface from Service -> Manager
402      */
403     protected interface ServiceListener {
onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining)404         default void onEnrollResult(BiometricAuthenticator.Identifier identifier,
405                 int remaining) throws RemoteException {};
406 
onAcquired(long deviceId, int acquiredInfo, int vendorCode)407         void onAcquired(long deviceId, int acquiredInfo, int vendorCode) throws RemoteException;
408 
onAuthenticationSucceeded(long deviceId, BiometricAuthenticator.Identifier biometric, int userId)409         default void onAuthenticationSucceeded(long deviceId,
410                 BiometricAuthenticator.Identifier biometric, int userId) throws RemoteException {
411             throw new UnsupportedOperationException("Stub!");
412         }
413 
onAuthenticationSucceededInternal(boolean requireConfirmation, byte[] token)414         default void onAuthenticationSucceededInternal(boolean requireConfirmation, byte[] token)
415                 throws RemoteException {
416             throw new UnsupportedOperationException("Stub!");
417         }
418 
onAuthenticationFailed(long deviceId)419         default void onAuthenticationFailed(long deviceId) throws RemoteException {
420             throw new UnsupportedOperationException("Stub!");
421         }
422 
onAuthenticationFailedInternal(int cookie, boolean requireConfirmation)423         default void onAuthenticationFailedInternal(int cookie, boolean requireConfirmation)
424                 throws RemoteException {
425             throw new UnsupportedOperationException("Stub!");
426         }
427 
onError(long deviceId, int error, int vendorCode, int cookie)428         void onError(long deviceId, int error, int vendorCode, int cookie) throws RemoteException;
429 
onRemoved(BiometricAuthenticator.Identifier identifier, int remaining)430         default void onRemoved(BiometricAuthenticator.Identifier identifier,
431                 int remaining) throws RemoteException {};
432 
onEnumerated(BiometricAuthenticator.Identifier identifier, int remaining)433         default void onEnumerated(BiometricAuthenticator.Identifier identifier,
434                 int remaining) throws RemoteException {};
435     }
436 
437     /**
438      * Wraps the callback interface from Service -> BiometricPrompt
439      */
440     protected abstract class BiometricServiceListener implements ServiceListener {
441         private IBiometricServiceReceiverInternal mWrapperReceiver;
442 
BiometricServiceListener(IBiometricServiceReceiverInternal wrapperReceiver)443         public BiometricServiceListener(IBiometricServiceReceiverInternal wrapperReceiver) {
444             mWrapperReceiver = wrapperReceiver;
445         }
446 
getWrapperReceiver()447         public IBiometricServiceReceiverInternal getWrapperReceiver() {
448             return mWrapperReceiver;
449         }
450 
451         @Override
onAuthenticationSucceededInternal(boolean requireConfirmation, byte[] token)452         public void onAuthenticationSucceededInternal(boolean requireConfirmation, byte[] token)
453                 throws RemoteException {
454             if (getWrapperReceiver() != null) {
455                 getWrapperReceiver().onAuthenticationSucceeded(requireConfirmation, token);
456             }
457         }
458 
459         @Override
onAuthenticationFailedInternal(int cookie, boolean requireConfirmation)460         public void onAuthenticationFailedInternal(int cookie, boolean requireConfirmation)
461                 throws RemoteException {
462             if (getWrapperReceiver() != null) {
463                 getWrapperReceiver().onAuthenticationFailed(cookie, requireConfirmation);
464             }
465         }
466     }
467 
468     /**
469      * Wraps a portion of the interface from Service -> Daemon that is used by the ClientMonitor
470      * subclasses.
471      */
472     protected interface DaemonWrapper {
473         int ERROR_ESRCH = 3; // Likely HAL is dead. see errno.h.
authenticate(long operationId, int groupId)474         int authenticate(long operationId, int groupId) throws RemoteException;
cancel()475         int cancel() throws RemoteException;
remove(int groupId, int biometricId)476         int remove(int groupId, int biometricId) throws RemoteException;
enumerate()477         int enumerate() throws RemoteException;
enroll(byte[] token, int groupId, int timeout, ArrayList<Integer> disabledFeatures)478         int enroll(byte[] token, int groupId, int timeout,
479                 ArrayList<Integer> disabledFeatures) throws RemoteException;
resetLockout(byte[] token)480         void resetLockout(byte[] token) throws RemoteException;
481     }
482 
483     /**
484      * Handler which all subclasses should post events to.
485      */
486     protected final class H extends Handler {
487         @Override
handleMessage(android.os.Message msg)488         public void handleMessage(android.os.Message msg) {
489             switch (msg.what) {
490                 case MSG_USER_SWITCHING:
491                     handleUserSwitching(msg.arg1);
492                     break;
493 
494                 default:
495                     Slog.w(getTag(), "Unknown message:" + msg.what);
496             }
497         }
498     }
499 
500     private final class BiometricTaskStackListener extends TaskStackListener {
501         @Override
onTaskStackChanged()502         public void onTaskStackChanged() {
503             try {
504                 if (!(mCurrentClient instanceof AuthenticationClient)) {
505                     return;
506                 }
507                 final String currentClient = mCurrentClient.getOwnerString();
508                 if (isKeyguard(currentClient)) {
509                     return; // Keyguard is always allowed
510                 }
511                 List<ActivityManager.RunningTaskInfo> runningTasks =
512                         mActivityTaskManager.getTasks(1);
513                 if (!runningTasks.isEmpty()) {
514                     final String topPackage = runningTasks.get(0).topActivity.getPackageName();
515                     if (!topPackage.contentEquals(currentClient)
516                             && !mCurrentClient.isAlreadyDone()) {
517                         Slog.e(getTag(), "Stopping background authentication, top: " + topPackage
518                                 + " currentClient: " + currentClient);
519                         mCurrentClient.stop(false /* initiatedByClient */);
520                     }
521                 }
522             } catch (RemoteException e) {
523                 Slog.e(getTag(), "Unable to get running tasks", e);
524             }
525         }
526     }
527 
528     private final class ResetClientStateRunnable implements Runnable {
529         @Override
run()530         public void run() {
531             /**
532              * Warning: if we get here, the driver never confirmed our call to cancel the current
533              * operation (authenticate, enroll, remove, enumerate, etc), which is
534              * really bad.  The result will be a 3-second delay in starting each new client.
535              * If you see this on a device, make certain the driver notifies with
536              * {@link BiometricConstants#BIOMETRIC_ERROR_CANCELED} in response to cancel()
537              * once it has successfully switched to the IDLE state in the HAL.
538              * Additionally,{@link BiometricConstants#BIOMETRIC_ERROR_CANCELED} should only be sent
539              * in response to an actual cancel() call.
540              */
541             Slog.w(getTag(), "Client "
542                     + (mCurrentClient != null ? mCurrentClient.getOwnerString() : "null")
543                     + " failed to respond to cancel, starting client "
544                     + (mPendingClient != null ? mPendingClient.getOwnerString() : "null"));
545 
546             StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
547                     statsModality(), BiometricsProtoEnums.ISSUE_CANCEL_TIMED_OUT);
548 
549             mCurrentClient = null;
550             startClient(mPendingClient, false);
551         }
552     }
553 
554 
555 
556     private final class LockoutResetMonitor implements IBinder.DeathRecipient {
557         private static final long WAKELOCK_TIMEOUT_MS = 2000;
558         private final IBiometricServiceLockoutResetCallback mCallback;
559         private final PowerManager.WakeLock mWakeLock;
560 
LockoutResetMonitor(IBiometricServiceLockoutResetCallback callback)561         public LockoutResetMonitor(IBiometricServiceLockoutResetCallback callback) {
562             mCallback = callback;
563             mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
564                     "lockout reset callback");
565             try {
566                 mCallback.asBinder().linkToDeath(LockoutResetMonitor.this, 0);
567             } catch (RemoteException e) {
568                 Slog.w(getTag(), "caught remote exception in linkToDeath", e);
569             }
570         }
571 
sendLockoutReset()572         public void sendLockoutReset() {
573             if (mCallback != null) {
574                 try {
575                     mWakeLock.acquire(WAKELOCK_TIMEOUT_MS);
576                     mCallback.onLockoutReset(getHalDeviceId(), new IRemoteCallback.Stub() {
577                         @Override
578                         public void sendResult(Bundle data) throws RemoteException {
579                             releaseWakelock();
580                         }
581                     });
582                 } catch (DeadObjectException e) {
583                     Slog.w(getTag(), "Death object while invoking onLockoutReset: ", e);
584                     mHandler.post(mRemoveCallbackRunnable);
585                 } catch (RemoteException e) {
586                     Slog.w(getTag(), "Failed to invoke onLockoutReset: ", e);
587                     releaseWakelock();
588                 }
589             }
590         }
591 
592         private final Runnable mRemoveCallbackRunnable = new Runnable() {
593             @Override
594             public void run() {
595                 releaseWakelock();
596                 removeLockoutResetCallback(LockoutResetMonitor.this);
597             }
598         };
599 
600         @Override
binderDied()601         public void binderDied() {
602             Slog.e(getTag(), "Lockout reset callback binder died");
603             mHandler.post(mRemoveCallbackRunnable);
604         }
605 
releaseWakelock()606         private void releaseWakelock() {
607             if (mWakeLock.isHeld()) {
608                 mWakeLock.release();
609             }
610         }
611     }
612 
613     /**
614      * Container for enumerated templates. Used to keep track when cleaning up unknown
615      * templates.
616      */
617     private final class UserTemplate {
618         final BiometricAuthenticator.Identifier mIdentifier;
619         final int mUserId;
UserTemplate(BiometricAuthenticator.Identifier identifier, int userId)620         UserTemplate(BiometricAuthenticator.Identifier identifier, int userId) {
621             this.mIdentifier = identifier;
622             this.mUserId = userId;
623         }
624     }
625 
626     /**
627      * Initializes the system service.
628      * <p>
629      * Subclasses must define a single argument constructor that accepts the context
630      * and passes it to super.
631      * </p>
632      *
633      * @param context The system server context.
634      */
BiometricServiceBase(Context context)635     public BiometricServiceBase(Context context) {
636         super(context);
637         mContext = context;
638         mStatusBarService = IStatusBarService.Stub.asInterface(
639                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
640         mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString(
641                 com.android.internal.R.string.config_keyguardComponent)).getPackageName();
642         mAppOps = context.getSystemService(AppOpsManager.class);
643         mActivityTaskManager = ((ActivityTaskManager) context.getSystemService(
644                 Context.ACTIVITY_TASK_SERVICE)).getService();
645         mPowerManager = mContext.getSystemService(PowerManager.class);
646         mUserManager = UserManager.get(mContext);
647         mMetricsLogger = new MetricsLogger();
648     }
649 
650     @Override
onStart()651     public void onStart() {
652         listenForUserSwitches();
653     }
654 
655     @Override
serviceDied(long cookie)656     public void serviceDied(long cookie) {
657         Slog.e(getTag(), "HAL died");
658         mMetricsLogger.count(getConstants().tagHalDied(), 1);
659         mHALDeathCount++;
660         mCurrentUserId = UserHandle.USER_NULL;
661         handleError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
662                 0 /*vendorCode */);
663 
664         StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(),
665                 BiometricsProtoEnums.ISSUE_HAL_DEATH);
666     }
667 
getCurrentClient()668     protected ClientMonitor getCurrentClient() {
669         return mCurrentClient;
670     }
671 
getPendingClient()672     protected ClientMonitor getPendingClient() {
673         return mPendingClient;
674     }
675 
676     /**
677      * Callback handlers from the daemon. The caller must put this on a handler.
678      */
679 
handleAcquired(long deviceId, int acquiredInfo, int vendorCode)680     protected void handleAcquired(long deviceId, int acquiredInfo, int vendorCode) {
681         ClientMonitor client = mCurrentClient;
682         if (client != null && client.onAcquired(acquiredInfo, vendorCode)) {
683             removeClient(client);
684         }
685         if (mPerformanceStats != null && getLockoutMode() == AuthenticationClient.LOCKOUT_NONE
686                 && client instanceof AuthenticationClient) {
687             // ignore enrollment acquisitions or acquisitions when we're locked out
688             mPerformanceStats.acquire++;
689         }
690     }
691 
handleAuthenticated(BiometricAuthenticator.Identifier identifier, ArrayList<Byte> token)692     protected void handleAuthenticated(BiometricAuthenticator.Identifier identifier,
693             ArrayList<Byte> token) {
694         ClientMonitor client = mCurrentClient;
695         final boolean authenticated = identifier.getBiometricId() != 0;
696 
697         if (client != null && client.onAuthenticated(identifier, authenticated, token)) {
698             removeClient(client);
699         }
700         if (authenticated) {
701             mPerformanceStats.accept++;
702         } else {
703             mPerformanceStats.reject++;
704         }
705     }
706 
handleEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining)707     protected void handleEnrollResult(BiometricAuthenticator.Identifier identifier,
708             int remaining) {
709         ClientMonitor client = mCurrentClient;
710         if (client != null && client.onEnrollResult(identifier, remaining)) {
711             removeClient(client);
712             // When enrollment finishes, update this group's authenticator id, as the HAL has
713             // already generated a new authenticator id when the new biometric is enrolled.
714             if (identifier instanceof Fingerprint) {
715                 updateActiveGroup(((Fingerprint)identifier).getGroupId(), null);
716             } else {
717                 updateActiveGroup(mCurrentUserId, null);
718             }
719         }
720     }
721 
handleError(long deviceId, int error, int vendorCode)722     protected void handleError(long deviceId, int error, int vendorCode) {
723         final ClientMonitor client = mCurrentClient;
724 
725         if (DEBUG) Slog.v(getTag(), "handleError(client="
726                 + (client != null ? client.getOwnerString() : "null") + ", error = " + error + ")");
727 
728         if (client instanceof InternalRemovalClient
729                 || client instanceof InternalEnumerateClient) {
730             clearEnumerateState();
731         }
732 
733         if (client != null && client.onError(deviceId, error, vendorCode)) {
734             removeClient(client);
735         }
736 
737         if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) {
738             mHandler.removeCallbacks(mResetClientState);
739             if (mPendingClient != null) {
740                 if (DEBUG) Slog.v(getTag(), "start pending client " +
741                         mPendingClient.getOwnerString());
742                 startClient(mPendingClient, false);
743                 mPendingClient = null;
744             }
745         }
746     }
747 
handleRemoved(BiometricAuthenticator.Identifier identifier, final int remaining)748     protected void handleRemoved(BiometricAuthenticator.Identifier identifier,
749             final int remaining) {
750         if (DEBUG) Slog.w(getTag(), "Removed: fid=" + identifier.getBiometricId()
751                 + ", dev=" + identifier.getDeviceId()
752                 + ", rem=" + remaining);
753 
754         ClientMonitor client = mCurrentClient;
755         if (client != null && client.onRemoved(identifier, remaining)) {
756             removeClient(client);
757             // When the last biometric of a group is removed, update the authenticator id
758             int userId = mCurrentUserId;
759             if (identifier instanceof Fingerprint) {
760                 userId = ((Fingerprint) identifier).getGroupId();
761             }
762             if (!hasEnrolledBiometrics(userId)) {
763                 updateActiveGroup(userId, null);
764             }
765         }
766 
767         if (client instanceof InternalRemovalClient && !mUnknownHALTemplates.isEmpty()) {
768             startCleanupUnknownHALTemplates();
769         } else if (client instanceof InternalRemovalClient) {
770             clearEnumerateState();
771         }
772     }
773 
handleEnumerate(BiometricAuthenticator.Identifier identifier, int remaining)774     protected void handleEnumerate(BiometricAuthenticator.Identifier identifier, int remaining) {
775         ClientMonitor client = getCurrentClient();
776 
777         client.onEnumerationResult(identifier, remaining);
778 
779         // All templates in the HAL for this user were enumerated
780         if (remaining == 0) {
781             if (client instanceof InternalEnumerateClient) {
782                 List<BiometricAuthenticator.Identifier> unknownHALTemplates =
783                         ((InternalEnumerateClient) client).getUnknownHALTemplates();
784 
785                 if (!unknownHALTemplates.isEmpty()) {
786                     Slog.w(getTag(), "Adding " + unknownHALTemplates.size()
787                             + " templates for deletion");
788                 }
789                 for (int i = 0; i < unknownHALTemplates.size(); i++) {
790                     mUnknownHALTemplates.add(new UserTemplate(unknownHALTemplates.get(i),
791                             client.getTargetUserId()));
792                 }
793                 removeClient(client);
794                 startCleanupUnknownHALTemplates();
795             } else {
796                 removeClient(client);
797             }
798         }
799     }
800 
801     /**
802      * Calls from the Manager. These are still on the calling binder's thread.
803      */
804 
enrollInternal(EnrollClientImpl client, int userId)805     protected void enrollInternal(EnrollClientImpl client, int userId) {
806         if (hasReachedEnrollmentLimit(userId)) {
807             return;
808         }
809 
810         // Group ID is arbitrarily set to parent profile user ID. It just represents
811         // the default biometrics for the user.
812         if (!isCurrentUserOrProfile(userId)) {
813             return;
814         }
815 
816         mHandler.post(() -> {
817             startClient(client, true /* initiatedByClient */);
818         });
819     }
820 
cancelEnrollmentInternal(IBinder token)821     protected void cancelEnrollmentInternal(IBinder token) {
822         mHandler.post(() -> {
823             ClientMonitor client = mCurrentClient;
824             if (client instanceof EnrollClient && client.getToken() == token) {
825                 if (DEBUG) Slog.v(getTag(), "Cancelling enrollment");
826                 client.stop(client.getToken() == token);
827             }
828         });
829     }
830 
authenticateInternal(AuthenticationClientImpl client, long opId, String opPackageName)831     protected void authenticateInternal(AuthenticationClientImpl client, long opId,
832             String opPackageName) {
833         final int callingUid = Binder.getCallingUid();
834         final int callingPid = Binder.getCallingPid();
835         final int callingUserId = UserHandle.getCallingUserId();
836         authenticateInternal(client, opId, opPackageName, callingUid, callingPid, callingUserId);
837     }
838 
authenticateInternal(AuthenticationClientImpl client, long opId, String opPackageName, int callingUid, int callingPid, int callingUserId)839     protected void authenticateInternal(AuthenticationClientImpl client, long opId,
840             String opPackageName, int callingUid, int callingPid, int callingUserId) {
841         if (!canUseBiometric(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
842                 callingUserId)) {
843             if (DEBUG) Slog.v(getTag(), "authenticate(): reject " + opPackageName);
844             return;
845         }
846 
847         mHandler.post(() -> {
848             mMetricsLogger.histogram(getConstants().tagAuthToken(), opId != 0L ? 1 : 0);
849 
850             // Get performance stats object for this user.
851             HashMap<Integer, PerformanceStats> pmap
852                     = (opId == 0) ? mPerformanceMap : mCryptoPerformanceMap;
853             PerformanceStats stats = pmap.get(mCurrentUserId);
854             if (stats == null) {
855                 stats = new PerformanceStats();
856                 pmap.put(mCurrentUserId, stats);
857             }
858             mPerformanceStats = stats;
859             mIsCrypto = (opId != 0);
860 
861             startAuthentication(client, opPackageName);
862         });
863     }
864 
cancelAuthenticationInternal(final IBinder token, final String opPackageName)865     protected void cancelAuthenticationInternal(final IBinder token, final String opPackageName) {
866         final int callingUid = Binder.getCallingUid();
867         final int callingPid = Binder.getCallingPid();
868         final int callingUserId = UserHandle.getCallingUserId();
869         cancelAuthenticationInternal(token, opPackageName, callingUid, callingPid, callingUserId,
870                 true /* fromClient */);
871     }
872 
cancelAuthenticationInternal(final IBinder token, final String opPackageName, int callingUid, int callingPid, int callingUserId, boolean fromClient)873     protected void cancelAuthenticationInternal(final IBinder token, final String opPackageName,
874             int callingUid, int callingPid, int callingUserId, boolean fromClient) {
875         if (fromClient) {
876             // Only check this if cancel was called from the client (app). If cancel was called
877             // from BiometricService, it means the dialog was dismissed due to user interaction.
878             if (!canUseBiometric(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
879                     callingUserId)) {
880                 if (DEBUG) Slog.v(getTag(), "cancelAuthentication(): reject " + opPackageName);
881                 return;
882             }
883         }
884 
885         mHandler.post(() -> {
886             ClientMonitor client = mCurrentClient;
887             if (client instanceof AuthenticationClient) {
888                 if (client.getToken() == token || !fromClient) {
889                     if (DEBUG) Slog.v(getTag(), "Stopping client " + client.getOwnerString()
890                             + ", fromClient: " + fromClient);
891                     // If cancel was from BiometricService, it means the dialog was dismissed
892                     // and authentication should be canceled.
893                     client.stop(client.getToken() == token);
894                 } else {
895                     if (DEBUG) Slog.v(getTag(), "Can't stop client " + client.getOwnerString()
896                             + " since tokens don't match. fromClient: " + fromClient);
897                 }
898             } else if (client != null) {
899                 if (DEBUG) Slog.v(getTag(), "Can't cancel non-authenticating client "
900                         + client.getOwnerString());
901             }
902         });
903     }
904 
setActiveUserInternal(int userId)905     protected void setActiveUserInternal(int userId) {
906         // Do not put on handler, since it should finish before returning to caller.
907         updateActiveGroup(userId, null /* clientPackage */);
908     }
909 
removeInternal(RemovalClient client)910     protected void removeInternal(RemovalClient client) {
911         mHandler.post(() -> {
912             startClient(client, true /* initiatedByClient */);
913         });
914     }
915 
enumerateInternal(EnumerateClient client)916     protected void enumerateInternal(EnumerateClient client) {
917         mHandler.post(() -> {
918             startClient(client, true /* initiatedByClient */);
919         });
920     }
921 
922     // Should be done on a handler thread - not on the Binder's thread.
startAuthentication(AuthenticationClientImpl client, String opPackageName)923     private void startAuthentication(AuthenticationClientImpl client, String opPackageName) {
924         if (DEBUG) Slog.v(getTag(), "startAuthentication(" + opPackageName + ")");
925 
926         int lockoutMode = getLockoutMode();
927         if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
928             Slog.v(getTag(), "In lockout mode(" + lockoutMode + ") ; disallowing authentication");
929             int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ?
930                     BiometricConstants.BIOMETRIC_ERROR_LOCKOUT :
931                     BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
932             if (!client.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */)) {
933                 Slog.w(getTag(), "Cannot send permanent lockout message to client");
934             }
935             return;
936         }
937         startClient(client, true /* initiatedByClient */);
938     }
939 
addLockoutResetCallback(IBiometricServiceLockoutResetCallback callback)940     protected void addLockoutResetCallback(IBiometricServiceLockoutResetCallback callback) {
941         mHandler.post(() -> {
942            final LockoutResetMonitor monitor = new LockoutResetMonitor(callback);
943            if (!mLockoutMonitors.contains(monitor)) {
944                mLockoutMonitors.add(monitor);
945            }
946         });
947     }
948 
949     /**
950      * Helper methods.
951      */
952 
953     /**
954      * @param opPackageName name of package for caller
955      * @param requireForeground only allow this call while app is in the foreground
956      * @return true if caller can use the biometric API
957      */
canUseBiometric(String opPackageName, boolean requireForeground, int uid, int pid, int userId)958     protected boolean canUseBiometric(String opPackageName, boolean requireForeground, int uid,
959             int pid, int userId) {
960         checkUseBiometricPermission();
961 
962 
963         if (Binder.getCallingUid() == Process.SYSTEM_UID) {
964             return true; // System process (BiometricService, etc) is always allowed
965         }
966         if (isKeyguard(opPackageName)) {
967             return true; // Keyguard is always allowed
968         }
969         if (!isCurrentUserOrProfile(userId)) {
970             Slog.w(getTag(), "Rejecting " + opPackageName + "; not a current user or profile");
971             return false;
972         }
973         if (!checkAppOps(uid, opPackageName)) {
974             Slog.w(getTag(), "Rejecting " + opPackageName + "; permission denied");
975             return false;
976         }
977 
978         if (requireForeground && !(isForegroundActivity(uid, pid) || isCurrentClient(
979                 opPackageName))) {
980             Slog.w(getTag(), "Rejecting " + opPackageName + "; not in foreground");
981             return false;
982         }
983         return true;
984     }
985 
986     /**
987      * @param opPackageName package of the caller
988      * @return true if this is the same client currently using the biometric
989      */
isCurrentClient(String opPackageName)990     private boolean isCurrentClient(String opPackageName) {
991         return mCurrentClient != null && mCurrentClient.getOwnerString().equals(opPackageName);
992     }
993 
994     /**
995      * @return true if this is keyguard package
996      */
isKeyguard(String clientPackage)997     private boolean isKeyguard(String clientPackage) {
998         return mKeyguardPackage.equals(clientPackage);
999     }
1000 
isForegroundActivity(int uid, int pid)1001     private boolean isForegroundActivity(int uid, int pid) {
1002         try {
1003             List<ActivityManager.RunningAppProcessInfo> procs =
1004                     ActivityManager.getService().getRunningAppProcesses();
1005             int N = procs.size();
1006             for (int i = 0; i < N; i++) {
1007                 ActivityManager.RunningAppProcessInfo proc = procs.get(i);
1008                 if (proc.pid == pid && proc.uid == uid
1009                         && proc.importance <= IMPORTANCE_FOREGROUND_SERVICE) {
1010                     return true;
1011                 }
1012             }
1013         } catch (RemoteException e) {
1014             Slog.w(getTag(), "am.getRunningAppProcesses() failed");
1015         }
1016         return false;
1017     }
1018 
1019     /**
1020      * Calls the HAL to switch states to the new task. If there's already a current task,
1021      * it calls cancel() and sets mPendingClient to begin when the current task finishes
1022      * ({@link BiometricConstants#BIOMETRIC_ERROR_CANCELED}).
1023      *
1024      * @param newClient the new client that wants to connect
1025      * @param initiatedByClient true for authenticate, remove and enroll
1026      */
startClient(ClientMonitor newClient, boolean initiatedByClient)1027     private void startClient(ClientMonitor newClient, boolean initiatedByClient) {
1028         ClientMonitor currentClient = mCurrentClient;
1029         if (currentClient != null) {
1030             if (DEBUG) Slog.v(getTag(), "request stop current client " +
1031                     currentClient.getOwnerString());
1032             // This check only matters for FingerprintService, since enumerate may call back
1033             // multiple times.
1034             if (currentClient instanceof InternalEnumerateClient
1035                     || currentClient instanceof InternalRemovalClient) {
1036                 // This condition means we're currently running internal diagnostics to
1037                 // remove extra templates in the hardware and/or the software
1038                 // TODO: design an escape hatch in case client never finishes
1039                 if (newClient != null) {
1040                     Slog.w(getTag(), "Internal cleanup in progress but trying to start client "
1041                             + newClient.getClass().getSuperclass().getSimpleName()
1042                             + "(" + newClient.getOwnerString() + ")"
1043                             + ", initiatedByClient = " + initiatedByClient);
1044                 }
1045             } else {
1046                 currentClient.stop(initiatedByClient);
1047 
1048                 // Only post the reset runnable for non-cleanup clients. Cleanup clients should
1049                 // never be forcibly stopped since they ensure synchronization between HAL and
1050                 // framework. Thus, we should instead just start the pending client once cleanup
1051                 // finishes instead of using the reset runnable.
1052                 mHandler.removeCallbacks(mResetClientState);
1053                 mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
1054             }
1055             mPendingClient = newClient;
1056         } else if (newClient != null) {
1057             // For BiometricPrompt clients, do not start until
1058             // <Biometric>Service#startPreparedClient is called. BiometricService waits until all
1059             // modalities are ready before initiating authentication.
1060             if (newClient instanceof AuthenticationClient) {
1061                 AuthenticationClient client = (AuthenticationClient) newClient;
1062                 if (client.isBiometricPrompt()) {
1063                     if (DEBUG) Slog.v(getTag(), "Returning cookie: " + client.getCookie());
1064                     mCurrentClient = newClient;
1065                     if (mBiometricService == null) {
1066                         mBiometricService = IBiometricService.Stub.asInterface(
1067                                 ServiceManager.getService(Context.BIOMETRIC_SERVICE));
1068                     }
1069                     try {
1070                         mBiometricService.onReadyForAuthentication(client.getCookie(),
1071                                 client.getRequireConfirmation(), client.getTargetUserId());
1072                     } catch (RemoteException e) {
1073                         Slog.e(getTag(), "Remote exception", e);
1074                     }
1075                     return;
1076                 }
1077             }
1078 
1079             // We are not a BiometricPrompt client, start the client immediately
1080             mCurrentClient = newClient;
1081             startCurrentClient(mCurrentClient.getCookie());
1082         }
1083     }
1084 
startCurrentClient(int cookie)1085     protected void startCurrentClient(int cookie) {
1086         if (mCurrentClient == null) {
1087             Slog.e(getTag(), "Trying to start null client!");
1088             return;
1089         }
1090         if (DEBUG) Slog.v(getTag(), "starting client "
1091                 + mCurrentClient.getClass().getSuperclass().getSimpleName()
1092                 + "(" + mCurrentClient.getOwnerString() + ")"
1093                 + " cookie: " + cookie + "/" + mCurrentClient.getCookie());
1094         if (cookie != mCurrentClient.getCookie()) {
1095             Slog.e(getTag(), "Mismatched cookie");
1096             return;
1097         }
1098         notifyClientActiveCallbacks(true);
1099         mCurrentClient.start();
1100     }
1101 
removeClient(ClientMonitor client)1102     protected void removeClient(ClientMonitor client) {
1103         if (client != null) {
1104             client.destroy();
1105             if (client != mCurrentClient && mCurrentClient != null) {
1106                 Slog.w(getTag(), "Unexpected client: " + client.getOwnerString() + "expected: "
1107                         + mCurrentClient.getOwnerString());
1108             }
1109         }
1110         if (mCurrentClient != null) {
1111             if (DEBUG) Slog.v(getTag(), "Done with client: " + client.getOwnerString());
1112             mCurrentClient = null;
1113         }
1114         if (mPendingClient == null) {
1115             notifyClientActiveCallbacks(false);
1116         }
1117     }
1118 
1119     /**
1120      * Populates existing authenticator ids. To be used only during the start of the service.
1121      */
loadAuthenticatorIds()1122     protected void loadAuthenticatorIds() {
1123         // This operation can be expensive, so keep track of the elapsed time. Might need to move to
1124         // background if it takes too long.
1125         long t = System.currentTimeMillis();
1126         mAuthenticatorIds.clear();
1127         for (UserInfo user : UserManager.get(getContext()).getUsers(true /* excludeDying */)) {
1128             int userId = getUserOrWorkProfileId(null, user.id);
1129             if (!mAuthenticatorIds.containsKey(userId)) {
1130                 updateActiveGroup(userId, null);
1131             }
1132         }
1133 
1134         t = System.currentTimeMillis() - t;
1135         if (t > 1000) {
1136             Slog.w(getTag(), "loadAuthenticatorIds() taking too long: " + t + "ms");
1137         }
1138     }
1139 
1140     /**
1141      * @param clientPackage the package of the caller
1142      * @return the profile id
1143      */
getUserOrWorkProfileId(String clientPackage, int userId)1144     protected int getUserOrWorkProfileId(String clientPackage, int userId) {
1145         if (!isKeyguard(clientPackage) && isWorkProfile(userId)) {
1146             return userId;
1147         }
1148         return getEffectiveUserId(userId);
1149     }
1150 
isRestricted()1151     protected boolean isRestricted() {
1152         // Only give privileged apps (like Settings) access to biometric info
1153         final boolean restricted = !hasPermission(getManageBiometricPermission());
1154         return restricted;
1155     }
1156 
hasPermission(String permission)1157     protected boolean hasPermission(String permission) {
1158         return getContext().checkCallingOrSelfPermission(permission)
1159                 == PackageManager.PERMISSION_GRANTED;
1160     }
1161 
checkPermission(String permission)1162     protected void checkPermission(String permission) {
1163         getContext().enforceCallingOrSelfPermission(permission,
1164                 "Must have " + permission + " permission.");
1165     }
1166 
isCurrentUserOrProfile(int userId)1167     protected boolean isCurrentUserOrProfile(int userId) {
1168         UserManager um = UserManager.get(mContext);
1169         if (um == null) {
1170             Slog.e(getTag(), "Unable to acquire UserManager");
1171             return false;
1172         }
1173 
1174         final long token = Binder.clearCallingIdentity();
1175         try {
1176             // Allow current user or profiles of the current user...
1177             for (int profileId : um.getEnabledProfileIds(ActivityManager.getCurrentUser())) {
1178                 if (profileId == userId) {
1179                     return true;
1180                 }
1181             }
1182         } finally {
1183             Binder.restoreCallingIdentity(token);
1184         }
1185 
1186         return false;
1187     }
1188 
1189     /***
1190      * @param opPackageName the name of the calling package
1191      * @return authenticator id for the calling user
1192      */
getAuthenticatorId(String opPackageName)1193     protected long getAuthenticatorId(String opPackageName) {
1194         final int userId = getUserOrWorkProfileId(opPackageName, UserHandle.getCallingUserId());
1195         return mAuthenticatorIds.getOrDefault(userId, 0L);
1196     }
1197 
1198     /**
1199      * This method should be called upon connection to the daemon, and when user switches.
1200      * @param userId
1201      */
doTemplateCleanupForUser(int userId)1202     protected void doTemplateCleanupForUser(int userId) {
1203         if (CLEANUP_UNKNOWN_TEMPLATES) {
1204             enumerateUser(userId);
1205         }
1206     }
1207 
clearEnumerateState()1208     private void clearEnumerateState() {
1209         if (DEBUG) Slog.v(getTag(), "clearEnumerateState()");
1210         mUnknownHALTemplates.clear();
1211     }
1212 
1213     /**
1214      * Remove unknown templates from HAL
1215      */
startCleanupUnknownHALTemplates()1216     private void startCleanupUnknownHALTemplates() {
1217         if (!mUnknownHALTemplates.isEmpty()) {
1218             UserTemplate template = mUnknownHALTemplates.get(0);
1219             mUnknownHALTemplates.remove(template);
1220             boolean restricted = !hasPermission(getManageBiometricPermission());
1221             InternalRemovalClient client = new InternalRemovalClient(getContext(),
1222                     getDaemonWrapper(), mHalDeviceId, mToken, null /* listener */,
1223                     template.mIdentifier.getBiometricId(), 0 /* groupId */, template.mUserId,
1224                     restricted, getContext().getPackageName());
1225             removeInternal(client);
1226             StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
1227                     statsModality(),
1228                     BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL);
1229         } else {
1230             clearEnumerateState();
1231             if (mPendingClient != null) {
1232                 Slog.d(getTag(), "Enumerate finished, starting pending client");
1233                 startClient(mPendingClient, false /* initiatedByClient */);
1234                 mPendingClient = null;
1235             }
1236         }
1237     }
1238 
enumerateUser(int userId)1239     private void enumerateUser(int userId) {
1240         if (DEBUG) Slog.v(getTag(), "Enumerating user(" + userId + ")");
1241 
1242         final boolean restricted = !hasPermission(getManageBiometricPermission());
1243         final List<? extends BiometricAuthenticator.Identifier> enrolledList =
1244                 getEnrolledTemplates(userId);
1245 
1246         InternalEnumerateClient client = new InternalEnumerateClient(getContext(),
1247                 getDaemonWrapper(), mHalDeviceId, mToken, null /* serviceListener */, userId,
1248                 userId, restricted, getContext().getOpPackageName(), enrolledList,
1249                 getBiometricUtils());
1250         enumerateInternal(client);
1251     }
1252 
1253     /**
1254      * This method is called when the user switches. Implementations should probably notify the
1255      * HAL.
1256      */
handleUserSwitching(int userId)1257     protected void handleUserSwitching(int userId) {
1258         if (getCurrentClient() instanceof InternalRemovalClient
1259                 || getCurrentClient() instanceof InternalEnumerateClient) {
1260             Slog.w(getTag(), "User switched while performing cleanup");
1261         }
1262         updateActiveGroup(userId, null);
1263         doTemplateCleanupForUser(userId);
1264     }
1265 
notifyLockoutResetMonitors()1266     protected void notifyLockoutResetMonitors() {
1267         for (int i = 0; i < mLockoutMonitors.size(); i++) {
1268             mLockoutMonitors.get(i).sendLockoutReset();
1269         }
1270     }
1271 
userActivity()1272     private void userActivity() {
1273         long now = SystemClock.uptimeMillis();
1274         mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
1275     }
1276 
1277     /**
1278      * @param userId
1279      * @return true if this is a work profile
1280      */
isWorkProfile(int userId)1281     private boolean isWorkProfile(int userId) {
1282         UserInfo userInfo = null;
1283         final long token = Binder.clearCallingIdentity();
1284         try {
1285             userInfo = mUserManager.getUserInfo(userId);
1286         } finally {
1287             Binder.restoreCallingIdentity(token);
1288         }
1289         return userInfo != null && userInfo.isManagedProfile();
1290     }
1291 
1292 
getEffectiveUserId(int userId)1293     private int getEffectiveUserId(int userId) {
1294         UserManager um = UserManager.get(mContext);
1295         if (um != null) {
1296             final long callingIdentity = Binder.clearCallingIdentity();
1297             userId = um.getCredentialOwnerProfile(userId);
1298             Binder.restoreCallingIdentity(callingIdentity);
1299         } else {
1300             Slog.e(getTag(), "Unable to acquire UserManager");
1301         }
1302         return userId;
1303     }
1304 
1305 
listenForUserSwitches()1306     private void listenForUserSwitches() {
1307         try {
1308             ActivityManager.getService().registerUserSwitchObserver(
1309                     new SynchronousUserSwitchObserver() {
1310                         @Override
1311                         public void onUserSwitching(int newUserId) throws RemoteException {
1312                             mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */)
1313                                     .sendToTarget();
1314                         }
1315                     }, getTag());
1316         } catch (RemoteException e) {
1317             Slog.w(getTag(), "Failed to listen for user switching event" ,e);
1318         }
1319     }
1320 
removeLockoutResetCallback( LockoutResetMonitor monitor)1321     private void removeLockoutResetCallback(
1322             LockoutResetMonitor monitor) {
1323         mLockoutMonitors.remove(monitor);
1324     }
1325 }
1326