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