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