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