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, int timeoutSec)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, int timeoutSec) { 286 super(context, getConstants(), daemon, halDeviceId, token, listener, 287 userId, groupId, cryptoToken, restricted, owner, getBiometricUtils(), 288 disabledFeatures, timeoutSec); 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 Runnable mOnTaskStackChangedRunnable = new Runnable() { 501 @Override 502 public void run() { 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: " 518 + topPackage + " 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 BiometricTaskStackListener extends TaskStackListener { 529 @Override onTaskStackChanged()530 public void onTaskStackChanged() { 531 mHandler.post(mOnTaskStackChangedRunnable); 532 } 533 } 534 535 private final class ResetClientStateRunnable implements Runnable { 536 @Override run()537 public void run() { 538 /** 539 * Warning: if we get here, the driver never confirmed our call to cancel the current 540 * operation (authenticate, enroll, remove, enumerate, etc), which is 541 * really bad. The result will be a 3-second delay in starting each new client. 542 * If you see this on a device, make certain the driver notifies with 543 * {@link BiometricConstants#BIOMETRIC_ERROR_CANCELED} in response to cancel() 544 * once it has successfully switched to the IDLE state in the HAL. 545 * Additionally,{@link BiometricConstants#BIOMETRIC_ERROR_CANCELED} should only be sent 546 * in response to an actual cancel() call. 547 */ 548 Slog.w(getTag(), "Client " 549 + (mCurrentClient != null ? mCurrentClient.getOwnerString() : "null") 550 + " failed to respond to cancel, starting client " 551 + (mPendingClient != null ? mPendingClient.getOwnerString() : "null")); 552 553 StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, 554 statsModality(), BiometricsProtoEnums.ISSUE_CANCEL_TIMED_OUT); 555 556 mCurrentClient = null; 557 startClient(mPendingClient, false); 558 } 559 } 560 561 562 563 private final class LockoutResetMonitor implements IBinder.DeathRecipient { 564 private static final long WAKELOCK_TIMEOUT_MS = 2000; 565 private final IBiometricServiceLockoutResetCallback mCallback; 566 private final PowerManager.WakeLock mWakeLock; 567 LockoutResetMonitor(IBiometricServiceLockoutResetCallback callback)568 public LockoutResetMonitor(IBiometricServiceLockoutResetCallback callback) { 569 mCallback = callback; 570 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 571 "lockout reset callback"); 572 try { 573 mCallback.asBinder().linkToDeath(LockoutResetMonitor.this, 0); 574 } catch (RemoteException e) { 575 Slog.w(getTag(), "caught remote exception in linkToDeath", e); 576 } 577 } 578 sendLockoutReset()579 public void sendLockoutReset() { 580 if (mCallback != null) { 581 try { 582 mWakeLock.acquire(WAKELOCK_TIMEOUT_MS); 583 mCallback.onLockoutReset(getHalDeviceId(), new IRemoteCallback.Stub() { 584 @Override 585 public void sendResult(Bundle data) throws RemoteException { 586 releaseWakelock(); 587 } 588 }); 589 } catch (DeadObjectException e) { 590 Slog.w(getTag(), "Death object while invoking onLockoutReset: ", e); 591 mHandler.post(mRemoveCallbackRunnable); 592 } catch (RemoteException e) { 593 Slog.w(getTag(), "Failed to invoke onLockoutReset: ", e); 594 releaseWakelock(); 595 } 596 } 597 } 598 599 private final Runnable mRemoveCallbackRunnable = new Runnable() { 600 @Override 601 public void run() { 602 releaseWakelock(); 603 removeLockoutResetCallback(LockoutResetMonitor.this); 604 } 605 }; 606 607 @Override binderDied()608 public void binderDied() { 609 Slog.e(getTag(), "Lockout reset callback binder died"); 610 mHandler.post(mRemoveCallbackRunnable); 611 } 612 releaseWakelock()613 private void releaseWakelock() { 614 if (mWakeLock.isHeld()) { 615 mWakeLock.release(); 616 } 617 } 618 } 619 620 /** 621 * Container for enumerated templates. Used to keep track when cleaning up unknown 622 * templates. 623 */ 624 private final class UserTemplate { 625 final BiometricAuthenticator.Identifier mIdentifier; 626 final int mUserId; UserTemplate(BiometricAuthenticator.Identifier identifier, int userId)627 UserTemplate(BiometricAuthenticator.Identifier identifier, int userId) { 628 this.mIdentifier = identifier; 629 this.mUserId = userId; 630 } 631 } 632 633 /** 634 * Initializes the system service. 635 * <p> 636 * Subclasses must define a single argument constructor that accepts the context 637 * and passes it to super. 638 * </p> 639 * 640 * @param context The system server context. 641 */ BiometricServiceBase(Context context)642 public BiometricServiceBase(Context context) { 643 super(context); 644 mContext = context; 645 mStatusBarService = IStatusBarService.Stub.asInterface( 646 ServiceManager.getService(Context.STATUS_BAR_SERVICE)); 647 mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString( 648 com.android.internal.R.string.config_keyguardComponent)).getPackageName(); 649 mAppOps = context.getSystemService(AppOpsManager.class); 650 mActivityTaskManager = ((ActivityTaskManager) context.getSystemService( 651 Context.ACTIVITY_TASK_SERVICE)).getService(); 652 mPowerManager = mContext.getSystemService(PowerManager.class); 653 mUserManager = UserManager.get(mContext); 654 mMetricsLogger = new MetricsLogger(); 655 } 656 657 @Override onStart()658 public void onStart() { 659 listenForUserSwitches(); 660 } 661 662 @Override serviceDied(long cookie)663 public void serviceDied(long cookie) { 664 Slog.e(getTag(), "HAL died"); 665 mMetricsLogger.count(getConstants().tagHalDied(), 1); 666 mHALDeathCount++; 667 mCurrentUserId = UserHandle.USER_NULL; 668 669 // All client lifecycle must be managed on the handler. 670 mHandler.post(() -> { 671 handleError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 672 0 /*vendorCode */); 673 }); 674 675 StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(), 676 BiometricsProtoEnums.ISSUE_HAL_DEATH); 677 } 678 getCurrentClient()679 protected ClientMonitor getCurrentClient() { 680 return mCurrentClient; 681 } 682 getPendingClient()683 protected ClientMonitor getPendingClient() { 684 return mPendingClient; 685 } 686 687 /** 688 * Callback handlers from the daemon. The caller must put this on a handler. 689 */ 690 handleAcquired(long deviceId, int acquiredInfo, int vendorCode)691 protected void handleAcquired(long deviceId, int acquiredInfo, int vendorCode) { 692 ClientMonitor client = mCurrentClient; 693 if (client != null && client.onAcquired(acquiredInfo, vendorCode)) { 694 removeClient(client); 695 } 696 if (mPerformanceStats != null && getLockoutMode() == AuthenticationClient.LOCKOUT_NONE 697 && client instanceof AuthenticationClient) { 698 // ignore enrollment acquisitions or acquisitions when we're locked out 699 mPerformanceStats.acquire++; 700 } 701 } 702 handleAuthenticated(BiometricAuthenticator.Identifier identifier, ArrayList<Byte> token)703 protected void handleAuthenticated(BiometricAuthenticator.Identifier identifier, 704 ArrayList<Byte> token) { 705 ClientMonitor client = mCurrentClient; 706 final boolean authenticated = identifier.getBiometricId() != 0; 707 708 if (client != null && client.onAuthenticated(identifier, authenticated, token)) { 709 removeClient(client); 710 } 711 if (authenticated) { 712 mPerformanceStats.accept++; 713 } else { 714 mPerformanceStats.reject++; 715 } 716 } 717 handleEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining)718 protected void handleEnrollResult(BiometricAuthenticator.Identifier identifier, 719 int remaining) { 720 ClientMonitor client = mCurrentClient; 721 if (client != null && client.onEnrollResult(identifier, remaining)) { 722 removeClient(client); 723 // When enrollment finishes, update this group's authenticator id, as the HAL has 724 // already generated a new authenticator id when the new biometric is enrolled. 725 if (identifier instanceof Fingerprint) { 726 updateActiveGroup(((Fingerprint)identifier).getGroupId(), null); 727 } 728 } 729 } 730 handleError(long deviceId, int error, int vendorCode)731 protected void handleError(long deviceId, int error, int vendorCode) { 732 final ClientMonitor client = mCurrentClient; 733 734 if (DEBUG) Slog.v(getTag(), "handleError(client=" 735 + (client != null ? client.getOwnerString() : "null") + ", error = " + error + ")"); 736 737 if (client instanceof InternalRemovalClient 738 || client instanceof InternalEnumerateClient) { 739 clearEnumerateState(); 740 } 741 742 if (client != null && client.onError(deviceId, error, vendorCode)) { 743 removeClient(client); 744 } 745 746 if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) { 747 mHandler.removeCallbacks(mResetClientState); 748 if (mPendingClient != null) { 749 if (DEBUG) Slog.v(getTag(), "start pending client " + 750 mPendingClient.getOwnerString()); 751 startClient(mPendingClient, false); 752 mPendingClient = null; 753 } 754 } 755 } 756 handleRemoved(BiometricAuthenticator.Identifier identifier, final int remaining)757 protected void handleRemoved(BiometricAuthenticator.Identifier identifier, 758 final int remaining) { 759 if (DEBUG) Slog.w(getTag(), "Removed: fid=" + identifier.getBiometricId() 760 + ", dev=" + identifier.getDeviceId() 761 + ", rem=" + remaining); 762 763 ClientMonitor client = mCurrentClient; 764 if (client != null && client.onRemoved(identifier, remaining)) { 765 removeClient(client); 766 // When the last biometric of a group is removed, update the authenticator id 767 int userId = mCurrentUserId; 768 if (identifier instanceof Fingerprint) { 769 userId = ((Fingerprint) identifier).getGroupId(); 770 } 771 if (!hasEnrolledBiometrics(userId)) { 772 updateActiveGroup(userId, null); 773 } 774 } 775 776 if (client instanceof InternalRemovalClient && !mUnknownHALTemplates.isEmpty()) { 777 startCleanupUnknownHALTemplates(); 778 } else if (client instanceof InternalRemovalClient) { 779 clearEnumerateState(); 780 } 781 } 782 handleEnumerate(BiometricAuthenticator.Identifier identifier, int remaining)783 protected void handleEnumerate(BiometricAuthenticator.Identifier identifier, int remaining) { 784 ClientMonitor client = getCurrentClient(); 785 786 client.onEnumerationResult(identifier, remaining); 787 788 // All templates in the HAL for this user were enumerated 789 if (remaining == 0) { 790 if (client instanceof InternalEnumerateClient) { 791 List<BiometricAuthenticator.Identifier> unknownHALTemplates = 792 ((InternalEnumerateClient) client).getUnknownHALTemplates(); 793 794 if (!unknownHALTemplates.isEmpty()) { 795 Slog.w(getTag(), "Adding " + unknownHALTemplates.size() 796 + " templates for deletion"); 797 } 798 for (int i = 0; i < unknownHALTemplates.size(); i++) { 799 mUnknownHALTemplates.add(new UserTemplate(unknownHALTemplates.get(i), 800 client.getTargetUserId())); 801 } 802 removeClient(client); 803 startCleanupUnknownHALTemplates(); 804 } else { 805 removeClient(client); 806 } 807 } 808 } 809 810 /** 811 * Calls from the Manager. These are still on the calling binder's thread. 812 */ 813 enrollInternal(EnrollClientImpl client, int userId)814 protected void enrollInternal(EnrollClientImpl client, int userId) { 815 if (hasReachedEnrollmentLimit(userId)) { 816 return; 817 } 818 819 // Group ID is arbitrarily set to parent profile user ID. It just represents 820 // the default biometrics for the user. 821 if (!isCurrentUserOrProfile(userId)) { 822 return; 823 } 824 825 mHandler.post(() -> { 826 startClient(client, true /* initiatedByClient */); 827 }); 828 } 829 cancelEnrollmentInternal(IBinder token)830 protected void cancelEnrollmentInternal(IBinder token) { 831 mHandler.post(() -> { 832 ClientMonitor client = mCurrentClient; 833 if (client instanceof EnrollClient && client.getToken() == token) { 834 if (DEBUG) Slog.v(getTag(), "Cancelling enrollment"); 835 client.stop(client.getToken() == token); 836 } 837 }); 838 } 839 authenticateInternal(AuthenticationClientImpl client, long opId, String opPackageName)840 protected void authenticateInternal(AuthenticationClientImpl client, long opId, 841 String opPackageName) { 842 final int callingUid = Binder.getCallingUid(); 843 final int callingPid = Binder.getCallingPid(); 844 final int callingUserId = UserHandle.getCallingUserId(); 845 authenticateInternal(client, opId, opPackageName, callingUid, callingPid, callingUserId); 846 } 847 authenticateInternal(AuthenticationClientImpl client, long opId, String opPackageName, int callingUid, int callingPid, int callingUserId)848 protected void authenticateInternal(AuthenticationClientImpl client, long opId, 849 String opPackageName, int callingUid, int callingPid, int callingUserId) { 850 if (!canUseBiometric(opPackageName, true /* foregroundOnly */, callingUid, callingPid, 851 callingUserId)) { 852 if (DEBUG) Slog.v(getTag(), "authenticate(): reject " + opPackageName); 853 return; 854 } 855 856 mHandler.post(() -> { 857 mMetricsLogger.histogram(getConstants().tagAuthToken(), opId != 0L ? 1 : 0); 858 859 // Get performance stats object for this user. 860 HashMap<Integer, PerformanceStats> pmap 861 = (opId == 0) ? mPerformanceMap : mCryptoPerformanceMap; 862 PerformanceStats stats = pmap.get(mCurrentUserId); 863 if (stats == null) { 864 stats = new PerformanceStats(); 865 pmap.put(mCurrentUserId, stats); 866 } 867 mPerformanceStats = stats; 868 mIsCrypto = (opId != 0); 869 870 startAuthentication(client, opPackageName); 871 }); 872 } 873 cancelAuthenticationInternal(final IBinder token, final String opPackageName)874 protected void cancelAuthenticationInternal(final IBinder token, final String opPackageName) { 875 final int callingUid = Binder.getCallingUid(); 876 final int callingPid = Binder.getCallingPid(); 877 final int callingUserId = UserHandle.getCallingUserId(); 878 cancelAuthenticationInternal(token, opPackageName, callingUid, callingPid, callingUserId, 879 true /* fromClient */); 880 } 881 cancelAuthenticationInternal(final IBinder token, final String opPackageName, int callingUid, int callingPid, int callingUserId, boolean fromClient)882 protected void cancelAuthenticationInternal(final IBinder token, final String opPackageName, 883 int callingUid, int callingPid, int callingUserId, boolean fromClient) { 884 if (fromClient) { 885 // Only check this if cancel was called from the client (app). If cancel was called 886 // from BiometricService, it means the dialog was dismissed due to user interaction. 887 if (!canUseBiometric(opPackageName, true /* foregroundOnly */, callingUid, callingPid, 888 callingUserId)) { 889 if (DEBUG) Slog.v(getTag(), "cancelAuthentication(): reject " + opPackageName); 890 return; 891 } 892 } 893 894 mHandler.post(() -> { 895 ClientMonitor client = mCurrentClient; 896 if (client instanceof AuthenticationClient) { 897 if (client.getToken() == token || !fromClient) { 898 if (DEBUG) Slog.v(getTag(), "Stopping client " + client.getOwnerString() 899 + ", fromClient: " + fromClient); 900 // If cancel was from BiometricService, it means the dialog was dismissed 901 // and authentication should be canceled. 902 client.stop(client.getToken() == token); 903 } else { 904 if (DEBUG) Slog.v(getTag(), "Can't stop client " + client.getOwnerString() 905 + " since tokens don't match. fromClient: " + fromClient); 906 } 907 } else if (client != null) { 908 if (DEBUG) Slog.v(getTag(), "Can't cancel non-authenticating client " 909 + client.getOwnerString()); 910 } 911 }); 912 } 913 setActiveUserInternal(int userId)914 protected void setActiveUserInternal(int userId) { 915 mHandler.post(() -> { 916 if (DEBUG) { 917 Slog.d(getTag(), "setActiveUser(" + userId + ")"); 918 } 919 updateActiveGroup(userId, null /* clientPackage */); 920 }); 921 } 922 removeInternal(RemovalClient client)923 protected void removeInternal(RemovalClient client) { 924 mHandler.post(() -> { 925 startClient(client, true /* initiatedByClient */); 926 }); 927 } 928 enumerateInternal(EnumerateClient client)929 protected void enumerateInternal(EnumerateClient client) { 930 mHandler.post(() -> { 931 startClient(client, true /* initiatedByClient */); 932 }); 933 } 934 935 // Should be done on a handler thread - not on the Binder's thread. startAuthentication(AuthenticationClientImpl client, String opPackageName)936 private void startAuthentication(AuthenticationClientImpl client, String opPackageName) { 937 if (DEBUG) Slog.v(getTag(), "startAuthentication(" + opPackageName + ")"); 938 939 int lockoutMode = getLockoutMode(); 940 if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) { 941 Slog.v(getTag(), "In lockout mode(" + lockoutMode + ") ; disallowing authentication"); 942 int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ? 943 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT : 944 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT; 945 if (!client.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */)) { 946 Slog.w(getTag(), "Cannot send permanent lockout message to client"); 947 } 948 return; 949 } 950 startClient(client, true /* initiatedByClient */); 951 } 952 addLockoutResetCallback(IBiometricServiceLockoutResetCallback callback)953 protected void addLockoutResetCallback(IBiometricServiceLockoutResetCallback callback) { 954 mHandler.post(() -> { 955 final LockoutResetMonitor monitor = new LockoutResetMonitor(callback); 956 if (!mLockoutMonitors.contains(monitor)) { 957 mLockoutMonitors.add(monitor); 958 } 959 }); 960 } 961 962 /** 963 * Helper methods. 964 */ 965 966 /** 967 * @param opPackageName name of package for caller 968 * @param requireForeground only allow this call while app is in the foreground 969 * @return true if caller can use the biometric API 970 */ canUseBiometric(String opPackageName, boolean requireForeground, int uid, int pid, int userId)971 protected boolean canUseBiometric(String opPackageName, boolean requireForeground, int uid, 972 int pid, int userId) { 973 checkUseBiometricPermission(); 974 975 976 if (Binder.getCallingUid() == Process.SYSTEM_UID) { 977 return true; // System process (BiometricService, etc) is always allowed 978 } 979 if (isKeyguard(opPackageName)) { 980 return true; // Keyguard is always allowed 981 } 982 if (!isCurrentUserOrProfile(userId)) { 983 Slog.w(getTag(), "Rejecting " + opPackageName + "; not a current user or profile"); 984 return false; 985 } 986 if (!checkAppOps(uid, opPackageName)) { 987 Slog.w(getTag(), "Rejecting " + opPackageName + "; permission denied"); 988 return false; 989 } 990 991 if (requireForeground && !(isForegroundActivity(uid, pid) || isCurrentClient( 992 opPackageName))) { 993 Slog.w(getTag(), "Rejecting " + opPackageName + "; not in foreground"); 994 return false; 995 } 996 return true; 997 } 998 999 /** 1000 * @param opPackageName package of the caller 1001 * @return true if this is the same client currently using the biometric 1002 */ isCurrentClient(String opPackageName)1003 private boolean isCurrentClient(String opPackageName) { 1004 return mCurrentClient != null && mCurrentClient.getOwnerString().equals(opPackageName); 1005 } 1006 1007 /** 1008 * @return true if this is keyguard package 1009 */ isKeyguard(String clientPackage)1010 private boolean isKeyguard(String clientPackage) { 1011 return mKeyguardPackage.equals(clientPackage); 1012 } 1013 isForegroundActivity(int uid, int pid)1014 private boolean isForegroundActivity(int uid, int pid) { 1015 try { 1016 List<ActivityManager.RunningAppProcessInfo> procs = 1017 ActivityManager.getService().getRunningAppProcesses(); 1018 int N = procs.size(); 1019 for (int i = 0; i < N; i++) { 1020 ActivityManager.RunningAppProcessInfo proc = procs.get(i); 1021 if (proc.pid == pid && proc.uid == uid 1022 && proc.importance <= IMPORTANCE_FOREGROUND_SERVICE) { 1023 return true; 1024 } 1025 } 1026 } catch (RemoteException e) { 1027 Slog.w(getTag(), "am.getRunningAppProcesses() failed"); 1028 } 1029 return false; 1030 } 1031 1032 /** 1033 * Calls the HAL to switch states to the new task. If there's already a current task, 1034 * it calls cancel() and sets mPendingClient to begin when the current task finishes 1035 * ({@link BiometricConstants#BIOMETRIC_ERROR_CANCELED}). 1036 * 1037 * @param newClient the new client that wants to connect 1038 * @param initiatedByClient true for authenticate, remove and enroll 1039 */ startClient(ClientMonitor newClient, boolean initiatedByClient)1040 private void startClient(ClientMonitor newClient, boolean initiatedByClient) { 1041 ClientMonitor currentClient = mCurrentClient; 1042 if (currentClient != null) { 1043 if (DEBUG) Slog.v(getTag(), "request stop current client " + 1044 currentClient.getOwnerString()); 1045 // This check only matters for FingerprintService, since enumerate may call back 1046 // multiple times. 1047 if (currentClient instanceof InternalEnumerateClient 1048 || currentClient instanceof InternalRemovalClient) { 1049 // This condition means we're currently running internal diagnostics to 1050 // remove extra templates in the hardware and/or the software 1051 // TODO: design an escape hatch in case client never finishes 1052 if (newClient != null) { 1053 Slog.w(getTag(), "Internal cleanup in progress but trying to start client " 1054 + newClient.getClass().getSuperclass().getSimpleName() 1055 + "(" + newClient.getOwnerString() + ")" 1056 + ", initiatedByClient = " + initiatedByClient); 1057 } 1058 } else { 1059 currentClient.stop(initiatedByClient); 1060 1061 // Only post the reset runnable for non-cleanup clients. Cleanup clients should 1062 // never be forcibly stopped since they ensure synchronization between HAL and 1063 // framework. Thus, we should instead just start the pending client once cleanup 1064 // finishes instead of using the reset runnable. 1065 mHandler.removeCallbacks(mResetClientState); 1066 mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT); 1067 } 1068 mPendingClient = newClient; 1069 } else if (newClient != null) { 1070 // For BiometricPrompt clients, do not start until 1071 // <Biometric>Service#startPreparedClient is called. BiometricService waits until all 1072 // modalities are ready before initiating authentication. 1073 if (newClient instanceof AuthenticationClient) { 1074 AuthenticationClient client = (AuthenticationClient) newClient; 1075 if (client.isBiometricPrompt()) { 1076 if (DEBUG) Slog.v(getTag(), "Returning cookie: " + client.getCookie()); 1077 mCurrentClient = newClient; 1078 if (mBiometricService == null) { 1079 mBiometricService = IBiometricService.Stub.asInterface( 1080 ServiceManager.getService(Context.BIOMETRIC_SERVICE)); 1081 } 1082 try { 1083 mBiometricService.onReadyForAuthentication(client.getCookie(), 1084 client.getRequireConfirmation(), client.getTargetUserId()); 1085 } catch (RemoteException e) { 1086 Slog.e(getTag(), "Remote exception", e); 1087 } 1088 return; 1089 } 1090 } 1091 1092 // We are not a BiometricPrompt client, start the client immediately 1093 mCurrentClient = newClient; 1094 startCurrentClient(mCurrentClient.getCookie()); 1095 } 1096 } 1097 startCurrentClient(int cookie)1098 protected void startCurrentClient(int cookie) { 1099 if (mCurrentClient == null) { 1100 Slog.e(getTag(), "Trying to start null client!"); 1101 return; 1102 } 1103 if (DEBUG) Slog.v(getTag(), "starting client " 1104 + mCurrentClient.getClass().getSuperclass().getSimpleName() 1105 + "(" + mCurrentClient.getOwnerString() + ")" 1106 + " targetUserId: " + mCurrentClient.getTargetUserId() 1107 + " currentUserId: " + mCurrentUserId 1108 + " cookie: " + cookie + "/" + mCurrentClient.getCookie()); 1109 if (cookie != mCurrentClient.getCookie()) { 1110 Slog.e(getTag(), "Mismatched cookie"); 1111 return; 1112 } 1113 notifyClientActiveCallbacks(true); 1114 mCurrentClient.start(); 1115 } 1116 removeClient(ClientMonitor client)1117 protected void removeClient(ClientMonitor client) { 1118 if (client != null) { 1119 client.destroy(); 1120 if (client != mCurrentClient && mCurrentClient != null) { 1121 Slog.w(getTag(), "Unexpected client: " + client.getOwnerString() + "expected: " 1122 + mCurrentClient.getOwnerString()); 1123 } 1124 } 1125 if (mCurrentClient != null) { 1126 if (DEBUG) Slog.v(getTag(), "Done with client: " + client.getOwnerString()); 1127 mCurrentClient = null; 1128 } 1129 if (mPendingClient == null) { 1130 notifyClientActiveCallbacks(false); 1131 } 1132 } 1133 1134 /** 1135 * Populates existing authenticator ids. To be used only during the start of the service. 1136 */ loadAuthenticatorIds()1137 protected void loadAuthenticatorIds() { 1138 // This operation can be expensive, so keep track of the elapsed time. Might need to move to 1139 // background if it takes too long. 1140 long t = System.currentTimeMillis(); 1141 mAuthenticatorIds.clear(); 1142 for (UserInfo user : UserManager.get(getContext()).getUsers(true /* excludeDying */)) { 1143 int userId = getUserOrWorkProfileId(null, user.id); 1144 if (!mAuthenticatorIds.containsKey(userId)) { 1145 updateActiveGroup(userId, null); 1146 } 1147 } 1148 1149 t = System.currentTimeMillis() - t; 1150 if (t > 1000) { 1151 Slog.w(getTag(), "loadAuthenticatorIds() taking too long: " + t + "ms"); 1152 } 1153 } 1154 1155 /** 1156 * @param clientPackage the package of the caller 1157 * @return the profile id 1158 */ getUserOrWorkProfileId(String clientPackage, int userId)1159 protected int getUserOrWorkProfileId(String clientPackage, int userId) { 1160 if (!isKeyguard(clientPackage) && isWorkProfile(userId)) { 1161 return userId; 1162 } 1163 return getEffectiveUserId(userId); 1164 } 1165 isRestricted()1166 protected boolean isRestricted() { 1167 // Only give privileged apps (like Settings) access to biometric info 1168 final boolean restricted = !hasPermission(getManageBiometricPermission()); 1169 return restricted; 1170 } 1171 hasPermission(String permission)1172 protected boolean hasPermission(String permission) { 1173 return getContext().checkCallingOrSelfPermission(permission) 1174 == PackageManager.PERMISSION_GRANTED; 1175 } 1176 checkPermission(String permission)1177 protected void checkPermission(String permission) { 1178 getContext().enforceCallingOrSelfPermission(permission, 1179 "Must have " + permission + " permission."); 1180 } 1181 isCurrentUserOrProfile(int userId)1182 protected boolean isCurrentUserOrProfile(int userId) { 1183 UserManager um = UserManager.get(mContext); 1184 if (um == null) { 1185 Slog.e(getTag(), "Unable to acquire UserManager"); 1186 return false; 1187 } 1188 1189 final long token = Binder.clearCallingIdentity(); 1190 try { 1191 // Allow current user or profiles of the current user... 1192 for (int profileId : um.getEnabledProfileIds(ActivityManager.getCurrentUser())) { 1193 if (profileId == userId) { 1194 return true; 1195 } 1196 } 1197 } finally { 1198 Binder.restoreCallingIdentity(token); 1199 } 1200 1201 return false; 1202 } 1203 1204 /*** 1205 * @param opPackageName the name of the calling package 1206 * @return authenticator id for the calling user 1207 */ getAuthenticatorId(String opPackageName)1208 protected long getAuthenticatorId(String opPackageName) { 1209 final int userId = getUserOrWorkProfileId(opPackageName, UserHandle.getCallingUserId()); 1210 return mAuthenticatorIds.getOrDefault(userId, 0L); 1211 } 1212 1213 /** 1214 * This method should be called upon connection to the daemon, and when user switches. 1215 * @param userId 1216 */ doTemplateCleanupForUser(int userId)1217 protected void doTemplateCleanupForUser(int userId) { 1218 if (CLEANUP_UNKNOWN_TEMPLATES) { 1219 enumerateUser(userId); 1220 } 1221 } 1222 clearEnumerateState()1223 private void clearEnumerateState() { 1224 if (DEBUG) Slog.v(getTag(), "clearEnumerateState()"); 1225 mUnknownHALTemplates.clear(); 1226 } 1227 1228 /** 1229 * Remove unknown templates from HAL 1230 */ startCleanupUnknownHALTemplates()1231 private void startCleanupUnknownHALTemplates() { 1232 if (!mUnknownHALTemplates.isEmpty()) { 1233 UserTemplate template = mUnknownHALTemplates.get(0); 1234 mUnknownHALTemplates.remove(template); 1235 boolean restricted = !hasPermission(getManageBiometricPermission()); 1236 InternalRemovalClient client = new InternalRemovalClient(getContext(), 1237 getDaemonWrapper(), mHalDeviceId, mToken, null /* listener */, 1238 template.mIdentifier.getBiometricId(), 0 /* groupId */, template.mUserId, 1239 restricted, getContext().getPackageName()); 1240 removeInternal(client); 1241 StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, 1242 statsModality(), 1243 BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL); 1244 } else { 1245 clearEnumerateState(); 1246 if (mPendingClient != null) { 1247 Slog.d(getTag(), "Enumerate finished, starting pending client"); 1248 startClient(mPendingClient, false /* initiatedByClient */); 1249 mPendingClient = null; 1250 } 1251 } 1252 } 1253 enumerateUser(int userId)1254 private void enumerateUser(int userId) { 1255 if (DEBUG) Slog.v(getTag(), "Enumerating user(" + userId + ")"); 1256 1257 final boolean restricted = !hasPermission(getManageBiometricPermission()); 1258 final List<? extends BiometricAuthenticator.Identifier> enrolledList = 1259 getEnrolledTemplates(userId); 1260 1261 InternalEnumerateClient client = new InternalEnumerateClient(getContext(), 1262 getDaemonWrapper(), mHalDeviceId, mToken, null /* serviceListener */, userId, 1263 userId, restricted, getContext().getOpPackageName(), enrolledList, 1264 getBiometricUtils()); 1265 enumerateInternal(client); 1266 } 1267 1268 /** 1269 * This method is called when the user switches. Implementations should probably notify the 1270 * HAL. 1271 */ handleUserSwitching(int userId)1272 protected void handleUserSwitching(int userId) { 1273 if (getCurrentClient() instanceof InternalRemovalClient 1274 || getCurrentClient() instanceof InternalEnumerateClient) { 1275 Slog.w(getTag(), "User switched while performing cleanup"); 1276 } 1277 updateActiveGroup(userId, null); 1278 doTemplateCleanupForUser(userId); 1279 } 1280 notifyLockoutResetMonitors()1281 protected void notifyLockoutResetMonitors() { 1282 for (int i = 0; i < mLockoutMonitors.size(); i++) { 1283 mLockoutMonitors.get(i).sendLockoutReset(); 1284 } 1285 } 1286 userActivity()1287 private void userActivity() { 1288 long now = SystemClock.uptimeMillis(); 1289 mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); 1290 } 1291 1292 /** 1293 * @param userId 1294 * @return true if this is a work profile 1295 */ isWorkProfile(int userId)1296 private boolean isWorkProfile(int userId) { 1297 UserInfo userInfo = null; 1298 final long token = Binder.clearCallingIdentity(); 1299 try { 1300 userInfo = mUserManager.getUserInfo(userId); 1301 } finally { 1302 Binder.restoreCallingIdentity(token); 1303 } 1304 return userInfo != null && userInfo.isManagedProfile(); 1305 } 1306 1307 getEffectiveUserId(int userId)1308 private int getEffectiveUserId(int userId) { 1309 UserManager um = UserManager.get(mContext); 1310 if (um != null) { 1311 final long callingIdentity = Binder.clearCallingIdentity(); 1312 userId = um.getCredentialOwnerProfile(userId); 1313 Binder.restoreCallingIdentity(callingIdentity); 1314 } else { 1315 Slog.e(getTag(), "Unable to acquire UserManager"); 1316 } 1317 return userId; 1318 } 1319 1320 listenForUserSwitches()1321 private void listenForUserSwitches() { 1322 try { 1323 ActivityManager.getService().registerUserSwitchObserver( 1324 new SynchronousUserSwitchObserver() { 1325 @Override 1326 public void onUserSwitching(int newUserId) throws RemoteException { 1327 mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */) 1328 .sendToTarget(); 1329 } 1330 }, getTag()); 1331 } catch (RemoteException e) { 1332 Slog.w(getTag(), "Failed to listen for user switching event" ,e); 1333 } 1334 } 1335 removeLockoutResetCallback( LockoutResetMonitor monitor)1336 private void removeLockoutResetCallback( 1337 LockoutResetMonitor monitor) { 1338 mLockoutMonitors.remove(monitor); 1339 } 1340 } 1341