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