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