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