• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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