1 /* 2 * Copyright (C) 2014 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.fingerprint; 18 19 import static android.Manifest.permission.INTERACT_ACROSS_USERS; 20 import static android.Manifest.permission.MANAGE_BIOMETRIC; 21 import static android.Manifest.permission.MANAGE_FINGERPRINT; 22 import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT; 23 import static android.Manifest.permission.USE_BIOMETRIC; 24 import static android.Manifest.permission.USE_FINGERPRINT; 25 26 import android.app.ActivityManager; 27 import android.app.AlarmManager; 28 import android.app.AppOpsManager; 29 import android.app.PendingIntent; 30 import android.content.BroadcastReceiver; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.IntentFilter; 34 import android.content.pm.PackageManager; 35 import android.content.pm.UserInfo; 36 import android.hardware.biometrics.BiometricAuthenticator; 37 import android.hardware.biometrics.BiometricConstants; 38 import android.hardware.biometrics.BiometricsProtoEnums; 39 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; 40 import android.hardware.biometrics.IBiometricServiceReceiverInternal; 41 import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint; 42 import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback; 43 import android.hardware.fingerprint.Fingerprint; 44 import android.hardware.fingerprint.FingerprintManager; 45 import android.hardware.fingerprint.IFingerprintClientActiveCallback; 46 import android.hardware.fingerprint.IFingerprintService; 47 import android.hardware.fingerprint.IFingerprintServiceReceiver; 48 import android.os.Binder; 49 import android.os.Build; 50 import android.os.Environment; 51 import android.os.IBinder; 52 import android.os.RemoteException; 53 import android.os.SELinux; 54 import android.os.SystemClock; 55 import android.os.UserHandle; 56 import android.os.UserManager; 57 import android.util.Slog; 58 import android.util.SparseBooleanArray; 59 import android.util.SparseIntArray; 60 import android.util.proto.ProtoOutputStream; 61 62 import com.android.internal.annotations.GuardedBy; 63 import com.android.internal.logging.MetricsLogger; 64 import com.android.internal.util.DumpUtils; 65 import com.android.server.SystemServerInitThreadPool; 66 import com.android.server.biometrics.AuthenticationClient; 67 import com.android.server.biometrics.BiometricServiceBase; 68 import com.android.server.biometrics.BiometricUtils; 69 import com.android.server.biometrics.ClientMonitor; 70 import com.android.server.biometrics.Constants; 71 import com.android.server.biometrics.EnumerateClient; 72 import com.android.server.biometrics.RemovalClient; 73 74 import org.json.JSONArray; 75 import org.json.JSONException; 76 import org.json.JSONObject; 77 78 import java.io.File; 79 import java.io.FileDescriptor; 80 import java.io.PrintWriter; 81 import java.util.ArrayList; 82 import java.util.Collections; 83 import java.util.List; 84 import java.util.concurrent.CopyOnWriteArrayList; 85 86 /** 87 * A service to manage multiple clients that want to access the fingerprint HAL API. 88 * The service is responsible for maintaining a list of clients and dispatching all 89 * fingerprint-related events. 90 * 91 * @hide 92 */ 93 public class FingerprintService extends BiometricServiceBase { 94 95 protected static final String TAG = "FingerprintService"; 96 private static final boolean DEBUG = true; 97 private static final String FP_DATA_DIR = "fpdata"; 98 private static final String ACTION_LOCKOUT_RESET = 99 "com.android.server.biometrics.fingerprint.ACTION_LOCKOUT_RESET"; 100 private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 5; 101 private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 20; 102 private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30 * 1000; 103 private static final String KEY_LOCKOUT_RESET_USER = "lockout_reset_user"; 104 105 private final class ResetFailedAttemptsForUserRunnable implements Runnable { 106 @Override run()107 public void run() { 108 resetFailedAttemptsForUser(true /* clearAttemptCounter */, 109 ActivityManager.getCurrentUser()); 110 } 111 } 112 113 private final class LockoutReceiver extends BroadcastReceiver { 114 @Override onReceive(Context context, Intent intent)115 public void onReceive(Context context, Intent intent) { 116 Slog.v(getTag(), "Resetting lockout: " + intent.getAction()); 117 if (getLockoutResetIntent().equals(intent.getAction())) { 118 final int user = intent.getIntExtra(KEY_LOCKOUT_RESET_USER, 0); 119 resetFailedAttemptsForUser(false /* clearAttemptCounter */, user); 120 } 121 } 122 } 123 124 private final class FingerprintAuthClient extends AuthenticationClientImpl { 125 @Override isFingerprint()126 protected boolean isFingerprint() { 127 return true; 128 } 129 FingerprintAuthClient(Context context, DaemonWrapper daemon, long halDeviceId, IBinder token, ServiceListener listener, int targetUserId, int groupId, long opId, boolean restricted, String owner, int cookie, boolean requireConfirmation)130 public FingerprintAuthClient(Context context, 131 DaemonWrapper daemon, long halDeviceId, IBinder token, 132 ServiceListener listener, int targetUserId, int groupId, long opId, 133 boolean restricted, String owner, int cookie, 134 boolean requireConfirmation) { 135 super(context, daemon, halDeviceId, token, listener, targetUserId, groupId, opId, 136 restricted, owner, cookie, requireConfirmation); 137 } 138 139 @Override statsModality()140 protected int statsModality() { 141 return FingerprintService.this.statsModality(); 142 } 143 144 @Override resetFailedAttempts()145 public void resetFailedAttempts() { 146 resetFailedAttemptsForUser(true /* clearAttemptCounter */, 147 ActivityManager.getCurrentUser()); 148 } 149 150 @Override shouldFrameworkHandleLockout()151 public boolean shouldFrameworkHandleLockout() { 152 return true; 153 } 154 155 @Override wasUserDetected()156 public boolean wasUserDetected() { 157 // TODO: Return a proper value for devices that use ERROR_TIMEOUT 158 return false; 159 } 160 161 @Override handleFailedAttempt()162 public int handleFailedAttempt() { 163 final int currentUser = ActivityManager.getCurrentUser(); 164 mFailedAttempts.put(currentUser, mFailedAttempts.get(currentUser, 0) + 1); 165 mTimedLockoutCleared.put(ActivityManager.getCurrentUser(), false); 166 167 if (getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) { 168 scheduleLockoutResetForUser(currentUser); 169 } 170 171 return super.handleFailedAttempt(); 172 } 173 } 174 175 /** 176 * Receives the incoming binder calls from FingerprintManager. 177 */ 178 private final class FingerprintServiceWrapper extends IFingerprintService.Stub { 179 private static final int ENROLL_TIMEOUT_SEC = 60; 180 181 /** 182 * The following methods contain common code which is shared in biometrics/common. 183 */ 184 185 @Override // Binder call preEnroll(IBinder token)186 public long preEnroll(IBinder token) { 187 checkPermission(MANAGE_FINGERPRINT); 188 return startPreEnroll(token); 189 } 190 191 @Override // Binder call postEnroll(IBinder token)192 public int postEnroll(IBinder token) { 193 checkPermission(MANAGE_FINGERPRINT); 194 return startPostEnroll(token); 195 } 196 197 @Override // Binder call enroll(final IBinder token, final byte[] cryptoToken, final int userId, final IFingerprintServiceReceiver receiver, final int flags, final String opPackageName)198 public void enroll(final IBinder token, final byte[] cryptoToken, final int userId, 199 final IFingerprintServiceReceiver receiver, final int flags, 200 final String opPackageName) { 201 checkPermission(MANAGE_FINGERPRINT); 202 203 final boolean restricted = isRestricted(); 204 final int groupId = userId; // default group for fingerprint enrollment 205 final EnrollClientImpl client = new EnrollClientImpl(getContext(), mDaemonWrapper, 206 mHalDeviceId, token, new ServiceListenerImpl(receiver), mCurrentUserId, groupId, 207 cryptoToken, restricted, opPackageName, new int[0] /* disabledFeatures */, 208 ENROLL_TIMEOUT_SEC) { 209 @Override 210 public boolean shouldVibrate() { 211 return true; 212 } 213 214 @Override 215 protected int statsModality() { 216 return FingerprintService.this.statsModality(); 217 } 218 }; 219 220 enrollInternal(client, userId); 221 } 222 223 @Override // Binder call cancelEnrollment(final IBinder token)224 public void cancelEnrollment(final IBinder token) { 225 checkPermission(MANAGE_FINGERPRINT); 226 cancelEnrollmentInternal(token); 227 } 228 229 @Override // Binder call authenticate(final IBinder token, final long opId, final int groupId, final IFingerprintServiceReceiver receiver, final int flags, final String opPackageName)230 public void authenticate(final IBinder token, final long opId, final int groupId, 231 final IFingerprintServiceReceiver receiver, final int flags, 232 final String opPackageName) { 233 updateActiveGroup(groupId, opPackageName); 234 final boolean restricted = isRestricted(); 235 final AuthenticationClientImpl client = new FingerprintAuthClient(getContext(), 236 mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver), 237 mCurrentUserId, groupId, opId, restricted, opPackageName, 238 0 /* cookie */, false /* requireConfirmation */); 239 authenticateInternal(client, opId, opPackageName); 240 } 241 242 @Override // Binder call prepareForAuthentication(IBinder token, long opId, int groupId, IBiometricServiceReceiverInternal wrapperReceiver, String opPackageName, int cookie, int callingUid, int callingPid, int callingUserId)243 public void prepareForAuthentication(IBinder token, long opId, int groupId, 244 IBiometricServiceReceiverInternal wrapperReceiver, String opPackageName, 245 int cookie, int callingUid, int callingPid, int callingUserId) { 246 checkPermission(MANAGE_BIOMETRIC); 247 updateActiveGroup(groupId, opPackageName); 248 final boolean restricted = true; // BiometricPrompt is always restricted 249 final AuthenticationClientImpl client = new FingerprintAuthClient(getContext(), 250 mDaemonWrapper, mHalDeviceId, token, 251 new BiometricPromptServiceListenerImpl(wrapperReceiver), 252 mCurrentUserId, groupId, opId, restricted, opPackageName, cookie, 253 false /* requireConfirmation */); 254 authenticateInternal(client, opId, opPackageName, callingUid, callingPid, 255 callingUserId); 256 } 257 258 @Override // Binder call startPreparedClient(int cookie)259 public void startPreparedClient(int cookie) { 260 checkPermission(MANAGE_BIOMETRIC); 261 startCurrentClient(cookie); 262 } 263 264 265 @Override // Binder call cancelAuthentication(final IBinder token, final String opPackageName)266 public void cancelAuthentication(final IBinder token, final String opPackageName) { 267 cancelAuthenticationInternal(token, opPackageName); 268 } 269 270 @Override // Binder call cancelAuthenticationFromService(final IBinder token, final String opPackageName, int callingUid, int callingPid, int callingUserId, boolean fromClient)271 public void cancelAuthenticationFromService(final IBinder token, final String opPackageName, 272 int callingUid, int callingPid, int callingUserId, boolean fromClient) { 273 checkPermission(MANAGE_BIOMETRIC); 274 cancelAuthenticationInternal(token, opPackageName, callingUid, callingPid, 275 callingUserId, fromClient); 276 } 277 278 @Override // Binder call setActiveUser(final int userId)279 public void setActiveUser(final int userId) { 280 checkPermission(MANAGE_FINGERPRINT); 281 setActiveUserInternal(userId); 282 } 283 284 @Override // Binder call remove(final IBinder token, final int fingerId, final int groupId, final int userId, final IFingerprintServiceReceiver receiver)285 public void remove(final IBinder token, final int fingerId, final int groupId, 286 final int userId, final IFingerprintServiceReceiver receiver) { 287 checkPermission(MANAGE_FINGERPRINT); 288 289 if (token == null) { 290 Slog.w(TAG, "remove(): token is null"); 291 return; 292 } 293 294 final boolean restricted = isRestricted(); 295 final RemovalClient client = new RemovalClient(getContext(), getConstants(), 296 mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver), 297 fingerId, groupId, userId, restricted, token.toString(), getBiometricUtils()) { 298 @Override 299 protected int statsModality() { 300 return FingerprintService.this.statsModality(); 301 } 302 }; 303 removeInternal(client); 304 } 305 306 @Override // Binder call enumerate(final IBinder token, final int userId, final IFingerprintServiceReceiver receiver)307 public void enumerate(final IBinder token, final int userId, 308 final IFingerprintServiceReceiver receiver) { 309 checkPermission(MANAGE_FINGERPRINT); 310 311 final boolean restricted = isRestricted(); 312 final EnumerateClient client = new EnumerateClient(getContext(), getConstants(), 313 mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver), userId, 314 userId, restricted, getContext().getOpPackageName()) { 315 @Override 316 protected int statsModality() { 317 return FingerprintService.this.statsModality(); 318 } 319 }; 320 enumerateInternal(client); 321 } 322 323 @Override addLockoutResetCallback(final IBiometricServiceLockoutResetCallback callback)324 public void addLockoutResetCallback(final IBiometricServiceLockoutResetCallback callback) 325 throws RemoteException { 326 FingerprintService.super.addLockoutResetCallback(callback); 327 } 328 329 @Override // Binder call dump(FileDescriptor fd, PrintWriter pw, String[] args)330 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 331 if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) { 332 return; 333 } 334 335 final long ident = Binder.clearCallingIdentity(); 336 try { 337 if (args.length > 0 && "--proto".equals(args[0])) { 338 dumpProto(fd); 339 } else { 340 dumpInternal(pw); 341 } 342 } finally { 343 Binder.restoreCallingIdentity(ident); 344 } 345 } 346 347 /** 348 * The following methods don't use any common code from BiometricService 349 */ 350 351 // TODO: refactor out common code here 352 @Override // Binder call isHardwareDetected(long deviceId, String opPackageName)353 public boolean isHardwareDetected(long deviceId, String opPackageName) { 354 if (!canUseBiometric(opPackageName, false /* foregroundOnly */, 355 Binder.getCallingUid(), Binder.getCallingPid(), 356 UserHandle.getCallingUserId())) { 357 return false; 358 } 359 360 final long token = Binder.clearCallingIdentity(); 361 try { 362 IBiometricsFingerprint daemon = getFingerprintDaemon(); 363 return daemon != null && mHalDeviceId != 0; 364 } finally { 365 Binder.restoreCallingIdentity(token); 366 } 367 } 368 369 @Override // Binder call rename(final int fingerId, final int groupId, final String name)370 public void rename(final int fingerId, final int groupId, final String name) { 371 checkPermission(MANAGE_FINGERPRINT); 372 if (!isCurrentUserOrProfile(groupId)) { 373 return; 374 } 375 mHandler.post(new Runnable() { 376 @Override 377 public void run() { 378 getBiometricUtils().renameBiometricForUser(getContext(), groupId, 379 fingerId, name); 380 } 381 }); 382 } 383 384 @Override // Binder call getEnrolledFingerprints(int userId, String opPackageName)385 public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) { 386 if (!canUseBiometric(opPackageName, false /* foregroundOnly */, 387 Binder.getCallingUid(), Binder.getCallingPid(), 388 UserHandle.getCallingUserId())) { 389 return Collections.emptyList(); 390 } 391 392 return FingerprintService.this.getEnrolledTemplates(userId); 393 } 394 395 @Override // Binder call hasEnrolledFingerprints(int userId, String opPackageName)396 public boolean hasEnrolledFingerprints(int userId, String opPackageName) { 397 if (!canUseBiometric(opPackageName, false /* foregroundOnly */, 398 Binder.getCallingUid(), Binder.getCallingPid(), 399 UserHandle.getCallingUserId())) { 400 return false; 401 } 402 403 return FingerprintService.this.hasEnrolledBiometrics(userId); 404 } 405 406 @Override // Binder call getAuthenticatorId(String opPackageName)407 public long getAuthenticatorId(String opPackageName) { 408 // In this method, we're not checking whether the caller is permitted to use fingerprint 409 // API because current authenticator ID is leaked (in a more contrived way) via Android 410 // Keystore (android.security.keystore package): the user of that API can create a key 411 // which requires fingerprint authentication for its use, and then query the key's 412 // characteristics (hidden API) which returns, among other things, fingerprint 413 // authenticator ID which was active at key creation time. 414 // 415 // Reason: The part of Android Keystore which runs inside an app's process invokes this 416 // method in certain cases. Those cases are not always where the developer demonstrates 417 // explicit intent to use fingerprint functionality. Thus, to avoiding throwing an 418 // unexpected SecurityException this method does not check whether its caller is 419 // permitted to use fingerprint API. 420 // 421 // The permission check should be restored once Android Keystore no longer invokes this 422 // method from inside app processes. 423 424 return FingerprintService.super.getAuthenticatorId(opPackageName); 425 } 426 427 @Override // Binder call resetTimeout(byte [] token)428 public void resetTimeout(byte [] token) { 429 checkPermission(RESET_FINGERPRINT_LOCKOUT); 430 431 if (!FingerprintService.this.hasEnrolledBiometrics(mCurrentUserId)) { 432 Slog.w(TAG, "Ignoring lockout reset, no templates enrolled"); 433 return; 434 } 435 436 // TODO: confirm security token when we move timeout management into the HAL layer. 437 mHandler.post(mResetFailedAttemptsForCurrentUserRunnable); 438 } 439 440 @Override isClientActive()441 public boolean isClientActive() { 442 checkPermission(MANAGE_FINGERPRINT); 443 synchronized(FingerprintService.this) { 444 return (getCurrentClient() != null) || (getPendingClient() != null); 445 } 446 } 447 448 @Override addClientActiveCallback(IFingerprintClientActiveCallback callback)449 public void addClientActiveCallback(IFingerprintClientActiveCallback callback) { 450 checkPermission(MANAGE_FINGERPRINT); 451 mClientActiveCallbacks.add(callback); 452 } 453 454 @Override removeClientActiveCallback(IFingerprintClientActiveCallback callback)455 public void removeClientActiveCallback(IFingerprintClientActiveCallback callback) { 456 checkPermission(MANAGE_FINGERPRINT); 457 mClientActiveCallbacks.remove(callback); 458 } 459 } 460 461 /** 462 * Receives callbacks from the ClientMonitor implementations. The results are forwarded to 463 * BiometricPrompt. 464 */ 465 private class BiometricPromptServiceListenerImpl extends BiometricServiceListener { BiometricPromptServiceListenerImpl(IBiometricServiceReceiverInternal wrapperReceiver)466 BiometricPromptServiceListenerImpl(IBiometricServiceReceiverInternal wrapperReceiver) { 467 super(wrapperReceiver); 468 } 469 470 @Override onAcquired(long deviceId, int acquiredInfo, int vendorCode)471 public void onAcquired(long deviceId, int acquiredInfo, int vendorCode) 472 throws RemoteException { 473 if (getWrapperReceiver() != null) { 474 getWrapperReceiver().onAcquired(acquiredInfo, FingerprintManager.getAcquiredString( 475 getContext(), acquiredInfo, vendorCode)); 476 } 477 } 478 479 @Override onError(long deviceId, int error, int vendorCode, int cookie)480 public void onError(long deviceId, int error, int vendorCode, int cookie) 481 throws RemoteException { 482 if (getWrapperReceiver() != null) { 483 getWrapperReceiver().onError(cookie, error, 484 FingerprintManager.getErrorString(getContext(), error, vendorCode)); 485 } 486 } 487 } 488 489 /** 490 * Receives callbacks from the ClientMonitor implementations. The results are forwarded to 491 * the FingerprintManager. 492 */ 493 private class ServiceListenerImpl implements ServiceListener { 494 private IFingerprintServiceReceiver mFingerprintServiceReceiver; 495 ServiceListenerImpl(IFingerprintServiceReceiver receiver)496 public ServiceListenerImpl(IFingerprintServiceReceiver receiver) { 497 mFingerprintServiceReceiver = receiver; 498 } 499 500 @Override onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining)501 public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining) 502 throws RemoteException { 503 if (mFingerprintServiceReceiver != null) { 504 final Fingerprint fp = (Fingerprint) identifier; 505 mFingerprintServiceReceiver.onEnrollResult(fp.getDeviceId(), fp.getBiometricId(), 506 fp.getGroupId(), remaining); 507 } 508 } 509 510 @Override onAcquired(long deviceId, int acquiredInfo, int vendorCode)511 public void onAcquired(long deviceId, int acquiredInfo, int vendorCode) 512 throws RemoteException { 513 if (mFingerprintServiceReceiver != null) { 514 mFingerprintServiceReceiver.onAcquired(deviceId, acquiredInfo, vendorCode); 515 } 516 } 517 518 @Override onAuthenticationSucceeded(long deviceId, BiometricAuthenticator.Identifier biometric, int userId)519 public void onAuthenticationSucceeded(long deviceId, 520 BiometricAuthenticator.Identifier biometric, int userId) 521 throws RemoteException { 522 if (mFingerprintServiceReceiver != null) { 523 if (biometric == null || biometric instanceof Fingerprint) { 524 mFingerprintServiceReceiver 525 .onAuthenticationSucceeded(deviceId, (Fingerprint) biometric, userId); 526 } else { 527 Slog.e(TAG, "onAuthenticationSucceeded received non-fingerprint biometric"); 528 } 529 } 530 } 531 532 @Override onAuthenticationFailed(long deviceId)533 public void onAuthenticationFailed(long deviceId) throws RemoteException { 534 if (mFingerprintServiceReceiver != null) { 535 mFingerprintServiceReceiver.onAuthenticationFailed(deviceId); 536 } 537 } 538 539 @Override onError(long deviceId, int error, int vendorCode, int cookie)540 public void onError(long deviceId, int error, int vendorCode, int cookie) 541 throws RemoteException { 542 if (mFingerprintServiceReceiver != null) { 543 mFingerprintServiceReceiver.onError(deviceId, error, vendorCode); 544 } 545 } 546 547 @Override onRemoved(BiometricAuthenticator.Identifier identifier, int remaining)548 public void onRemoved(BiometricAuthenticator.Identifier identifier, int remaining) 549 throws RemoteException { 550 if (mFingerprintServiceReceiver != null) { 551 final Fingerprint fp = (Fingerprint) identifier; 552 mFingerprintServiceReceiver.onRemoved(fp.getDeviceId(), fp.getBiometricId(), 553 fp.getGroupId(), remaining); 554 } 555 } 556 557 @Override onEnumerated(BiometricAuthenticator.Identifier identifier, int remaining)558 public void onEnumerated(BiometricAuthenticator.Identifier identifier, int remaining) 559 throws RemoteException { 560 if (mFingerprintServiceReceiver != null) { 561 final Fingerprint fp = (Fingerprint) identifier; 562 mFingerprintServiceReceiver.onEnumerated(fp.getDeviceId(), fp.getBiometricId(), 563 fp.getGroupId(), remaining); 564 } 565 } 566 } 567 568 private final FingerprintConstants mFingerprintConstants = new FingerprintConstants(); 569 private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks = 570 new CopyOnWriteArrayList<>(); 571 572 @GuardedBy("this") 573 private IBiometricsFingerprint mDaemon; 574 private final SparseBooleanArray mTimedLockoutCleared; 575 private final SparseIntArray mFailedAttempts; 576 private final AlarmManager mAlarmManager; 577 private final LockoutReceiver mLockoutReceiver = new LockoutReceiver(); 578 protected final ResetFailedAttemptsForUserRunnable mResetFailedAttemptsForCurrentUserRunnable = 579 new ResetFailedAttemptsForUserRunnable(); 580 581 /** 582 * Receives callbacks from the HAL. 583 */ 584 private IBiometricsFingerprintClientCallback mDaemonCallback = 585 new IBiometricsFingerprintClientCallback.Stub() { 586 @Override 587 public void onEnrollResult(final long deviceId, final int fingerId, final int groupId, 588 final int remaining) { 589 mHandler.post(() -> { 590 final Fingerprint fingerprint = 591 new Fingerprint(getBiometricUtils().getUniqueName(getContext(), groupId), 592 groupId, fingerId, deviceId); 593 FingerprintService.super.handleEnrollResult(fingerprint, remaining); 594 }); 595 } 596 597 @Override 598 public void onAcquired(final long deviceId, final int acquiredInfo, final int vendorCode) { 599 mHandler.post(() -> { 600 FingerprintService.super.handleAcquired(deviceId, acquiredInfo, vendorCode); 601 }); 602 } 603 604 @Override 605 public void onAuthenticated(final long deviceId, final int fingerId, final int groupId, 606 ArrayList<Byte> token) { 607 mHandler.post(() -> { 608 Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId); 609 FingerprintService.super.handleAuthenticated(fp, token); 610 }); 611 } 612 613 @Override 614 public void onError(final long deviceId, final int error, final int vendorCode) { 615 mHandler.post(() -> { 616 FingerprintService.super.handleError(deviceId, error, vendorCode); 617 // TODO: this chunk of code should be common to all biometric services 618 if (error == BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE) { 619 // If we get HW_UNAVAILABLE, try to connect again later... 620 Slog.w(TAG, "Got ERROR_HW_UNAVAILABLE; try reconnecting next client."); 621 synchronized (this) { 622 mDaemon = null; 623 mHalDeviceId = 0; 624 mCurrentUserId = UserHandle.USER_NULL; 625 } 626 } 627 }); 628 } 629 630 @Override 631 public void onRemoved(final long deviceId, final int fingerId, final int groupId, 632 final int remaining) { 633 mHandler.post(() -> { 634 ClientMonitor client = getCurrentClient(); 635 final Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId); 636 FingerprintService.super.handleRemoved(fp, remaining); 637 }); 638 } 639 640 @Override 641 public void onEnumerate(final long deviceId, final int fingerId, final int groupId, 642 final int remaining) { 643 mHandler.post(() -> { 644 final Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId); 645 FingerprintService.super.handleEnumerate(fp, remaining); 646 }); 647 648 } 649 }; 650 651 /** 652 * Wraps the HAL-specific code and is passed to the ClientMonitor implementations so that they 653 * can be shared between the multiple biometric services. 654 */ 655 private final DaemonWrapper mDaemonWrapper = new DaemonWrapper() { 656 @Override 657 public int authenticate(long operationId, int groupId) throws RemoteException { 658 IBiometricsFingerprint daemon = getFingerprintDaemon(); 659 if (daemon == null) { 660 Slog.w(TAG, "authenticate(): no fingerprint HAL!"); 661 return ERROR_ESRCH; 662 } 663 return daemon.authenticate(operationId, groupId); 664 } 665 666 @Override 667 public int cancel() throws RemoteException { 668 IBiometricsFingerprint daemon = getFingerprintDaemon(); 669 if (daemon == null) { 670 Slog.w(TAG, "cancel(): no fingerprint HAL!"); 671 return ERROR_ESRCH; 672 } 673 return daemon.cancel(); 674 } 675 676 @Override 677 public int remove(int groupId, int biometricId) throws RemoteException { 678 IBiometricsFingerprint daemon = getFingerprintDaemon(); 679 if (daemon == null) { 680 Slog.w(TAG, "remove(): no fingerprint HAL!"); 681 return ERROR_ESRCH; 682 } 683 return daemon.remove(groupId, biometricId); 684 } 685 686 @Override 687 public int enumerate() throws RemoteException { 688 IBiometricsFingerprint daemon = getFingerprintDaemon(); 689 if (daemon == null) { 690 Slog.w(TAG, "enumerate(): no fingerprint HAL!"); 691 return ERROR_ESRCH; 692 } 693 return daemon.enumerate(); 694 } 695 696 @Override 697 public int enroll(byte[] cryptoToken, int groupId, int timeout, 698 ArrayList<Integer> disabledFeatures) throws RemoteException { 699 IBiometricsFingerprint daemon = getFingerprintDaemon(); 700 if (daemon == null) { 701 Slog.w(TAG, "enroll(): no fingerprint HAL!"); 702 return ERROR_ESRCH; 703 } 704 return daemon.enroll(cryptoToken, groupId, timeout); 705 } 706 707 @Override 708 public void resetLockout(byte[] token) throws RemoteException { 709 // TODO: confirm security token when we move timeout management into the HAL layer. 710 Slog.e(TAG, "Not supported"); 711 return; 712 } 713 }; 714 FingerprintService(Context context)715 public FingerprintService(Context context) { 716 super(context); 717 mTimedLockoutCleared = new SparseBooleanArray(); 718 mFailedAttempts = new SparseIntArray(); 719 mAlarmManager = context.getSystemService(AlarmManager.class); 720 context.registerReceiver(mLockoutReceiver, new IntentFilter(getLockoutResetIntent()), 721 getLockoutBroadcastPermission(), null /* handler */); 722 } 723 724 @Override onStart()725 public void onStart() { 726 super.onStart(); 727 publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper()); 728 SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart"); 729 } 730 731 @Override getTag()732 protected String getTag() { 733 return TAG; 734 } 735 736 @Override getDaemonWrapper()737 protected DaemonWrapper getDaemonWrapper() { 738 return mDaemonWrapper; 739 } 740 741 @Override getBiometricUtils()742 protected BiometricUtils getBiometricUtils() { 743 return FingerprintUtils.getInstance(); 744 } 745 746 @Override getConstants()747 protected Constants getConstants() { 748 return mFingerprintConstants; 749 } 750 751 @Override hasReachedEnrollmentLimit(int userId)752 protected boolean hasReachedEnrollmentLimit(int userId) { 753 final int limit = getContext().getResources().getInteger( 754 com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser); 755 final int enrolled = FingerprintService.this.getEnrolledTemplates(userId).size(); 756 if (enrolled >= limit) { 757 Slog.w(TAG, "Too many fingerprints registered"); 758 return true; 759 } 760 return false; 761 } 762 763 @Override serviceDied(long cookie)764 public void serviceDied(long cookie) { 765 super.serviceDied(cookie); 766 mDaemon = null; 767 } 768 769 @Override updateActiveGroup(int userId, String clientPackage)770 protected void updateActiveGroup(int userId, String clientPackage) { 771 IBiometricsFingerprint daemon = getFingerprintDaemon(); 772 773 if (daemon != null) { 774 try { 775 userId = getUserOrWorkProfileId(clientPackage, userId); 776 if (userId != mCurrentUserId) { 777 int firstSdkInt = Build.VERSION.FIRST_SDK_INT; 778 if (firstSdkInt < Build.VERSION_CODES.BASE) { 779 Slog.e(TAG, "First SDK version " + firstSdkInt + " is invalid; must be " + 780 "at least VERSION_CODES.BASE"); 781 } 782 File baseDir; 783 if (firstSdkInt <= Build.VERSION_CODES.O_MR1) { 784 baseDir = Environment.getUserSystemDirectory(userId); 785 } else { 786 baseDir = Environment.getDataVendorDeDirectory(userId); 787 } 788 789 File fpDir = new File(baseDir, FP_DATA_DIR); 790 if (!fpDir.exists()) { 791 if (!fpDir.mkdir()) { 792 Slog.v(TAG, "Cannot make directory: " + fpDir.getAbsolutePath()); 793 return; 794 } 795 // Calling mkdir() from this process will create a directory with our 796 // permissions (inherited from the containing dir). This command fixes 797 // the label. 798 if (!SELinux.restorecon(fpDir)) { 799 Slog.w(TAG, "Restorecons failed. Directory will have wrong label."); 800 return; 801 } 802 } 803 804 daemon.setActiveGroup(userId, fpDir.getAbsolutePath()); 805 mCurrentUserId = userId; 806 } 807 mAuthenticatorIds.put(userId, 808 hasEnrolledBiometrics(userId) ? daemon.getAuthenticatorId() : 0L); 809 } catch (RemoteException e) { 810 Slog.e(TAG, "Failed to setActiveGroup():", e); 811 } 812 } 813 } 814 815 @Override getLockoutResetIntent()816 protected String getLockoutResetIntent() { 817 return ACTION_LOCKOUT_RESET; 818 } 819 820 @Override getLockoutBroadcastPermission()821 protected String getLockoutBroadcastPermission() { 822 return RESET_FINGERPRINT_LOCKOUT; 823 } 824 825 @Override getHalDeviceId()826 protected long getHalDeviceId() { 827 return mHalDeviceId; 828 } 829 830 @Override hasEnrolledBiometrics(int userId)831 protected boolean hasEnrolledBiometrics(int userId) { 832 if (userId != UserHandle.getCallingUserId()) { 833 checkPermission(INTERACT_ACROSS_USERS); 834 } 835 return getBiometricUtils().getBiometricsForUser(getContext(), userId).size() > 0; 836 } 837 838 @Override getManageBiometricPermission()839 protected String getManageBiometricPermission() { 840 return MANAGE_FINGERPRINT; 841 } 842 843 @Override checkUseBiometricPermission()844 protected void checkUseBiometricPermission() { 845 if (getContext().checkCallingPermission(USE_FINGERPRINT) 846 != PackageManager.PERMISSION_GRANTED) { 847 checkPermission(USE_BIOMETRIC); 848 } 849 } 850 851 @Override checkAppOps(int uid, String opPackageName)852 protected boolean checkAppOps(int uid, String opPackageName) { 853 boolean appOpsOk = false; 854 if (mAppOps.noteOp(AppOpsManager.OP_USE_BIOMETRIC, uid, opPackageName) 855 == AppOpsManager.MODE_ALLOWED) { 856 appOpsOk = true; 857 } else if (mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, uid, opPackageName) 858 == AppOpsManager.MODE_ALLOWED) { 859 appOpsOk = true; 860 } 861 return appOpsOk; 862 } 863 864 @Override getEnrolledTemplates(int userId)865 protected List<Fingerprint> getEnrolledTemplates(int userId) { 866 if (userId != UserHandle.getCallingUserId()) { 867 checkPermission(INTERACT_ACROSS_USERS); 868 } 869 return getBiometricUtils().getBiometricsForUser(getContext(), userId); 870 } 871 872 @Override notifyClientActiveCallbacks(boolean isActive)873 protected void notifyClientActiveCallbacks(boolean isActive) { 874 List<IFingerprintClientActiveCallback> callbacks = mClientActiveCallbacks; 875 for (int i = 0; i < callbacks.size(); i++) { 876 try { 877 callbacks.get(i).onClientActiveChanged(isActive); 878 } catch (RemoteException re) { 879 // If the remote is dead, stop notifying it 880 mClientActiveCallbacks.remove(callbacks.get(i)); 881 } 882 } 883 } 884 885 @Override statsModality()886 protected int statsModality() { 887 return BiometricsProtoEnums.MODALITY_FINGERPRINT; 888 } 889 890 @Override getLockoutMode()891 protected int getLockoutMode() { 892 final int currentUser = ActivityManager.getCurrentUser(); 893 final int failedAttempts = mFailedAttempts.get(currentUser, 0); 894 if (failedAttempts >= MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT) { 895 return AuthenticationClient.LOCKOUT_PERMANENT; 896 } else if (failedAttempts > 0 897 && !mTimedLockoutCleared.get(currentUser, false) 898 && (failedAttempts % MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED == 0)) { 899 return AuthenticationClient.LOCKOUT_TIMED; 900 } 901 return AuthenticationClient.LOCKOUT_NONE; 902 } 903 904 /** Gets the fingerprint daemon */ getFingerprintDaemon()905 private synchronized IBiometricsFingerprint getFingerprintDaemon() { 906 if (mDaemon == null) { 907 Slog.v(TAG, "mDaemon was null, reconnect to fingerprint"); 908 try { 909 mDaemon = IBiometricsFingerprint.getService(); 910 } catch (java.util.NoSuchElementException e) { 911 // Service doesn't exist or cannot be opened. Logged below. 912 } catch (RemoteException e) { 913 Slog.e(TAG, "Failed to get biometric interface", e); 914 } 915 if (mDaemon == null) { 916 Slog.w(TAG, "fingerprint HIDL not available"); 917 return null; 918 } 919 920 mDaemon.asBinder().linkToDeath(this, 0); 921 922 try { 923 mHalDeviceId = mDaemon.setNotify(mDaemonCallback); 924 } catch (RemoteException e) { 925 Slog.e(TAG, "Failed to open fingerprint HAL", e); 926 mDaemon = null; // try again later! 927 } 928 929 if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId); 930 if (mHalDeviceId != 0) { 931 loadAuthenticatorIds(); 932 updateActiveGroup(ActivityManager.getCurrentUser(), null); 933 doTemplateCleanupForUser(ActivityManager.getCurrentUser()); 934 } else { 935 Slog.w(TAG, "Failed to open Fingerprint HAL!"); 936 MetricsLogger.count(getContext(), "fingerprintd_openhal_error", 1); 937 mDaemon = null; 938 } 939 } 940 return mDaemon; 941 } 942 startPreEnroll(IBinder token)943 private long startPreEnroll(IBinder token) { 944 IBiometricsFingerprint daemon = getFingerprintDaemon(); 945 if (daemon == null) { 946 Slog.w(TAG, "startPreEnroll: no fingerprint HAL!"); 947 return 0; 948 } 949 try { 950 return daemon.preEnroll(); 951 } catch (RemoteException e) { 952 Slog.e(TAG, "startPreEnroll failed", e); 953 } 954 return 0; 955 } 956 startPostEnroll(IBinder token)957 private int startPostEnroll(IBinder token) { 958 IBiometricsFingerprint daemon = getFingerprintDaemon(); 959 if (daemon == null) { 960 Slog.w(TAG, "startPostEnroll: no fingerprint HAL!"); 961 return 0; 962 } 963 try { 964 return daemon.postEnroll(); 965 } catch (RemoteException e) { 966 Slog.e(TAG, "startPostEnroll failed", e); 967 } 968 return 0; 969 } 970 971 // Attempt counter should only be cleared when Keyguard goes away or when 972 // a biometric is successfully authenticated. Lockout should eventually be done below the HAL. 973 // See AuthenticationClient#shouldFrameworkHandleLockout(). resetFailedAttemptsForUser(boolean clearAttemptCounter, int userId)974 private void resetFailedAttemptsForUser(boolean clearAttemptCounter, int userId) { 975 if (DEBUG && getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) { 976 Slog.v(getTag(), "Reset biometric lockout, clearAttemptCounter=" + clearAttemptCounter); 977 } 978 if (clearAttemptCounter) { 979 mFailedAttempts.put(userId, 0); 980 } 981 mTimedLockoutCleared.put(userId, true); 982 // If we're asked to reset failed attempts externally (i.e. from Keyguard), 983 // the alarm might still be pending; remove it. 984 cancelLockoutResetForUser(userId); 985 notifyLockoutResetMonitors(); 986 } 987 988 cancelLockoutResetForUser(int userId)989 private void cancelLockoutResetForUser(int userId) { 990 mAlarmManager.cancel(getLockoutResetIntentForUser(userId)); 991 } 992 scheduleLockoutResetForUser(int userId)993 private void scheduleLockoutResetForUser(int userId) { 994 mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, 995 SystemClock.elapsedRealtime() + FAIL_LOCKOUT_TIMEOUT_MS, 996 getLockoutResetIntentForUser(userId)); 997 } 998 getLockoutResetIntentForUser(int userId)999 private PendingIntent getLockoutResetIntentForUser(int userId) { 1000 return PendingIntent.getBroadcast(getContext(), userId, 1001 new Intent(getLockoutResetIntent()).putExtra(KEY_LOCKOUT_RESET_USER, userId), 1002 PendingIntent.FLAG_UPDATE_CURRENT); 1003 } 1004 dumpInternal(PrintWriter pw)1005 private void dumpInternal(PrintWriter pw) { 1006 JSONObject dump = new JSONObject(); 1007 try { 1008 dump.put("service", "Fingerprint Manager"); 1009 1010 JSONArray sets = new JSONArray(); 1011 for (UserInfo user : UserManager.get(getContext()).getUsers()) { 1012 final int userId = user.getUserHandle().getIdentifier(); 1013 final int N = getBiometricUtils().getBiometricsForUser(getContext(), userId).size(); 1014 PerformanceStats stats = mPerformanceMap.get(userId); 1015 PerformanceStats cryptoStats = mCryptoPerformanceMap.get(userId); 1016 JSONObject set = new JSONObject(); 1017 set.put("id", userId); 1018 set.put("count", N); 1019 set.put("accept", (stats != null) ? stats.accept : 0); 1020 set.put("reject", (stats != null) ? stats.reject : 0); 1021 set.put("acquire", (stats != null) ? stats.acquire : 0); 1022 set.put("lockout", (stats != null) ? stats.lockout : 0); 1023 set.put("permanentLockout", (stats != null) ? stats.permanentLockout : 0); 1024 // cryptoStats measures statistics about secure fingerprint transactions 1025 // (e.g. to unlock password storage, make secure purchases, etc.) 1026 set.put("acceptCrypto", (cryptoStats != null) ? cryptoStats.accept : 0); 1027 set.put("rejectCrypto", (cryptoStats != null) ? cryptoStats.reject : 0); 1028 set.put("acquireCrypto", (cryptoStats != null) ? cryptoStats.acquire : 0); 1029 set.put("lockoutCrypto", (cryptoStats != null) ? cryptoStats.lockout : 0); 1030 set.put("permanentLockoutCrypto", 1031 (cryptoStats != null) ? cryptoStats.permanentLockout : 0); 1032 sets.put(set); 1033 } 1034 1035 dump.put("prints", sets); 1036 } catch (JSONException e) { 1037 Slog.e(TAG, "dump formatting failure", e); 1038 } 1039 pw.println(dump); 1040 pw.println("HAL deaths since last reboot: " + mHALDeathCount); 1041 } 1042 dumpProto(FileDescriptor fd)1043 private void dumpProto(FileDescriptor fd) { 1044 final ProtoOutputStream proto = new ProtoOutputStream(fd); 1045 for (UserInfo user : UserManager.get(getContext()).getUsers()) { 1046 final int userId = user.getUserHandle().getIdentifier(); 1047 1048 final long userToken = proto.start(FingerprintServiceDumpProto.USERS); 1049 1050 proto.write(FingerprintUserStatsProto.USER_ID, userId); 1051 proto.write(FingerprintUserStatsProto.NUM_FINGERPRINTS, 1052 getBiometricUtils().getBiometricsForUser(getContext(), userId).size()); 1053 1054 // Normal fingerprint authentications (e.g. lockscreen) 1055 final PerformanceStats normal = mPerformanceMap.get(userId); 1056 if (normal != null) { 1057 final long countsToken = proto.start(FingerprintUserStatsProto.NORMAL); 1058 proto.write(PerformanceStatsProto.ACCEPT, normal.accept); 1059 proto.write(PerformanceStatsProto.REJECT, normal.reject); 1060 proto.write(PerformanceStatsProto.ACQUIRE, normal.acquire); 1061 proto.write(PerformanceStatsProto.LOCKOUT, normal.lockout); 1062 proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, normal.permanentLockout); 1063 proto.end(countsToken); 1064 } 1065 1066 // Statistics about secure fingerprint transactions (e.g. to unlock password 1067 // storage, make secure purchases, etc.) 1068 final PerformanceStats crypto = mCryptoPerformanceMap.get(userId); 1069 if (crypto != null) { 1070 final long countsToken = proto.start(FingerprintUserStatsProto.CRYPTO); 1071 proto.write(PerformanceStatsProto.ACCEPT, crypto.accept); 1072 proto.write(PerformanceStatsProto.REJECT, crypto.reject); 1073 proto.write(PerformanceStatsProto.ACQUIRE, crypto.acquire); 1074 proto.write(PerformanceStatsProto.LOCKOUT, crypto.lockout); 1075 proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, crypto.permanentLockout); 1076 proto.end(countsToken); 1077 } 1078 1079 proto.end(userToken); 1080 } 1081 proto.flush(); 1082 mPerformanceMap.clear(); 1083 mCryptoPerformanceMap.clear(); 1084 } 1085 } 1086