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