1 /* 2 * Copyright (C) 2020 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.sensors.fingerprint.hidl; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.app.ActivityManager; 22 import android.app.ActivityTaskManager; 23 import android.app.SynchronousUserSwitchObserver; 24 import android.app.TaskStackListener; 25 import android.app.UserSwitchObserver; 26 import android.content.Context; 27 import android.content.pm.UserInfo; 28 import android.hardware.biometrics.BiometricConstants; 29 import android.hardware.biometrics.BiometricsProtoEnums; 30 import android.hardware.biometrics.IInvalidationCallback; 31 import android.hardware.biometrics.ITestSession; 32 import android.hardware.biometrics.ITestSessionCallback; 33 import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint; 34 import android.hardware.biometrics.fingerprint.V2_2.IBiometricsFingerprintClientCallback; 35 import android.hardware.fingerprint.Fingerprint; 36 import android.hardware.fingerprint.FingerprintManager; 37 import android.hardware.fingerprint.FingerprintSensorProperties; 38 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; 39 import android.hardware.fingerprint.IFingerprintServiceReceiver; 40 import android.hardware.fingerprint.ISidefpsController; 41 import android.hardware.fingerprint.IUdfpsOverlayController; 42 import android.os.Handler; 43 import android.os.IBinder; 44 import android.os.IHwBinder; 45 import android.os.RemoteException; 46 import android.os.UserHandle; 47 import android.os.UserManager; 48 import android.util.Slog; 49 import android.util.proto.ProtoOutputStream; 50 51 import com.android.internal.annotations.VisibleForTesting; 52 import com.android.internal.util.FrameworkStatsLog; 53 import com.android.server.biometrics.SensorServiceStateProto; 54 import com.android.server.biometrics.SensorStateProto; 55 import com.android.server.biometrics.UserStateProto; 56 import com.android.server.biometrics.Utils; 57 import com.android.server.biometrics.fingerprint.FingerprintServiceDumpProto; 58 import com.android.server.biometrics.fingerprint.FingerprintUserStatsProto; 59 import com.android.server.biometrics.fingerprint.PerformanceStatsProto; 60 import com.android.server.biometrics.sensors.AcquisitionClient; 61 import com.android.server.biometrics.sensors.AuthenticationClient; 62 import com.android.server.biometrics.sensors.AuthenticationConsumer; 63 import com.android.server.biometrics.sensors.BaseClientMonitor; 64 import com.android.server.biometrics.sensors.BiometricScheduler; 65 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; 66 import com.android.server.biometrics.sensors.EnumerateConsumer; 67 import com.android.server.biometrics.sensors.ErrorConsumer; 68 import com.android.server.biometrics.sensors.HalClientMonitor; 69 import com.android.server.biometrics.sensors.LockoutResetDispatcher; 70 import com.android.server.biometrics.sensors.LockoutTracker; 71 import com.android.server.biometrics.sensors.PerformanceTracker; 72 import com.android.server.biometrics.sensors.RemovalConsumer; 73 import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback; 74 import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; 75 import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; 76 import com.android.server.biometrics.sensors.fingerprint.ServiceProvider; 77 import com.android.server.biometrics.sensors.fingerprint.Udfps; 78 79 import org.json.JSONArray; 80 import org.json.JSONException; 81 import org.json.JSONObject; 82 83 import java.io.FileDescriptor; 84 import java.io.PrintWriter; 85 import java.util.ArrayList; 86 import java.util.Collections; 87 import java.util.HashMap; 88 import java.util.List; 89 import java.util.Map; 90 import java.util.concurrent.atomic.AtomicLong; 91 92 /** 93 * Supports a single instance of the {@link android.hardware.biometrics.fingerprint.V2_1} or 94 * its extended minor versions. 95 */ 96 public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider { 97 98 private static final String TAG = "Fingerprint21"; 99 private static final int ENROLL_TIMEOUT_SEC = 60; 100 101 private boolean mTestHalEnabled; 102 103 final Context mContext; 104 @NonNull private final FingerprintStateCallback mFingerprintStateCallback; 105 private final ActivityTaskManager mActivityTaskManager; 106 @NonNull private final FingerprintSensorPropertiesInternal mSensorProperties; 107 private final BiometricScheduler mScheduler; 108 private final Handler mHandler; 109 private final LockoutResetDispatcher mLockoutResetDispatcher; 110 private final LockoutFrameworkImpl mLockoutTracker; 111 private final BiometricTaskStackListener mTaskStackListener; 112 private final HalClientMonitor.LazyDaemon<IBiometricsFingerprint> mLazyDaemon; 113 private final Map<Integer, Long> mAuthenticatorIds; 114 115 @Nullable private IBiometricsFingerprint mDaemon; 116 @NonNull private final HalResultController mHalResultController; 117 @Nullable private IUdfpsOverlayController mUdfpsOverlayController; 118 @Nullable private ISidefpsController mSidefpsController; 119 // for requests that do not use biometric prompt 120 @NonNull private final AtomicLong mRequestCounter = new AtomicLong(0); 121 private int mCurrentUserId = UserHandle.USER_NULL; 122 private final boolean mIsUdfps; 123 private final int mSensorId; 124 private final boolean mIsPowerbuttonFps; 125 126 private final class BiometricTaskStackListener extends TaskStackListener { 127 @Override onTaskStackChanged()128 public void onTaskStackChanged() { 129 mHandler.post(() -> { 130 final BaseClientMonitor client = mScheduler.getCurrentClient(); 131 if (!(client instanceof AuthenticationClient)) { 132 Slog.e(TAG, "Task stack changed for client: " + client); 133 return; 134 } 135 if (Utils.isKeyguard(mContext, client.getOwnerString()) 136 || Utils.isSystem(mContext, client.getOwnerString())) { 137 return; // Keyguard is always allowed 138 } 139 140 final List<ActivityManager.RunningTaskInfo> runningTasks = 141 mActivityTaskManager.getTasks(1); 142 if (!runningTasks.isEmpty()) { 143 final String topPackage = runningTasks.get(0).topActivity.getPackageName(); 144 if (!topPackage.contentEquals(client.getOwnerString()) 145 && !client.isAlreadyDone()) { 146 Slog.e(TAG, "Stopping background authentication, top: " 147 + topPackage + " currentClient: " + client); 148 mScheduler.cancelAuthenticationOrDetection( 149 client.getToken(), client.getRequestId()); 150 } 151 } 152 }); 153 } 154 } 155 156 private final LockoutFrameworkImpl.LockoutResetCallback mLockoutResetCallback = 157 new LockoutFrameworkImpl.LockoutResetCallback() { 158 @Override 159 public void onLockoutReset(int userId) { 160 mLockoutResetDispatcher.notifyLockoutResetCallbacks(mSensorProperties.sensorId); 161 } 162 }; 163 164 private final UserSwitchObserver mUserSwitchObserver = new SynchronousUserSwitchObserver() { 165 @Override 166 public void onUserSwitching(int newUserId) { 167 scheduleInternalCleanup(newUserId, null /* callback */); 168 } 169 }; 170 171 public static class HalResultController extends IBiometricsFingerprintClientCallback.Stub { 172 173 /** 174 * Interface to sends results to the HalResultController's owner. 175 */ 176 public interface Callback { 177 /** 178 * Invoked when the HAL sends ERROR_HW_UNAVAILABLE. 179 */ onHardwareUnavailable()180 void onHardwareUnavailable(); 181 } 182 183 private final int mSensorId; 184 @NonNull private final Context mContext; 185 @NonNull final Handler mHandler; 186 @NonNull final BiometricScheduler mScheduler; 187 @Nullable private Callback mCallback; 188 HalResultController(int sensorId, @NonNull Context context, @NonNull Handler handler, @NonNull BiometricScheduler scheduler)189 HalResultController(int sensorId, @NonNull Context context, @NonNull Handler handler, 190 @NonNull BiometricScheduler scheduler) { 191 mSensorId = sensorId; 192 mContext = context; 193 mHandler = handler; 194 mScheduler = scheduler; 195 } 196 setCallback(@ullable Callback callback)197 public void setCallback(@Nullable Callback callback) { 198 mCallback = callback; 199 } 200 201 @Override onEnrollResult(long deviceId, int fingerId, int groupId, int remaining)202 public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) { 203 mHandler.post(() -> { 204 final BaseClientMonitor client = mScheduler.getCurrentClient(); 205 if (!(client instanceof FingerprintEnrollClient)) { 206 Slog.e(TAG, "onEnrollResult for non-enroll client: " 207 + Utils.getClientName(client)); 208 return; 209 } 210 211 final int currentUserId = client.getTargetUserId(); 212 final CharSequence name = FingerprintUtils.getLegacyInstance(mSensorId) 213 .getUniqueName(mContext, currentUserId); 214 final Fingerprint fingerprint = new Fingerprint(name, groupId, fingerId, deviceId); 215 216 final FingerprintEnrollClient enrollClient = (FingerprintEnrollClient) client; 217 enrollClient.onEnrollResult(fingerprint, remaining); 218 }); 219 } 220 221 @Override onAcquired(long deviceId, int acquiredInfo, int vendorCode)222 public void onAcquired(long deviceId, int acquiredInfo, int vendorCode) { 223 onAcquired_2_2(deviceId, acquiredInfo, vendorCode); 224 } 225 226 @Override onAcquired_2_2(long deviceId, int acquiredInfo, int vendorCode)227 public void onAcquired_2_2(long deviceId, int acquiredInfo, int vendorCode) { 228 mHandler.post(() -> { 229 final BaseClientMonitor client = mScheduler.getCurrentClient(); 230 if (!(client instanceof AcquisitionClient)) { 231 Slog.e(TAG, "onAcquired for non-acquisition client: " 232 + Utils.getClientName(client)); 233 return; 234 } 235 236 final AcquisitionClient<?> acquisitionClient = (AcquisitionClient<?>) client; 237 acquisitionClient.onAcquired(acquiredInfo, vendorCode); 238 }); 239 } 240 241 @Override onAuthenticated(long deviceId, int fingerId, int groupId, ArrayList<Byte> token)242 public void onAuthenticated(long deviceId, int fingerId, int groupId, 243 ArrayList<Byte> token) { 244 mHandler.post(() -> { 245 final BaseClientMonitor client = mScheduler.getCurrentClient(); 246 if (!(client instanceof AuthenticationConsumer)) { 247 Slog.e(TAG, "onAuthenticated for non-authentication consumer: " 248 + Utils.getClientName(client)); 249 return; 250 } 251 252 final AuthenticationConsumer authenticationConsumer = 253 (AuthenticationConsumer) client; 254 final boolean authenticated = fingerId != 0; 255 final Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId); 256 authenticationConsumer.onAuthenticated(fp, authenticated, token); 257 }); 258 } 259 260 @Override onError(long deviceId, int error, int vendorCode)261 public void onError(long deviceId, int error, int vendorCode) { 262 mHandler.post(() -> { 263 final BaseClientMonitor client = mScheduler.getCurrentClient(); 264 Slog.d(TAG, "handleError" 265 + ", client: " + Utils.getClientName(client) 266 + ", error: " + error 267 + ", vendorCode: " + vendorCode); 268 if (!(client instanceof ErrorConsumer)) { 269 Slog.e(TAG, "onError for non-error consumer: " + Utils.getClientName(client)); 270 return; 271 } 272 273 final ErrorConsumer errorConsumer = (ErrorConsumer) client; 274 errorConsumer.onError(error, vendorCode); 275 276 if (error == BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE) { 277 Slog.e(TAG, "Got ERROR_HW_UNAVAILABLE"); 278 if (mCallback != null) { 279 mCallback.onHardwareUnavailable(); 280 } 281 } 282 }); 283 } 284 285 @Override onRemoved(long deviceId, int fingerId, int groupId, int remaining)286 public void onRemoved(long deviceId, int fingerId, int groupId, int remaining) { 287 mHandler.post(() -> { 288 Slog.d(TAG, "Removed, fingerId: " + fingerId + ", remaining: " + remaining); 289 final BaseClientMonitor client = mScheduler.getCurrentClient(); 290 if (!(client instanceof RemovalConsumer)) { 291 Slog.e(TAG, "onRemoved for non-removal consumer: " 292 + Utils.getClientName(client)); 293 return; 294 } 295 296 final Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId); 297 final RemovalConsumer removalConsumer = (RemovalConsumer) client; 298 removalConsumer.onRemoved(fp, remaining); 299 }); 300 } 301 302 @Override onEnumerate(long deviceId, int fingerId, int groupId, int remaining)303 public void onEnumerate(long deviceId, int fingerId, int groupId, int remaining) { 304 mHandler.post(() -> { 305 final BaseClientMonitor client = mScheduler.getCurrentClient(); 306 if (!(client instanceof EnumerateConsumer)) { 307 Slog.e(TAG, "onEnumerate for non-enumerate consumer: " 308 + Utils.getClientName(client)); 309 return; 310 } 311 312 final Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId); 313 final EnumerateConsumer enumerateConsumer = (EnumerateConsumer) client; 314 enumerateConsumer.onEnumerationResult(fp, remaining); 315 }); 316 } 317 } 318 Fingerprint21(@onNull Context context, @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull BiometricScheduler scheduler, @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull HalResultController controller)319 Fingerprint21(@NonNull Context context, 320 @NonNull FingerprintStateCallback fingerprintStateCallback, 321 @NonNull FingerprintSensorPropertiesInternal sensorProps, 322 @NonNull BiometricScheduler scheduler, 323 @NonNull Handler handler, 324 @NonNull LockoutResetDispatcher lockoutResetDispatcher, 325 @NonNull HalResultController controller) { 326 mContext = context; 327 mFingerprintStateCallback = fingerprintStateCallback; 328 329 mSensorProperties = sensorProps; 330 mSensorId = sensorProps.sensorId; 331 mIsUdfps = sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL 332 || sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC; 333 mIsPowerbuttonFps = sensorProps.sensorType == FingerprintSensorProperties.TYPE_POWER_BUTTON; 334 335 mScheduler = scheduler; 336 mHandler = handler; 337 mActivityTaskManager = ActivityTaskManager.getInstance(); 338 mTaskStackListener = new BiometricTaskStackListener(); 339 mAuthenticatorIds = Collections.synchronizedMap(new HashMap<>()); 340 mLazyDaemon = Fingerprint21.this::getDaemon; 341 mLockoutResetDispatcher = lockoutResetDispatcher; 342 mLockoutTracker = new LockoutFrameworkImpl(context, mLockoutResetCallback); 343 mHalResultController = controller; 344 mHalResultController.setCallback(() -> { 345 mDaemon = null; 346 mCurrentUserId = UserHandle.USER_NULL; 347 }); 348 349 try { 350 ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, TAG); 351 } catch (RemoteException e) { 352 Slog.e(TAG, "Unable to register user switch observer"); 353 } 354 } 355 newInstance(@onNull Context context, @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher)356 public static Fingerprint21 newInstance(@NonNull Context context, 357 @NonNull FingerprintStateCallback fingerprintStateCallback, 358 @NonNull FingerprintSensorPropertiesInternal sensorProps, 359 @NonNull Handler handler, 360 @NonNull LockoutResetDispatcher lockoutResetDispatcher, 361 @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { 362 final BiometricScheduler scheduler = 363 new BiometricScheduler(TAG, 364 BiometricScheduler.sensorTypeFromFingerprintProperties(sensorProps), 365 gestureAvailabilityDispatcher); 366 final HalResultController controller = new HalResultController(sensorProps.sensorId, 367 context, handler, scheduler); 368 return new Fingerprint21(context, fingerprintStateCallback, sensorProps, scheduler, handler, 369 lockoutResetDispatcher, controller); 370 } 371 372 @Override serviceDied(long cookie)373 public void serviceDied(long cookie) { 374 Slog.e(TAG, "HAL died"); 375 mHandler.post(() -> { 376 PerformanceTracker.getInstanceForSensorId(mSensorProperties.sensorId) 377 .incrementHALDeathCount(); 378 mDaemon = null; 379 mCurrentUserId = UserHandle.USER_NULL; 380 381 final BaseClientMonitor client = mScheduler.getCurrentClient(); 382 if (client instanceof ErrorConsumer) { 383 Slog.e(TAG, "Sending ERROR_HW_UNAVAILABLE for client: " + client); 384 final ErrorConsumer errorConsumer = (ErrorConsumer) client; 385 errorConsumer.onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 386 0 /* vendorCode */); 387 388 FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, 389 BiometricsProtoEnums.MODALITY_FINGERPRINT, 390 BiometricsProtoEnums.ISSUE_HAL_DEATH, 391 -1 /* sensorId */); 392 } 393 394 mScheduler.recordCrashState(); 395 mScheduler.reset(); 396 }); 397 } 398 399 @VisibleForTesting getDaemon()400 synchronized IBiometricsFingerprint getDaemon() { 401 if (mTestHalEnabled) { 402 final TestHal testHal = new TestHal(mContext, mSensorId); 403 testHal.setNotify(mHalResultController); 404 return testHal; 405 } 406 407 if (mDaemon != null) { 408 return mDaemon; 409 } 410 411 Slog.d(TAG, "Daemon was null, reconnecting, current operation: " 412 + mScheduler.getCurrentClient()); 413 try { 414 mDaemon = IBiometricsFingerprint.getService(); 415 } catch (java.util.NoSuchElementException e) { 416 // Service doesn't exist or cannot be opened. 417 Slog.w(TAG, "NoSuchElementException", e); 418 } catch (RemoteException e) { 419 Slog.e(TAG, "Failed to get fingerprint HAL", e); 420 } 421 422 if (mDaemon == null) { 423 Slog.w(TAG, "Fingerprint HAL not available"); 424 return null; 425 } 426 427 mDaemon.asBinder().linkToDeath(this, 0 /* flags */); 428 429 // HAL ID for these HIDL versions are only used to determine if callbacks have been 430 // successfully set. 431 long halId = 0; 432 try { 433 halId = mDaemon.setNotify(mHalResultController); 434 } catch (RemoteException e) { 435 Slog.e(TAG, "Failed to set callback for fingerprint HAL", e); 436 mDaemon = null; 437 } 438 439 Slog.d(TAG, "Fingerprint HAL ready, HAL ID: " + halId); 440 if (halId != 0) { 441 scheduleLoadAuthenticatorIds(); 442 scheduleInternalCleanup(ActivityManager.getCurrentUser(), null /* callback */); 443 } else { 444 Slog.e(TAG, "Unable to set callback"); 445 mDaemon = null; 446 } 447 448 return mDaemon; 449 } 450 getUdfpsOverlayController()451 @Nullable IUdfpsOverlayController getUdfpsOverlayController() { 452 return mUdfpsOverlayController; 453 } 454 scheduleLoadAuthenticatorIds()455 private void scheduleLoadAuthenticatorIds() { 456 // Note that this can be performed on the scheduler (as opposed to being done immediately 457 // when the HAL is (re)loaded, since 458 // 1) If this is truly the first time it's being performed (e.g. system has just started), 459 // this will be run very early and way before any applications need to generate keys. 460 // 2) If this is being performed to refresh the authenticatorIds (e.g. HAL crashed and has 461 // just been reloaded), the framework already has a cache of the authenticatorIds. This 462 // is safe because authenticatorIds only change when A) new template has been enrolled, 463 // or B) all templates are removed. 464 mHandler.post(() -> { 465 for (UserInfo user : UserManager.get(mContext).getAliveUsers()) { 466 final int targetUserId = user.id; 467 if (!mAuthenticatorIds.containsKey(targetUserId)) { 468 scheduleUpdateActiveUserWithoutHandler(targetUserId, true /* force */); 469 } 470 } 471 }); 472 } 473 scheduleUpdateActiveUserWithoutHandler(int targetUserId)474 private void scheduleUpdateActiveUserWithoutHandler(int targetUserId) { 475 scheduleUpdateActiveUserWithoutHandler(targetUserId, false /* force */); 476 } 477 478 /** 479 * Schedules the {@link FingerprintUpdateActiveUserClient} without posting the work onto the 480 * handler. Many/most APIs are user-specific. However, the HAL requires explicit "setActiveUser" 481 * invocation prior to authenticate/enroll/etc. Thus, internally we usually want to schedule 482 * this operation on the same lambda/runnable as those operations so that the ordering is 483 * correct. 484 * 485 * @param targetUserId Switch to this user, and update their authenticatorId 486 * @param force Always retrieve the authenticatorId, even if we are already the targetUserId 487 */ scheduleUpdateActiveUserWithoutHandler(int targetUserId, boolean force)488 private void scheduleUpdateActiveUserWithoutHandler(int targetUserId, boolean force) { 489 final boolean hasEnrolled = 490 !getEnrolledFingerprints(mSensorProperties.sensorId, targetUserId).isEmpty(); 491 final FingerprintUpdateActiveUserClient client = 492 new FingerprintUpdateActiveUserClient(mContext, mLazyDaemon, targetUserId, 493 mContext.getOpPackageName(), mSensorProperties.sensorId, 494 this::getCurrentUser, hasEnrolled, mAuthenticatorIds, force); 495 mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() { 496 @Override 497 public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, 498 boolean success) { 499 if (success) { 500 mCurrentUserId = targetUserId; 501 } else { 502 Slog.w(TAG, "Failed to change user, still: " + mCurrentUserId); 503 } 504 } 505 }); 506 } 507 getCurrentUser()508 private int getCurrentUser() { 509 return mCurrentUserId; 510 } 511 512 @Override containsSensor(int sensorId)513 public boolean containsSensor(int sensorId) { 514 return mSensorProperties.sensorId == sensorId; 515 } 516 517 @Override 518 @NonNull getSensorProperties()519 public List<FingerprintSensorPropertiesInternal> getSensorProperties() { 520 final List<FingerprintSensorPropertiesInternal> properties = new ArrayList<>(); 521 properties.add(mSensorProperties); 522 return properties; 523 } 524 525 @Nullable 526 @Override getSensorProperties(int sensorId)527 public FingerprintSensorPropertiesInternal getSensorProperties(int sensorId) { 528 return mSensorProperties; 529 } 530 531 @Override scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken)532 public void scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken) { 533 // Fingerprint2.1 keeps track of lockout in the framework. Let's just do it on the handler 534 // thread. 535 mHandler.post(() -> { 536 final FingerprintResetLockoutClient client = new FingerprintResetLockoutClient(mContext, 537 userId, mContext.getOpPackageName(), sensorId, mLockoutTracker); 538 mScheduler.scheduleClientMonitor(client); 539 }); 540 } 541 542 @Override scheduleGenerateChallenge(int sensorId, int userId, @NonNull IBinder token, @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName)543 public void scheduleGenerateChallenge(int sensorId, int userId, @NonNull IBinder token, 544 @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName) { 545 mHandler.post(() -> { 546 final FingerprintGenerateChallengeClient client = 547 new FingerprintGenerateChallengeClient(mContext, mLazyDaemon, token, 548 new ClientMonitorCallbackConverter(receiver), userId, opPackageName, 549 mSensorProperties.sensorId); 550 mScheduler.scheduleClientMonitor(client); 551 }); 552 } 553 554 @Override scheduleRevokeChallenge(int sensorId, int userId, @NonNull IBinder token, @NonNull String opPackageName, long challenge)555 public void scheduleRevokeChallenge(int sensorId, int userId, @NonNull IBinder token, 556 @NonNull String opPackageName, long challenge) { 557 mHandler.post(() -> { 558 final FingerprintRevokeChallengeClient client = new FingerprintRevokeChallengeClient( 559 mContext, mLazyDaemon, token, userId, opPackageName, 560 mSensorProperties.sensorId); 561 mScheduler.scheduleClientMonitor(client); 562 }); 563 } 564 565 @Override scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason)566 public long scheduleEnroll(int sensorId, @NonNull IBinder token, 567 @NonNull byte[] hardwareAuthToken, int userId, 568 @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName, 569 @FingerprintManager.EnrollReason int enrollReason) { 570 final long id = mRequestCounter.incrementAndGet(); 571 mHandler.post(() -> { 572 scheduleUpdateActiveUserWithoutHandler(userId); 573 574 final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext, 575 mLazyDaemon, token, id, new ClientMonitorCallbackConverter(receiver), 576 userId, hardwareAuthToken, opPackageName, 577 FingerprintUtils.getLegacyInstance(mSensorId), ENROLL_TIMEOUT_SEC, 578 mSensorProperties.sensorId, mUdfpsOverlayController, mSidefpsController, 579 enrollReason); 580 mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() { 581 @Override 582 public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) { 583 mFingerprintStateCallback.onClientStarted(clientMonitor); 584 } 585 586 @Override 587 public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, 588 boolean success) { 589 mFingerprintStateCallback.onClientFinished(clientMonitor, success); 590 if (success) { 591 // Update authenticatorIds 592 scheduleUpdateActiveUserWithoutHandler(clientMonitor.getTargetUserId(), 593 true /* force */); 594 } 595 } 596 }); 597 }); 598 return id; 599 } 600 601 @Override cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId)602 public void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId) { 603 mHandler.post(() -> mScheduler.cancelEnrollment(token, requestId)); 604 } 605 606 @Override scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId, @NonNull ClientMonitorCallbackConverter listener, @NonNull String opPackageName, int statsClient)607 public long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId, 608 @NonNull ClientMonitorCallbackConverter listener, @NonNull String opPackageName, 609 int statsClient) { 610 final long id = mRequestCounter.incrementAndGet(); 611 mHandler.post(() -> { 612 scheduleUpdateActiveUserWithoutHandler(userId); 613 614 final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorProperties.sensorId); 615 final FingerprintDetectClient client = new FingerprintDetectClient(mContext, 616 mLazyDaemon, token, id, listener, userId, opPackageName, 617 mSensorProperties.sensorId, mUdfpsOverlayController, isStrongBiometric, 618 statsClient); 619 mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); 620 }); 621 622 return id; 623 } 624 625 @Override scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener, @NonNull String opPackageName, long requestId, boolean restricted, int statsClient, boolean allowBackgroundAuthentication)626 public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, 627 int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener, 628 @NonNull String opPackageName, long requestId, boolean restricted, int statsClient, 629 boolean allowBackgroundAuthentication) { 630 mHandler.post(() -> { 631 scheduleUpdateActiveUserWithoutHandler(userId); 632 633 final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorProperties.sensorId); 634 final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient( 635 mContext, mLazyDaemon, token, requestId, listener, userId, operationId, 636 restricted, opPackageName, cookie, false /* requireConfirmation */, 637 mSensorProperties.sensorId, isStrongBiometric, statsClient, 638 mTaskStackListener, mLockoutTracker, 639 mUdfpsOverlayController, mSidefpsController, 640 allowBackgroundAuthentication, mSensorProperties); 641 mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); 642 }); 643 } 644 645 @Override scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener, @NonNull String opPackageName, boolean restricted, int statsClient, boolean allowBackgroundAuthentication)646 public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, 647 int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener, 648 @NonNull String opPackageName, boolean restricted, int statsClient, 649 boolean allowBackgroundAuthentication) { 650 final long id = mRequestCounter.incrementAndGet(); 651 652 scheduleAuthenticate(sensorId, token, operationId, userId, cookie, listener, 653 opPackageName, id, restricted, statsClient, allowBackgroundAuthentication); 654 655 return id; 656 } 657 658 @Override startPreparedClient(int sensorId, int cookie)659 public void startPreparedClient(int sensorId, int cookie) { 660 mHandler.post(() -> mScheduler.startPreparedClient(cookie)); 661 } 662 663 @Override cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId)664 public void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId) { 665 Slog.d(TAG, "cancelAuthentication, sensorId: " + sensorId); 666 mHandler.post(() -> mScheduler.cancelAuthenticationOrDetection(token, requestId)); 667 } 668 669 @Override scheduleRemove(int sensorId, @NonNull IBinder token, @NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId, @NonNull String opPackageName)670 public void scheduleRemove(int sensorId, @NonNull IBinder token, 671 @NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId, 672 @NonNull String opPackageName) { 673 mHandler.post(() -> { 674 scheduleUpdateActiveUserWithoutHandler(userId); 675 676 final FingerprintRemovalClient client = new FingerprintRemovalClient(mContext, 677 mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), fingerId, 678 userId, opPackageName, FingerprintUtils.getLegacyInstance(mSensorId), 679 mSensorProperties.sensorId, mAuthenticatorIds); 680 mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); 681 }); 682 } 683 684 @Override scheduleRemoveAll(int sensorId, @NonNull IBinder token, @NonNull IFingerprintServiceReceiver receiver, int userId, @NonNull String opPackageName)685 public void scheduleRemoveAll(int sensorId, @NonNull IBinder token, 686 @NonNull IFingerprintServiceReceiver receiver, int userId, 687 @NonNull String opPackageName) { 688 mHandler.post(() -> { 689 scheduleUpdateActiveUserWithoutHandler(userId); 690 691 // For IBiometricsFingerprint@2.1, remove(0) means remove all enrollments 692 final FingerprintRemovalClient client = new FingerprintRemovalClient(mContext, 693 mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), 694 0 /* fingerprintId */, userId, opPackageName, 695 FingerprintUtils.getLegacyInstance(mSensorId), 696 mSensorProperties.sensorId, mAuthenticatorIds); 697 mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); 698 }); 699 } 700 scheduleInternalCleanup(int userId, @Nullable BaseClientMonitor.Callback callback)701 private void scheduleInternalCleanup(int userId, 702 @Nullable BaseClientMonitor.Callback callback) { 703 mHandler.post(() -> { 704 scheduleUpdateActiveUserWithoutHandler(userId); 705 706 final List<Fingerprint> enrolledList = getEnrolledFingerprints( 707 mSensorProperties.sensorId, userId); 708 final FingerprintInternalCleanupClient client = new FingerprintInternalCleanupClient( 709 mContext, mLazyDaemon, userId, mContext.getOpPackageName(), 710 mSensorProperties.sensorId, enrolledList, 711 FingerprintUtils.getLegacyInstance(mSensorId), mAuthenticatorIds); 712 mScheduler.scheduleClientMonitor(client, callback); 713 }); 714 } 715 716 @Override scheduleInternalCleanup(int sensorId, int userId, @Nullable BaseClientMonitor.Callback callback)717 public void scheduleInternalCleanup(int sensorId, int userId, 718 @Nullable BaseClientMonitor.Callback callback) { 719 scheduleInternalCleanup(userId, new BaseClientMonitor.CompositeCallback(callback, 720 mFingerprintStateCallback)); 721 } 722 723 @Override isHardwareDetected(int sensorId)724 public boolean isHardwareDetected(int sensorId) { 725 return getDaemon() != null; 726 } 727 728 @Override rename(int sensorId, int fingerId, int userId, @NonNull String name)729 public void rename(int sensorId, int fingerId, int userId, @NonNull String name) { 730 mHandler.post(() -> { 731 FingerprintUtils.getLegacyInstance(mSensorId) 732 .renameBiometricForUser(mContext, userId, fingerId, name); 733 }); 734 } 735 736 @Override 737 @NonNull getEnrolledFingerprints(int sensorId, int userId)738 public List<Fingerprint> getEnrolledFingerprints(int sensorId, int userId) { 739 return FingerprintUtils.getLegacyInstance(mSensorId).getBiometricsForUser(mContext, userId); 740 } 741 742 @Override getLockoutModeForUser(int sensorId, int userId)743 @LockoutTracker.LockoutMode public int getLockoutModeForUser(int sensorId, int userId) { 744 return mLockoutTracker.getLockoutModeForUser(userId); 745 } 746 747 @Override getAuthenticatorId(int sensorId, int userId)748 public long getAuthenticatorId(int sensorId, int userId) { 749 return mAuthenticatorIds.getOrDefault(userId, 0L); 750 } 751 752 @Override onPointerDown(int sensorId, int x, int y, float minor, float major)753 public void onPointerDown(int sensorId, int x, int y, float minor, float major) { 754 final BaseClientMonitor client = mScheduler.getCurrentClient(); 755 if (!(client instanceof Udfps)) { 756 Slog.w(TAG, "onFingerDown received during client: " + client); 757 return; 758 } 759 final Udfps udfps = (Udfps) client; 760 udfps.onPointerDown(x, y, minor, major); 761 } 762 763 @Override onPointerUp(int sensorId)764 public void onPointerUp(int sensorId) { 765 final BaseClientMonitor client = mScheduler.getCurrentClient(); 766 if (!(client instanceof Udfps)) { 767 Slog.w(TAG, "onFingerDown received during client: " + client); 768 return; 769 } 770 final Udfps udfps = (Udfps) client; 771 udfps.onPointerUp(); 772 } 773 774 @Override onUiReady(int sensorId)775 public void onUiReady(int sensorId) { 776 final BaseClientMonitor client = mScheduler.getCurrentClient(); 777 if (!(client instanceof Udfps)) { 778 Slog.w(TAG, "onUiReady received during client: " + client); 779 return; 780 } 781 final Udfps udfps = (Udfps) client; 782 udfps.onUiReady(); 783 } 784 785 @Override setUdfpsOverlayController(@onNull IUdfpsOverlayController controller)786 public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) { 787 mUdfpsOverlayController = controller; 788 } 789 790 @Override setSidefpsController(@onNull ISidefpsController controller)791 public void setSidefpsController(@NonNull ISidefpsController controller) { 792 mSidefpsController = controller; 793 } 794 795 @Override dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto, boolean clearSchedulerBuffer)796 public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto, 797 boolean clearSchedulerBuffer) { 798 final long sensorToken = proto.start(SensorServiceStateProto.SENSOR_STATES); 799 800 proto.write(SensorStateProto.SENSOR_ID, mSensorProperties.sensorId); 801 proto.write(SensorStateProto.MODALITY, SensorStateProto.FINGERPRINT); 802 if (mSensorProperties.isAnyUdfpsType()) { 803 proto.write(SensorStateProto.MODALITY_FLAGS, SensorStateProto.FINGERPRINT_UDFPS); 804 } 805 proto.write(SensorStateProto.CURRENT_STRENGTH, 806 Utils.getCurrentStrength(mSensorProperties.sensorId)); 807 proto.write(SensorStateProto.SCHEDULER, mScheduler.dumpProtoState(clearSchedulerBuffer)); 808 809 for (UserInfo user : UserManager.get(mContext).getUsers()) { 810 final int userId = user.getUserHandle().getIdentifier(); 811 812 final long userToken = proto.start(SensorStateProto.USER_STATES); 813 proto.write(UserStateProto.USER_ID, userId); 814 proto.write(UserStateProto.NUM_ENROLLED, FingerprintUtils.getLegacyInstance(mSensorId) 815 .getBiometricsForUser(mContext, userId).size()); 816 proto.end(userToken); 817 } 818 819 proto.write(SensorStateProto.RESET_LOCKOUT_REQUIRES_HARDWARE_AUTH_TOKEN, 820 mSensorProperties.resetLockoutRequiresHardwareAuthToken); 821 proto.write(SensorStateProto.RESET_LOCKOUT_REQUIRES_CHALLENGE, 822 mSensorProperties.resetLockoutRequiresChallenge); 823 824 proto.end(sensorToken); 825 } 826 827 @Override dumpProtoMetrics(int sensorId, FileDescriptor fd)828 public void dumpProtoMetrics(int sensorId, FileDescriptor fd) { 829 PerformanceTracker tracker = 830 PerformanceTracker.getInstanceForSensorId(mSensorProperties.sensorId); 831 832 final ProtoOutputStream proto = new ProtoOutputStream(fd); 833 for (UserInfo user : UserManager.get(mContext).getUsers()) { 834 final int userId = user.getUserHandle().getIdentifier(); 835 836 final long userToken = proto.start(FingerprintServiceDumpProto.USERS); 837 838 proto.write(FingerprintUserStatsProto.USER_ID, userId); 839 proto.write(FingerprintUserStatsProto.NUM_FINGERPRINTS, 840 FingerprintUtils.getLegacyInstance(mSensorId) 841 .getBiometricsForUser(mContext, userId).size()); 842 843 // Normal fingerprint authentications (e.g. lockscreen) 844 long countsToken = proto.start(FingerprintUserStatsProto.NORMAL); 845 proto.write(PerformanceStatsProto.ACCEPT, tracker.getAcceptForUser(userId)); 846 proto.write(PerformanceStatsProto.REJECT, tracker.getRejectForUser(userId)); 847 proto.write(PerformanceStatsProto.ACQUIRE, tracker.getAcquireForUser(userId)); 848 proto.write(PerformanceStatsProto.LOCKOUT, tracker.getTimedLockoutForUser(userId)); 849 proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, 850 tracker.getPermanentLockoutForUser(userId)); 851 proto.end(countsToken); 852 853 // Statistics about secure fingerprint transactions (e.g. to unlock password 854 // storage, make secure purchases, etc.) 855 countsToken = proto.start(FingerprintUserStatsProto.CRYPTO); 856 proto.write(PerformanceStatsProto.ACCEPT, tracker.getAcceptCryptoForUser(userId)); 857 proto.write(PerformanceStatsProto.REJECT, tracker.getRejectCryptoForUser(userId)); 858 proto.write(PerformanceStatsProto.ACQUIRE, tracker.getAcquireCryptoForUser(userId)); 859 proto.write(PerformanceStatsProto.LOCKOUT, 0); // meaningless for crypto 860 proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, 0); // meaningless for crypto 861 proto.end(countsToken); 862 863 proto.end(userToken); 864 } 865 proto.flush(); 866 tracker.clear(); 867 } 868 869 @Override scheduleInvalidateAuthenticatorId(int sensorId, int userId, @NonNull IInvalidationCallback callback)870 public void scheduleInvalidateAuthenticatorId(int sensorId, int userId, 871 @NonNull IInvalidationCallback callback) { 872 // TODO (b/179101888): Remove this temporary workaround. 873 try { 874 callback.onCompleted(); 875 } catch (RemoteException e) { 876 Slog.e(TAG, "Failed to complete InvalidateAuthenticatorId"); 877 } 878 } 879 880 @Override dumpInternal(int sensorId, @NonNull PrintWriter pw)881 public void dumpInternal(int sensorId, @NonNull PrintWriter pw) { 882 PerformanceTracker performanceTracker = 883 PerformanceTracker.getInstanceForSensorId(mSensorProperties.sensorId); 884 885 JSONObject dump = new JSONObject(); 886 try { 887 dump.put("service", TAG); 888 dump.put("isUdfps", mIsUdfps); 889 dump.put("isPowerbuttonFps", mIsPowerbuttonFps); 890 891 JSONArray sets = new JSONArray(); 892 for (UserInfo user : UserManager.get(mContext).getUsers()) { 893 final int userId = user.getUserHandle().getIdentifier(); 894 final int N = FingerprintUtils.getLegacyInstance(mSensorId) 895 .getBiometricsForUser(mContext, userId).size(); 896 JSONObject set = new JSONObject(); 897 set.put("id", userId); 898 set.put("count", N); 899 set.put("accept", performanceTracker.getAcceptForUser(userId)); 900 set.put("reject", performanceTracker.getRejectForUser(userId)); 901 set.put("acquire", performanceTracker.getAcquireForUser(userId)); 902 set.put("lockout", performanceTracker.getTimedLockoutForUser(userId)); 903 set.put("permanentLockout", performanceTracker.getPermanentLockoutForUser(userId)); 904 // cryptoStats measures statistics about secure fingerprint transactions 905 // (e.g. to unlock password storage, make secure purchases, etc.) 906 set.put("acceptCrypto", performanceTracker.getAcceptCryptoForUser(userId)); 907 set.put("rejectCrypto", performanceTracker.getRejectCryptoForUser(userId)); 908 set.put("acquireCrypto", performanceTracker.getAcquireCryptoForUser(userId)); 909 sets.put(set); 910 } 911 912 dump.put("prints", sets); 913 } catch (JSONException e) { 914 Slog.e(TAG, "dump formatting failure", e); 915 } 916 pw.println(dump); 917 pw.println("HAL deaths since last reboot: " + performanceTracker.getHALDeathCount()); 918 mScheduler.dump(pw); 919 } 920 setTestHalEnabled(boolean enabled)921 void setTestHalEnabled(boolean enabled) { 922 mTestHalEnabled = enabled; 923 } 924 925 @NonNull 926 @Override createTestSession(int sensorId, @NonNull ITestSessionCallback callback, @NonNull String opPackageName)927 public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback, 928 @NonNull String opPackageName) { 929 return new BiometricTestSessionImpl(mContext, mSensorProperties.sensorId, callback, 930 mFingerprintStateCallback, this, mHalResultController); 931 } 932 } 933