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