1 /*
2  * Copyright (C) 2014 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 android.hardware.fingerprint;
18 
19 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
20 import static android.Manifest.permission.MANAGE_FINGERPRINT;
21 import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
22 import static android.Manifest.permission.TEST_BIOMETRIC;
23 import static android.Manifest.permission.USE_BIOMETRIC;
24 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
25 import static android.Manifest.permission.USE_FINGERPRINT;
26 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
27 import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
28 
29 import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE;
30 import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_HAS_ENROLLED_FINGERPRINTS;
31 import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_IS_HARDWARE_DETECTED;
32 
33 import android.annotation.IntDef;
34 import android.annotation.NonNull;
35 import android.annotation.Nullable;
36 import android.annotation.RequiresFeature;
37 import android.annotation.RequiresPermission;
38 import android.annotation.SystemService;
39 import android.annotation.TestApi;
40 import android.app.ActivityManager;
41 import android.compat.annotation.UnsupportedAppUsage;
42 import android.content.Context;
43 import android.content.pm.PackageManager;
44 import android.hardware.biometrics.BiometricAuthenticator;
45 import android.hardware.biometrics.BiometricConstants;
46 import android.hardware.biometrics.BiometricFingerprintConstants;
47 import android.hardware.biometrics.BiometricPrompt;
48 import android.hardware.biometrics.BiometricStateListener;
49 import android.hardware.biometrics.BiometricTestSession;
50 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
51 import android.hardware.biometrics.SensorProperties;
52 import android.hardware.biometrics.fingerprint.PointerContext;
53 import android.os.Binder;
54 import android.os.Build;
55 import android.os.CancellationSignal;
56 import android.os.CancellationSignal.OnCancelListener;
57 import android.os.Handler;
58 import android.os.IBinder;
59 import android.os.IRemoteCallback;
60 import android.os.Looper;
61 import android.os.PowerManager;
62 import android.os.RemoteException;
63 import android.os.UserHandle;
64 import android.security.identity.IdentityCredential;
65 import android.security.identity.PresentationSession;
66 import android.util.Slog;
67 import android.view.Surface;
68 
69 import com.android.internal.util.FrameworkStatsLog;
70 
71 import java.lang.annotation.Retention;
72 import java.lang.annotation.RetentionPolicy;
73 import java.security.Signature;
74 import java.util.ArrayList;
75 import java.util.List;
76 import java.util.concurrent.Executor;
77 
78 import javax.crypto.Cipher;
79 import javax.crypto.Mac;
80 
81 /**
82  * A class that coordinates access to the fingerprint hardware.
83  * @deprecated See {@link BiometricPrompt} which shows a system-provided dialog upon starting
84  * authentication. In a world where devices may have different types of biometric authentication,
85  * it's much more realistic to have a system-provided authentication dialog since the method may
86  * vary by vendor/device.
87  */
88 @SuppressWarnings("deprecation")
89 @Deprecated
90 @SystemService(Context.FINGERPRINT_SERVICE)
91 @RequiresFeature(PackageManager.FEATURE_FINGERPRINT)
92 public class FingerprintManager implements BiometricAuthenticator, BiometricFingerprintConstants {
93     private static final String TAG = "FingerprintManager";
94     private static final boolean DEBUG = true;
95     private static final int MSG_ENROLL_RESULT = 100;
96     private static final int MSG_ACQUIRED = 101;
97     private static final int MSG_AUTHENTICATION_SUCCEEDED = 102;
98     private static final int MSG_AUTHENTICATION_FAILED = 103;
99     private static final int MSG_ERROR = 104;
100     private static final int MSG_REMOVED = 105;
101     private static final int MSG_CHALLENGE_GENERATED = 106;
102     private static final int MSG_FINGERPRINT_DETECTED = 107;
103     private static final int MSG_UDFPS_POINTER_DOWN = 108;
104     private static final int MSG_UDFPS_POINTER_UP = 109;
105     private static final int MSG_POWER_BUTTON_PRESSED = 110;
106     private static final int MSG_UDFPS_OVERLAY_SHOWN = 111;
107 
108     /**
109      * @hide
110      */
111     public static final int ENROLL_FIND_SENSOR = 1;
112     /**
113      * @hide
114      */
115     public static final int ENROLL_ENROLL = 2;
116 
117     /**
118      * @hide
119      */
120     @IntDef({ENROLL_FIND_SENSOR, ENROLL_ENROLL})
121     @Retention(RetentionPolicy.SOURCE)
122     public @interface EnrollReason {}
123 
124     /**
125      * Udfps ui event of overlay is shown on the screen.
126      * @hide
127      */
128     public static final int UDFPS_UI_OVERLAY_SHOWN = 1;
129     /**
130      * Udfps ui event of the udfps UI being ready (e.g. HBM illumination is enabled).
131      * @hide
132      */
133     public static final int UDFPS_UI_READY = 2;
134 
135     /**
136      * @hide
137      */
138     @IntDef({UDFPS_UI_OVERLAY_SHOWN, UDFPS_UI_READY})
139     @Retention(RetentionPolicy.SOURCE)
140     public @interface UdfpsUiEvent{}
141 
142     /**
143      * Request authentication with any single sensor.
144      * @hide
145      */
146     public static final int SENSOR_ID_ANY = -1;
147 
148     private static class RemoveTracker {
149         static final int REMOVE_SINGLE = 1;
150         static final int REMOVE_ALL = 2;
151         @IntDef({REMOVE_SINGLE, REMOVE_ALL})
152         @interface RemoveRequest {}
153 
154         final @RemoveRequest int mRemoveRequest;
155         @Nullable final Fingerprint mSingleFingerprint;
156 
RemoveTracker(@emoveRequest int request, @Nullable Fingerprint fingerprint)157         RemoveTracker(@RemoveRequest int request, @Nullable Fingerprint fingerprint) {
158             mRemoveRequest = request;
159             mSingleFingerprint = fingerprint;
160         }
161     }
162 
163     private IFingerprintService mService;
164     private Context mContext;
165     private IBinder mToken = new Binder();
166     private AuthenticationCallback mAuthenticationCallback;
167     private FingerprintDetectionCallback mFingerprintDetectionCallback;
168     private EnrollmentCallback mEnrollmentCallback;
169     private RemovalCallback mRemovalCallback;
170     private GenerateChallengeCallback mGenerateChallengeCallback;
171     private CryptoObject mCryptoObject;
172     @Nullable private RemoveTracker mRemoveTracker;
173     private Handler mHandler;
174     @Nullable private float[] mEnrollStageThresholds;
175     private List<FingerprintSensorPropertiesInternal> mProps = new ArrayList<>();
176 
177     /**
178      * Retrieves a list of properties for all fingerprint sensors on the device.
179      * @hide
180      */
181     @TestApi
182     @NonNull
183     @RequiresPermission(TEST_BIOMETRIC)
getSensorProperties()184     public List<SensorProperties> getSensorProperties() {
185         final List<SensorProperties> properties = new ArrayList<>();
186         final List<FingerprintSensorPropertiesInternal> internalProperties
187                 = getSensorPropertiesInternal();
188         for (FingerprintSensorPropertiesInternal internalProp : internalProperties) {
189             properties.add(FingerprintSensorProperties.from(internalProp));
190         }
191         return properties;
192     }
193 
194     /**
195      * Retrieves a test session for FingerprintManager.
196      * @hide
197      */
198     @TestApi
199     @NonNull
200     @RequiresPermission(TEST_BIOMETRIC)
createTestSession(int sensorId)201     public BiometricTestSession createTestSession(int sensorId) {
202         try {
203             return new BiometricTestSession(mContext, sensorId,
204                     (context, sensorId1, callback) -> mService
205                             .createTestSession(sensorId1, callback, context.getOpPackageName()));
206         } catch (RemoteException e) {
207             throw e.rethrowFromSystemServer();
208         }
209     }
210 
211     private class OnEnrollCancelListener implements OnCancelListener {
212         private final long mAuthRequestId;
213 
OnEnrollCancelListener(long id)214         private OnEnrollCancelListener(long id) {
215             mAuthRequestId = id;
216         }
217 
218         @Override
onCancel()219         public void onCancel() {
220             Slog.d(TAG, "Cancel fingerprint enrollment requested for: " + mAuthRequestId);
221             cancelEnrollment(mAuthRequestId);
222         }
223     }
224 
225     private class OnAuthenticationCancelListener implements OnCancelListener {
226         private final long mAuthRequestId;
227 
OnAuthenticationCancelListener(long id)228         OnAuthenticationCancelListener(long id) {
229             mAuthRequestId = id;
230         }
231 
232         @Override
onCancel()233         public void onCancel() {
234             Slog.d(TAG, "Cancel fingerprint authentication requested for: " + mAuthRequestId);
235             cancelAuthentication(mAuthRequestId);
236         }
237     }
238 
239     private class OnFingerprintDetectionCancelListener implements OnCancelListener {
240         private final long mAuthRequestId;
241 
OnFingerprintDetectionCancelListener(long id)242         OnFingerprintDetectionCancelListener(long id) {
243             mAuthRequestId = id;
244         }
245 
246         @Override
onCancel()247         public void onCancel() {
248             Slog.d(TAG, "Cancel fingerprint detect requested for: " + mAuthRequestId);
249             cancelFingerprintDetect(mAuthRequestId);
250         }
251     }
252 
253     /**
254      * A wrapper class for the crypto objects supported by FingerprintManager. Currently the
255      * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
256      * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.CryptoObject}
257      */
258     @Deprecated
259     public static final class CryptoObject extends android.hardware.biometrics.CryptoObject {
CryptoObject(@onNull Signature signature)260         public CryptoObject(@NonNull Signature signature) {
261             super(signature);
262         }
263 
CryptoObject(@onNull Cipher cipher)264         public CryptoObject(@NonNull Cipher cipher) {
265             super(cipher);
266         }
267 
CryptoObject(@onNull Mac mac)268         public CryptoObject(@NonNull Mac mac) {
269             super(mac);
270         }
271 
272         /**
273          * Get {@link Signature} object.
274          * @return {@link Signature} object or null if this doesn't contain one.
275          */
getSignature()276         public Signature getSignature() {
277             return super.getSignature();
278         }
279 
280         /**
281          * Get {@link Cipher} object.
282          * @return {@link Cipher} object or null if this doesn't contain one.
283          */
getCipher()284         public Cipher getCipher() {
285             return super.getCipher();
286         }
287 
288         /**
289          * Get {@link Mac} object.
290          * @return {@link Mac} object or null if this doesn't contain one.
291          */
getMac()292         public Mac getMac() {
293             return super.getMac();
294         }
295 
296         /**
297          * Get {@link IdentityCredential} object.
298          * @return {@link IdentityCredential} object or null if this doesn't contain one.
299          * @hide
300          * @deprecated Use {@link PresentationSession} instead of {@link IdentityCredential}.
301          */
302         @Deprecated
getIdentityCredential()303         public IdentityCredential getIdentityCredential() {
304             return super.getIdentityCredential();
305         }
306 
307         /**
308          * Get {@link PresentationSession} object.
309          * @return {@link PresentationSession} object or null if this doesn't contain one.
310          * @hide
311          */
getPresentationSession()312         public PresentationSession getPresentationSession() {
313             return super.getPresentationSession();
314         }
315     }
316 
317     /**
318      * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject,
319      *     CancellationSignal, int, AuthenticationCallback, Handler)}.
320      * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationResult}
321      */
322     @Deprecated
323     public static class AuthenticationResult {
324         private Fingerprint mFingerprint;
325         private CryptoObject mCryptoObject;
326         private int mUserId;
327         private boolean mIsStrongBiometric;
328 
329         /**
330          * Authentication result
331          *
332          * @param crypto the crypto object
333          * @param fingerprint the recognized fingerprint data, if allowed.
334          * @hide
335          */
AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint, int userId, boolean isStrongBiometric)336         public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint, int userId,
337                 boolean isStrongBiometric) {
338             mCryptoObject = crypto;
339             mFingerprint = fingerprint;
340             mUserId = userId;
341             mIsStrongBiometric = isStrongBiometric;
342         }
343 
344         /**
345          * Obtain the crypto object associated with this transaction
346          * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject,
347          *     CancellationSignal, int, AuthenticationCallback, Handler)}.
348          */
getCryptoObject()349         public CryptoObject getCryptoObject() { return mCryptoObject; }
350 
351         /**
352          * Obtain the Fingerprint associated with this operation. Applications are strongly
353          * discouraged from associating specific fingers with specific applications or operations.
354          *
355          * @hide
356          */
357         @UnsupportedAppUsage
getFingerprint()358         public Fingerprint getFingerprint() { return mFingerprint; }
359 
360         /**
361          * Obtain the userId for which this fingerprint was authenticated.
362          * @hide
363          */
getUserId()364         public int getUserId() { return mUserId; }
365 
366         /**
367          * Check whether the strength of the fingerprint modality associated with this operation is
368          * strong (i.e. not weak or convenience).
369          * @hide
370          */
isStrongBiometric()371         public boolean isStrongBiometric() {
372             return mIsStrongBiometric;
373         }
374     }
375 
376     /**
377      * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject,
378      * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link
379      * FingerprintManager#authenticate(CryptoObject, CancellationSignal,
380      * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to
381      * fingerprint events.
382      * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationCallback}
383      */
384     @Deprecated
385     public static abstract class AuthenticationCallback
386             extends BiometricAuthenticator.AuthenticationCallback {
387         /**
388          * Called when an unrecoverable error has been encountered and the operation is complete.
389          * No further callbacks will be made on this object.
390          * @param errorCode An integer identifying the error message
391          * @param errString A human-readable error string that can be shown in UI
392          */
393         @Override
onAuthenticationError(int errorCode, CharSequence errString)394         public void onAuthenticationError(int errorCode, CharSequence errString) { }
395 
396         /**
397          * Called when a recoverable error has been encountered during authentication. The help
398          * string is provided to give the user guidance for what went wrong, such as
399          * "Sensor dirty, please clean it."
400          * @param helpCode An integer identifying the error message
401          * @param helpString A human-readable string that can be shown in UI
402          */
403         @Override
onAuthenticationHelp(int helpCode, CharSequence helpString)404         public void onAuthenticationHelp(int helpCode, CharSequence helpString) { }
405 
406         /**
407          * Called when a fingerprint is recognized.
408          * @param result An object containing authentication-related data
409          */
onAuthenticationSucceeded(AuthenticationResult result)410         public void onAuthenticationSucceeded(AuthenticationResult result) { }
411 
412         /**
413          * Called when a fingerprint is valid but not recognized.
414          */
415         @Override
onAuthenticationFailed()416         public void onAuthenticationFailed() { }
417 
418         /**
419          * Called when a fingerprint image has been acquired, but wasn't processed yet.
420          *
421          * @param acquireInfo one of FINGERPRINT_ACQUIRED_* constants
422          * @hide
423          */
424         @Override
onAuthenticationAcquired(int acquireInfo)425         public void onAuthenticationAcquired(int acquireInfo) {}
426 
427         /**
428          * Invoked for under-display fingerprint sensors when a touch has been detected on the
429          * sensor area.
430          * @hide
431          */
onUdfpsPointerDown(int sensorId)432         public void onUdfpsPointerDown(int sensorId) {}
433 
434         /**
435          * Invoked for under-display fingerprint sensors when a touch has been removed from the
436          * sensor area.
437          * @hide
438          */
onUdfpsPointerUp(int sensorId)439         public void onUdfpsPointerUp(int sensorId) {}
440     }
441 
442     /**
443      * Callback structure provided for {@link #detectFingerprint(CancellationSignal,
444      * FingerprintDetectionCallback, int, Surface)}.
445      * @hide
446      */
447     public interface FingerprintDetectionCallback {
448         /**
449          * Invoked when a fingerprint has been detected.
450          */
onFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric)451         void onFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric);
452     }
453 
454     /**
455      * Callback structure provided to {@link FingerprintManager#enroll(byte[], CancellationSignal,
456      * int, EnrollmentCallback)} must provide an implementation of this for listening to
457      * fingerprint events.
458      *
459      * @hide
460      */
461     public static abstract class EnrollmentCallback {
462         /**
463          * Called when an unrecoverable error has been encountered and the operation is complete.
464          * No further callbacks will be made on this object.
465          * @param errMsgId An integer identifying the error message
466          * @param errString A human-readable error string that can be shown in UI
467          */
onEnrollmentError(int errMsgId, CharSequence errString)468         public void onEnrollmentError(int errMsgId, CharSequence errString) { }
469 
470         /**
471          * Called when a recoverable error has been encountered during enrollment. The help
472          * string is provided to give the user guidance for what went wrong, such as
473          * "Sensor dirty, please clean it" or what they need to do next, such as
474          * "Touch sensor again."
475          * @param helpMsgId An integer identifying the error message
476          * @param helpString A human-readable string that can be shown in UI
477          */
onEnrollmentHelp(int helpMsgId, CharSequence helpString)478         public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { }
479 
480         /**
481          * Called as each enrollment step progresses. Enrollment is considered complete when
482          * remaining reaches 0. This function will not be called if enrollment fails. See
483          * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)}
484          * @param remaining The number of remaining steps
485          */
onEnrollmentProgress(int remaining)486         public void onEnrollmentProgress(int remaining) { }
487 
488         /**
489          * Called when a fingerprint image has been acquired.
490          * @param isAcquiredGood whether the fingerprint image was good.
491          */
onAcquired(boolean isAcquiredGood)492         public void onAcquired(boolean isAcquiredGood){ }
493 
494         /**
495          * Called when a pointer down event has occurred.
496          */
onUdfpsPointerDown(int sensorId)497         public void onUdfpsPointerDown(int sensorId){ }
498 
499         /**
500          * Called when a pointer up event has occurred.
501          */
onUdfpsPointerUp(int sensorId)502         public void onUdfpsPointerUp(int sensorId){ }
503 
504         /**
505          * Called when udfps overlay is shown.
506          */
onUdfpsOverlayShown()507         public void onUdfpsOverlayShown() { }
508     }
509 
510     /**
511      * Callback structure provided to {@link #remove}. Users of {@link FingerprintManager} may
512      * optionally provide an implementation of this to
513      * {@link #remove(Fingerprint, int, RemovalCallback)} for listening to fingerprint template
514      * removal events.
515      *
516      * @hide
517      */
518     public static abstract class RemovalCallback {
519         /**
520          * Called when the given fingerprint can't be removed.
521          * @param fp The fingerprint that the call attempted to remove
522          * @param errMsgId An associated error message id
523          * @param errString An error message indicating why the fingerprint id can't be removed
524          */
onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString)525         public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { }
526 
527         /**
528          * Called when a given fingerprint is successfully removed.
529          * @param fp The fingerprint template that was removed.
530          * @param remaining The number of fingerprints yet to be removed in this operation. If
531          *         {@link #remove} is called on one fingerprint, this should be 0. If
532          *         {@link #remove} is called on a group, this should be the number of remaining
533          *         fingerprints in the group, and 0 after the last fingerprint is removed.
534          */
onRemovalSucceeded(@ullable Fingerprint fp, int remaining)535         public void onRemovalSucceeded(@Nullable Fingerprint fp, int remaining) { }
536     }
537 
538     /**
539      * @hide
540      */
541     public static abstract class LockoutResetCallback {
542 
543         /**
544          * Called when lockout period expired and clients are allowed to listen for fingerprint
545          * again.
546          */
onLockoutReset(int sensorId)547         public void onLockoutReset(int sensorId) { }
548     }
549 
550     /**
551      * Callbacks for generate challenge operations.
552      *
553      * @hide
554      */
555     public interface GenerateChallengeCallback {
556         /** Called when a challenged has been generated. */
onChallengeGenerated(int sensorId, int userId, long challenge)557         void onChallengeGenerated(int sensorId, int userId, long challenge);
558     }
559 
560     /**
561      * Use the provided handler thread for events.
562      * @param handler
563      */
useHandler(Handler handler)564     private void useHandler(Handler handler) {
565         if (handler != null) {
566             mHandler = new MyHandler(handler.getLooper());
567         } else if (mHandler.getLooper() != mContext.getMainLooper()) {
568             mHandler = new MyHandler(mContext.getMainLooper());
569         }
570     }
571 
572     /**
573      * Request authentication of a crypto object. This call warms up the fingerprint hardware
574      * and starts scanning for a fingerprint. It terminates when
575      * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
576      * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
577      * which point the object is no longer valid. The operation can be canceled by using the
578      * provided cancel object.
579      *
580      * @param crypto object associated with the call or null if none required.
581      * @param cancel an object that can be used to cancel authentication
582      * @param flags optional flags; should be 0
583      * @param callback an object to receive authentication events
584      * @param handler an optional handler to handle callback events
585      *
586      * @throws IllegalArgumentException if the crypto operation is not supported or is not backed
587      *         by <a href="{@docRoot}training/articles/keystore.html">Android Keystore
588      *         facility</a>.
589      * @throws IllegalStateException if the crypto primitive is not initialized.
590      * @deprecated See {@link BiometricPrompt#authenticate(CancellationSignal, Executor,
591      * BiometricPrompt.AuthenticationCallback)} and {@link BiometricPrompt#authenticate(
592      * BiometricPrompt.CryptoObject, CancellationSignal, Executor,
593      * BiometricPrompt.AuthenticationCallback)}
594      */
595     @Deprecated
596     @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
authenticate(@ullable CryptoObject crypto, @Nullable CancellationSignal cancel, int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler)597     public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
598             int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
599         authenticate(crypto, cancel, callback, handler, SENSOR_ID_ANY, mContext.getUserId(), flags);
600     }
601 
602     /**
603      * Per-user version of authenticate.
604      * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FingerprintAuthenticateOptions)}.
605      * @hide
606      */
607     @Deprecated
608     @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
authenticate(@ullable CryptoObject crypto, @Nullable CancellationSignal cancel, @NonNull AuthenticationCallback callback, Handler handler, int userId)609     public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
610             @NonNull AuthenticationCallback callback, Handler handler, int userId) {
611         authenticate(crypto, cancel, callback, handler, SENSOR_ID_ANY, userId, 0 /* flags */);
612     }
613 
614     /**
615      * Per-user and per-sensor version of authenticate.
616      * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FingerprintAuthenticateOptions)}.
617      * @hide
618      */
619     @Deprecated
620     @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
authenticate(@ullable CryptoObject crypto, @Nullable CancellationSignal cancel, @NonNull AuthenticationCallback callback, Handler handler, int sensorId, int userId, int flags)621     public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
622             @NonNull AuthenticationCallback callback, Handler handler, int sensorId, int userId,
623             int flags) {
624         authenticate(crypto, cancel, callback, handler, new FingerprintAuthenticateOptions.Builder()
625                 .setSensorId(sensorId)
626                 .setUserId(userId)
627                 .setIgnoreEnrollmentState(flags != 0)
628                 .build());
629     }
630 
631     /**
632      * Version of authenticate with additional options.
633      * @hide
634      */
635     @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
authenticate(@ullable CryptoObject crypto, @Nullable CancellationSignal cancel, @NonNull AuthenticationCallback callback, @NonNull Handler handler, @NonNull FingerprintAuthenticateOptions options)636     public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
637             @NonNull AuthenticationCallback callback, @NonNull Handler handler,
638             @NonNull FingerprintAuthenticateOptions options) {
639         FrameworkStatsLog.write(FrameworkStatsLog.AUTH_DEPRECATED_API_USED,
640                 AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE,
641                 mContext.getApplicationInfo().uid,
642                 mContext.getApplicationInfo().targetSdkVersion);
643 
644         if (callback == null) {
645             throw new IllegalArgumentException("Must supply an authentication callback");
646         }
647 
648         if (cancel != null && cancel.isCanceled()) {
649             Slog.w(TAG, "authentication already canceled");
650             return;
651         }
652 
653         options.setOpPackageName(mContext.getOpPackageName());
654         options.setAttributionTag(mContext.getAttributionTag());
655 
656         if (mService != null) {
657             try {
658                 useHandler(handler);
659                 mAuthenticationCallback = callback;
660                 mCryptoObject = crypto;
661                 final long operationId = crypto != null ? crypto.getOpId() : 0;
662                 final long authId = mService.authenticate(mToken, operationId, mServiceReceiver, options);
663                 if (cancel != null) {
664                     cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
665                 }
666             } catch (RemoteException e) {
667                 Slog.w(TAG, "Remote exception while authenticating: ", e);
668                 // Though this may not be a hardware issue, it will cause apps to give up or try
669                 // again later.
670                 callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
671                         getErrorString(mContext, FINGERPRINT_ERROR_HW_UNAVAILABLE,
672                                 0 /* vendorCode */));
673             }
674         }
675     }
676 
677     /**
678      * Uses the fingerprint hardware to detect for the presence of a finger, without giving details
679      * about accept/reject/lockout.
680      * @hide
681      */
682     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
detectFingerprint(@onNull CancellationSignal cancel, @NonNull FingerprintDetectionCallback callback, @NonNull FingerprintAuthenticateOptions options)683     public void detectFingerprint(@NonNull CancellationSignal cancel,
684             @NonNull FingerprintDetectionCallback callback, @NonNull FingerprintAuthenticateOptions options) {
685         if (mService == null) {
686             return;
687         }
688 
689         if (cancel.isCanceled()) {
690             Slog.w(TAG, "Detection already cancelled");
691             return;
692         }
693 
694         options.setOpPackageName(mContext.getOpPackageName());
695         options.setAttributionTag(mContext.getAttributionTag());
696 
697         mFingerprintDetectionCallback = callback;
698 
699         try {
700             final long authId = mService.detectFingerprint(mToken, mServiceReceiver, options);
701             cancel.setOnCancelListener(new OnFingerprintDetectionCancelListener(authId));
702         } catch (RemoteException e) {
703             Slog.w(TAG, "Remote exception when requesting finger detect", e);
704         }
705     }
706 
707     /**
708      * Request fingerprint enrollment. This call warms up the fingerprint hardware
709      * and starts scanning for fingerprints. Progress will be indicated by callbacks to the
710      * {@link EnrollmentCallback} object. It terminates when
711      * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or
712      * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at
713      * which point the object is no longer valid. The operation can be canceled by using the
714      * provided cancel object.
715      * @param token a unique token provided by a recent creation or verification of device
716      * credentials (e.g. pin, pattern or password).
717      * @param cancel an object that can be used to cancel enrollment
718      * @param userId the user to whom this fingerprint will belong to
719      * @param callback an object to receive enrollment events
720      * @param shouldLogMetrics a flag that indicates if enrollment failure/success metrics
721      * should be logged.
722      * @hide
723      */
724     @RequiresPermission(MANAGE_FINGERPRINT)
enroll(byte [] hardwareAuthToken, CancellationSignal cancel, int userId, EnrollmentCallback callback, @EnrollReason int enrollReason)725     public void enroll(byte [] hardwareAuthToken, CancellationSignal cancel, int userId,
726             EnrollmentCallback callback, @EnrollReason int enrollReason) {
727         if (userId == UserHandle.USER_CURRENT) {
728             userId = getCurrentUserId();
729         }
730         if (callback == null) {
731             throw new IllegalArgumentException("Must supply an enrollment callback");
732         }
733 
734         if (cancel != null && cancel.isCanceled()) {
735             Slog.w(TAG, "enrollment already canceled");
736             return;
737         }
738 
739         if (hardwareAuthToken == null) {
740             callback.onEnrollmentError(FINGERPRINT_ERROR_UNABLE_TO_PROCESS,
741                     getErrorString(mContext, FINGERPRINT_ERROR_UNABLE_TO_PROCESS,
742                             0 /* vendorCode */));
743             return;
744         }
745 
746         if (mService != null) {
747             try {
748                 mEnrollmentCallback = callback;
749                 final long enrollId = mService.enroll(mToken, hardwareAuthToken, userId,
750                         mServiceReceiver, mContext.getOpPackageName(), enrollReason);
751                 if (cancel != null) {
752                     cancel.setOnCancelListener(new OnEnrollCancelListener(enrollId));
753                 }
754             } catch (RemoteException e) {
755                 Slog.w(TAG, "Remote exception in enroll: ", e);
756                 // Though this may not be a hardware issue, it will cause apps to give up or try
757                 // again later.
758                 callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
759                         getErrorString(mContext, FINGERPRINT_ERROR_HW_UNAVAILABLE,
760                                 0 /* vendorCode */));
761             }
762         }
763     }
764 
765     /**
766      * Generates a unique random challenge in the TEE. A typical use case is to have it wrapped in a
767      * HardwareAuthenticationToken, minted by Gatekeeper upon PIN/Pattern/Password verification.
768      * The HardwareAuthenticationToken can then be sent to the biometric HAL together with a
769      * request to perform sensitive operation(s) (for example enroll), represented by the challenge.
770      * Doing this ensures that a the sensitive operation cannot be performed unless the user has
771      * entered confirmed PIN/Pattern/Password.
772      *
773      * @see com.android.server.locksettings.LockSettingsService
774      *
775      * @hide
776      */
777     @RequiresPermission(MANAGE_FINGERPRINT)
generateChallenge(int sensorId, int userId, GenerateChallengeCallback callback)778     public void generateChallenge(int sensorId, int userId, GenerateChallengeCallback callback) {
779         if (mService != null) try {
780             mGenerateChallengeCallback = callback;
781             mService.generateChallenge(mToken, sensorId, userId, mServiceReceiver,
782                     mContext.getOpPackageName());
783         } catch (RemoteException e) {
784             throw e.rethrowFromSystemServer();
785         }
786     }
787 
788     /**
789      * Same as {@link #generateChallenge(int, GenerateChallengeCallback)}, but assumes the first
790      * enumerated sensor.
791      * @hide
792      */
793     @RequiresPermission(MANAGE_FINGERPRINT)
generateChallenge(int userId, GenerateChallengeCallback callback)794     public void generateChallenge(int userId, GenerateChallengeCallback callback) {
795         final FingerprintSensorPropertiesInternal sensorProps = getFirstFingerprintSensor();
796         if (sensorProps == null) {
797             Slog.e(TAG, "No sensors");
798             return;
799         }
800         generateChallenge(sensorProps.sensorId, userId, callback);
801     }
802 
803     /**
804      * Revokes the specified challenge.
805      * @hide
806      */
807     @RequiresPermission(MANAGE_FINGERPRINT)
revokeChallenge(int userId, long challenge)808     public void revokeChallenge(int userId, long challenge) {
809         if (mService != null) {
810             try {
811                 final FingerprintSensorPropertiesInternal sensorProps = getFirstFingerprintSensor();
812                 if (sensorProps == null) {
813                     Slog.e(TAG, "No sensors");
814                     return;
815                 }
816                 mService.revokeChallenge(mToken, sensorProps.sensorId, userId,
817                         mContext.getOpPackageName(), challenge);
818             } catch (RemoteException e) {
819                 throw e.rethrowFromSystemServer();
820             }
821         }
822     }
823 
824     /**
825      * Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password)
826      *
827      * @param sensorId Sensor ID that this operation takes effect for
828      * @param userId User ID that this operation takes effect for.
829      * @param hardwareAuthToken An opaque token returned by password confirmation.
830      * @hide
831      */
832     @RequiresPermission(RESET_FINGERPRINT_LOCKOUT)
resetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken)833     public void resetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken) {
834         if (mService != null) {
835             try {
836                 mService.resetLockout(mToken, sensorId, userId, hardwareAuthToken,
837                         mContext.getOpPackageName());
838             } catch (RemoteException e) {
839                 throw e.rethrowFromSystemServer();
840             }
841         }
842     }
843 
844     /**
845      * Remove given fingerprint template from fingerprint hardware and/or protected storage.
846      * @param fp the fingerprint item to remove
847      * @param userId the user who this fingerprint belongs to
848      * @param callback an optional callback to verify that fingerprint templates have been
849      * successfully removed. May be null of no callback is required.
850      *
851      * @hide
852      */
853     @RequiresPermission(MANAGE_FINGERPRINT)
remove(Fingerprint fp, int userId, RemovalCallback callback)854     public void remove(Fingerprint fp, int userId, RemovalCallback callback) {
855         if (mService != null) try {
856             mRemovalCallback = callback;
857             mRemoveTracker = new RemoveTracker(RemoveTracker.REMOVE_SINGLE, fp);
858             mService.remove(mToken, fp.getBiometricId(), userId, mServiceReceiver,
859                     mContext.getOpPackageName());
860         } catch (RemoteException e) {
861             throw e.rethrowFromSystemServer();
862         }
863     }
864 
865     /**
866      * Removes all fingerprint templates for the given user.
867      * @hide
868      */
869     @RequiresPermission(MANAGE_FINGERPRINT)
removeAll(int userId, @NonNull RemovalCallback callback)870     public void removeAll(int userId, @NonNull RemovalCallback callback) {
871         if (mService != null) {
872             try {
873                 mRemovalCallback = callback;
874                 mRemoveTracker = new RemoveTracker(RemoveTracker.REMOVE_ALL, null /* fp */);
875                 mService.removeAll(mToken, userId, mServiceReceiver, mContext.getOpPackageName());
876             } catch (RemoteException e) {
877                 throw e.rethrowFromSystemServer();
878             }
879         }
880     }
881 
882     /**
883      * Renames the given fingerprint template
884      * @param fpId the fingerprint id
885      * @param userId the user who this fingerprint belongs to
886      * @param newName the new name
887      *
888      * @hide
889      */
890     @RequiresPermission(MANAGE_FINGERPRINT)
rename(int fpId, int userId, String newName)891     public void rename(int fpId, int userId, String newName) {
892         // Renames the given fpId
893         if (mService != null) {
894             try {
895                 mService.rename(fpId, userId, newName);
896             } catch (RemoteException e) {
897                 throw e.rethrowFromSystemServer();
898             }
899         } else {
900             Slog.w(TAG, "rename(): Service not connected!");
901         }
902     }
903 
904     /**
905      * Obtain the list of enrolled fingerprints templates.
906      * @return list of current fingerprint items
907      *
908      * @hide
909      */
910     @RequiresPermission(USE_FINGERPRINT)
911     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getEnrolledFingerprints(int userId)912     public List<Fingerprint> getEnrolledFingerprints(int userId) {
913         if (mService != null) try {
914                 return mService.getEnrolledFingerprints(
915                         userId, mContext.getOpPackageName(), mContext.getAttributionTag());
916         } catch (RemoteException e) {
917             throw e.rethrowFromSystemServer();
918         }
919         return null;
920     }
921 
922     /**
923      * Obtain the list of enrolled fingerprints templates.
924      * @return list of current fingerprint items
925      *
926      * @hide
927      */
928     @RequiresPermission(USE_FINGERPRINT)
929     @UnsupportedAppUsage
getEnrolledFingerprints()930     public List<Fingerprint> getEnrolledFingerprints() {
931         return getEnrolledFingerprints(mContext.getUserId());
932     }
933 
934     /**
935      * @hide
936      */
hasEnrolledTemplates()937     public boolean hasEnrolledTemplates() {
938         return hasEnrolledFingerprints();
939     }
940 
941     /**
942      * @hide
943      */
hasEnrolledTemplates(int userId)944     public boolean hasEnrolledTemplates(int userId) {
945         return hasEnrolledFingerprints(userId);
946     }
947 
948     /**
949      * @hide
950      */
951     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
setUdfpsOverlayController(@onNull IUdfpsOverlayController controller)952     public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) {
953         if (mService == null) {
954             Slog.w(TAG, "setUdfpsOverlayController: no fingerprint service");
955             return;
956         }
957 
958         try {
959             mService.setUdfpsOverlayController(controller);
960         } catch (RemoteException e) {
961             throw e.rethrowFromSystemServer();
962         }
963     }
964 
965     /**
966      * @hide
967      */
968     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
setSidefpsController(@onNull ISidefpsController controller)969     public void setSidefpsController(@NonNull ISidefpsController controller) {
970         if (mService == null) {
971             Slog.w(TAG, "setSidefpsController: no fingerprint service");
972             return;
973         }
974 
975         try {
976             mService.setSidefpsController(controller);
977         } catch (RemoteException e) {
978             throw e.rethrowFromSystemServer();
979         }
980     }
981 
982     /**
983      * Forwards BiometricStateListener to FingerprintService
984      * @param listener new BiometricStateListener being added
985      * @hide
986      */
registerBiometricStateListener(@onNull BiometricStateListener listener)987     public void registerBiometricStateListener(@NonNull BiometricStateListener listener) {
988         try {
989             mService.registerBiometricStateListener(listener);
990         } catch (RemoteException e) {
991             throw e.rethrowFromSystemServer();
992         }
993     }
994 
995     /**
996      * @hide
997      */
998     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
onPointerDown(long requestId, int sensorId, int x, int y, float minor, float major)999     public void onPointerDown(long requestId, int sensorId, int x, int y,
1000             float minor, float major) {
1001         if (mService == null) {
1002             Slog.w(TAG, "onPointerDown: no fingerprint service");
1003             return;
1004         }
1005 
1006         final PointerContext pc = new PointerContext();
1007         pc.x = (int) x;
1008         pc.y = (int) y;
1009         pc.minor = minor;
1010         pc.major = major;
1011 
1012         try {
1013             mService.onPointerDown(requestId, sensorId, pc);
1014         } catch (RemoteException e) {
1015             throw e.rethrowFromSystemServer();
1016         }
1017     }
1018 
1019     /**
1020      * @hide
1021      */
1022     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
onPointerUp(long requestId, int sensorId)1023     public void onPointerUp(long requestId, int sensorId) {
1024         if (mService == null) {
1025             Slog.w(TAG, "onPointerUp: no fingerprint service");
1026             return;
1027         }
1028 
1029         final PointerContext pc = new PointerContext();
1030 
1031         try {
1032             mService.onPointerUp(requestId, sensorId, pc);
1033         } catch (RemoteException e) {
1034             throw e.rethrowFromSystemServer();
1035         }
1036     }
1037 
1038     /**
1039      * TODO(b/218388821): The parameter list should be replaced with PointerContext.
1040      * @hide
1041      */
1042     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
onPointerDown( long requestId, int sensorId, int pointerId, float x, float y, float minor, float major, float orientation, long time, long gestureStart, boolean isAod)1043     public void onPointerDown(
1044             long requestId,
1045             int sensorId,
1046             int pointerId,
1047             float x,
1048             float y,
1049             float minor,
1050             float major,
1051             float orientation,
1052             long time,
1053             long gestureStart,
1054             boolean isAod) {
1055         if (mService == null) {
1056             Slog.w(TAG, "onPointerDown: no fingerprint service");
1057             return;
1058         }
1059 
1060         final PointerContext pc = new PointerContext();
1061         pc.pointerId = pointerId;
1062         pc.x = x;
1063         pc.y = y;
1064         pc.minor = minor;
1065         pc.major = major;
1066         pc.orientation = orientation;
1067         pc.time = time;
1068         pc.gestureStart = gestureStart;
1069         pc.isAod = isAod;
1070 
1071         try {
1072             mService.onPointerDown(requestId, sensorId, pc);
1073         } catch (RemoteException e) {
1074             throw e.rethrowFromSystemServer();
1075         }
1076     }
1077 
1078     /**
1079      * TODO(b/218388821): The parameter list should be replaced with PointerContext.
1080      * @hide
1081      */
1082     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
onPointerUp( long requestId, int sensorId, int pointerId, float x, float y, float minor, float major, float orientation, long time, long gestureStart, boolean isAod)1083     public void onPointerUp(
1084             long requestId,
1085             int sensorId,
1086             int pointerId,
1087             float x,
1088             float y,
1089             float minor,
1090             float major,
1091             float orientation,
1092             long time,
1093             long gestureStart,
1094             boolean isAod) {
1095         if (mService == null) {
1096             Slog.w(TAG, "onPointerUp: no fingerprint service");
1097             return;
1098         }
1099 
1100         final PointerContext pc = new PointerContext();
1101         pc.pointerId = pointerId;
1102         pc.x = x;
1103         pc.y = y;
1104         pc.minor = minor;
1105         pc.major = major;
1106         pc.orientation = orientation;
1107         pc.time = time;
1108         pc.gestureStart = gestureStart;
1109         pc.isAod = isAod;
1110 
1111         try {
1112             mService.onPointerUp(requestId, sensorId, pc);
1113         } catch (RemoteException e) {
1114             throw e.rethrowFromSystemServer();
1115         }
1116     }
1117 
1118     /**
1119      * @hide
1120      */
1121     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
onUdfpsUiEvent(@dfpsUiEvent int event, long requestId, int sensorId)1122     public void onUdfpsUiEvent(@UdfpsUiEvent int event, long requestId, int sensorId) {
1123         if (mService == null) {
1124             Slog.w(TAG, "onUdfpsUiEvent: no fingerprint service");
1125             return;
1126         }
1127 
1128         try {
1129             mService.onUdfpsUiEvent(event, requestId, sensorId);
1130         } catch (RemoteException e) {
1131             throw e.rethrowFromSystemServer();
1132         }
1133     }
1134 
1135     /**
1136      * This is triggered by SideFpsEventHandler
1137      * @hide
1138      */
1139     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
onPowerPressed()1140     public void onPowerPressed() {
1141         Slog.i(TAG, "onPowerPressed");
1142         mHandler.obtainMessage(MSG_POWER_BUTTON_PRESSED).sendToTarget();
1143     }
1144 
1145     /**
1146      * Determine if there is at least one fingerprint enrolled.
1147      *
1148      * @return true if at least one fingerprint is enrolled, false otherwise
1149      * @deprecated See {@link BiometricPrompt} and
1150      * {@link FingerprintManager#FINGERPRINT_ERROR_NO_FINGERPRINTS}
1151      */
1152     @Deprecated
1153     @RequiresPermission(USE_FINGERPRINT)
hasEnrolledFingerprints()1154     public boolean hasEnrolledFingerprints() {
1155         FrameworkStatsLog.write(FrameworkStatsLog.AUTH_DEPRECATED_API_USED,
1156                 AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_HAS_ENROLLED_FINGERPRINTS,
1157                 mContext.getApplicationInfo().uid,
1158                 mContext.getApplicationInfo().targetSdkVersion);
1159 
1160         return hasEnrolledFingerprints(UserHandle.myUserId());
1161     }
1162 
1163     /**
1164      * @hide
1165      */
1166     @RequiresPermission(allOf = {
1167             USE_FINGERPRINT,
1168             INTERACT_ACROSS_USERS})
hasEnrolledFingerprints(int userId)1169     public boolean hasEnrolledFingerprints(int userId) {
1170         if (mService != null) try {
1171                 return mService.hasEnrolledFingerprintsDeprecated(
1172                         userId, mContext.getOpPackageName(), mContext.getAttributionTag());
1173         } catch (RemoteException e) {
1174             throw e.rethrowFromSystemServer();
1175         }
1176         return false;
1177     }
1178 
1179     /**
1180      * Determine if fingerprint hardware is present and functional.
1181      *
1182      * @return true if hardware is present and functional, false otherwise.
1183      * @deprecated See {@link BiometricPrompt} and
1184      * {@link FingerprintManager#FINGERPRINT_ERROR_HW_UNAVAILABLE}
1185      */
1186     @Deprecated
1187     @RequiresPermission(USE_FINGERPRINT)
isHardwareDetected()1188     public boolean isHardwareDetected() {
1189         FrameworkStatsLog.write(FrameworkStatsLog.AUTH_DEPRECATED_API_USED,
1190                 AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_IS_HARDWARE_DETECTED,
1191                 mContext.getApplicationInfo().uid,
1192                 mContext.getApplicationInfo().targetSdkVersion);
1193 
1194         if (mService != null) {
1195             try {
1196                 return mService.isHardwareDetectedDeprecated(
1197                         mContext.getOpPackageName(), mContext.getAttributionTag());
1198             } catch (RemoteException e) {
1199                 throw e.rethrowFromSystemServer();
1200             }
1201         } else {
1202             Slog.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
1203         }
1204         return false;
1205     }
1206 
1207     /**
1208      * Get statically configured sensor properties.
1209      * @hide
1210      */
1211     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
1212     @NonNull
getSensorPropertiesInternal()1213     public List<FingerprintSensorPropertiesInternal> getSensorPropertiesInternal() {
1214         try {
1215             if (!mProps.isEmpty() || mService == null) {
1216                 return mProps;
1217             }
1218             return mService.getSensorPropertiesInternal(mContext.getOpPackageName());
1219         } catch (RemoteException e) {
1220             throw e.rethrowFromSystemServer();
1221         }
1222     }
1223 
1224     /**
1225      * Returns whether the device has a power button fingerprint sensor.
1226      * @return boolean indicating whether power button is fingerprint sensor
1227      * @hide
1228      */
isPowerbuttonFps()1229     public boolean isPowerbuttonFps() {
1230         final FingerprintSensorPropertiesInternal sensorProps = getFirstFingerprintSensor();
1231         return sensorProps == null ? false : sensorProps.sensorType == TYPE_POWER_BUTTON;
1232     }
1233 
1234     /**
1235      * Adds a callback that gets called when the service registers all of the fingerprint
1236      * authenticators (HALs).
1237      *
1238      * If the fingerprint authenticators are already registered when the callback is added, the
1239      * callback is invoked immediately.
1240      *
1241      * The callback is automatically removed after it's invoked.
1242      *
1243      * @hide
1244      */
1245     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
addAuthenticatorsRegisteredCallback( IFingerprintAuthenticatorsRegisteredCallback callback)1246     public void addAuthenticatorsRegisteredCallback(
1247             IFingerprintAuthenticatorsRegisteredCallback callback) {
1248         if (mService != null) {
1249             try {
1250                 mService.addAuthenticatorsRegisteredCallback(callback);
1251             } catch (RemoteException e) {
1252                 throw e.rethrowFromSystemServer();
1253             }
1254         } else {
1255             Slog.w(TAG, "addProvidersAvailableCallback(): Service not connected!");
1256         }
1257     }
1258 
1259     /**
1260      * @hide
1261      */
1262     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
1263     @BiometricConstants.LockoutMode
getLockoutModeForUser(int sensorId, int userId)1264     public int getLockoutModeForUser(int sensorId, int userId) {
1265         if (mService != null) {
1266             try {
1267                 return mService.getLockoutModeForUser(sensorId, userId);
1268             } catch (RemoteException e) {
1269                 e.rethrowFromSystemServer();
1270             }
1271         }
1272         return BIOMETRIC_LOCKOUT_NONE;
1273     }
1274 
1275     /**
1276      * Schedules a watchdog.
1277      *
1278      * @hide
1279      */
1280     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
scheduleWatchdog()1281     public void scheduleWatchdog() {
1282         try {
1283             mService.scheduleWatchdog();
1284         } catch (RemoteException e) {
1285             throw e.rethrowFromSystemServer();
1286         }
1287     }
1288 
1289     /**
1290      * @hide
1291      */
addLockoutResetCallback(final LockoutResetCallback callback)1292     public void addLockoutResetCallback(final LockoutResetCallback callback) {
1293         if (mService != null) {
1294             try {
1295                 final PowerManager powerManager = mContext.getSystemService(PowerManager.class);
1296                 mService.addLockoutResetCallback(
1297                         new IBiometricServiceLockoutResetCallback.Stub() {
1298 
1299                     @Override
1300                     public void onLockoutReset(int sensorId, IRemoteCallback serverCallback)
1301                             throws RemoteException {
1302                         try {
1303                             final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
1304                                     PowerManager.PARTIAL_WAKE_LOCK, "lockoutResetCallback");
1305                             wakeLock.acquire();
1306                             mHandler.post(() -> {
1307                                 try {
1308                                     callback.onLockoutReset(sensorId);
1309                                 } finally {
1310                                     wakeLock.release();
1311                                 }
1312                             });
1313                         } finally {
1314                             serverCallback.sendResult(null /* data */);
1315                         }
1316                     }
1317                 }, mContext.getOpPackageName());
1318             } catch (RemoteException e) {
1319                 throw e.rethrowFromSystemServer();
1320             }
1321         } else {
1322             Slog.w(TAG, "addLockoutResetCallback(): Service not connected!");
1323         }
1324     }
1325 
1326     private class MyHandler extends Handler {
MyHandler(Context context)1327         private MyHandler(Context context) {
1328             super(context.getMainLooper());
1329         }
1330 
MyHandler(Looper looper)1331         private MyHandler(Looper looper) {
1332             super(looper);
1333         }
1334 
1335         @Override
handleMessage(android.os.Message msg)1336         public void handleMessage(android.os.Message msg) {
1337             switch (msg.what) {
1338                 case MSG_ENROLL_RESULT:
1339                     sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
1340                     break;
1341                 case MSG_ACQUIRED:
1342                     sendAcquiredResult(msg.arg1 /* acquire info */,
1343                             msg.arg2 /* vendorCode */);
1344                     break;
1345                 case MSG_AUTHENTICATION_SUCCEEDED:
1346                     sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */,
1347                             msg.arg2 == 1 /* isStrongBiometric */);
1348                     break;
1349                 case MSG_AUTHENTICATION_FAILED:
1350                     sendAuthenticatedFailed();
1351                     break;
1352                 case MSG_ERROR:
1353                     sendErrorResult(msg.arg1 /* errMsgId */, msg.arg2 /* vendorCode */);
1354                     break;
1355                 case MSG_REMOVED:
1356                     sendRemovedResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
1357                     break;
1358                 case MSG_CHALLENGE_GENERATED:
1359                     sendChallengeGenerated(msg.arg1 /* sensorId */, msg.arg2 /* userId */,
1360                             (long) msg.obj /* challenge */);
1361                     break;
1362                 case MSG_FINGERPRINT_DETECTED:
1363                     sendFingerprintDetected(msg.arg1 /* sensorId */, msg.arg2 /* userId */,
1364                             (boolean) msg.obj /* isStrongBiometric */);
1365                     break;
1366                 case MSG_UDFPS_POINTER_DOWN:
1367                     sendUdfpsPointerDown(msg.arg1 /* sensorId */);
1368                     break;
1369                 case MSG_UDFPS_POINTER_UP:
1370                     sendUdfpsPointerUp(msg.arg1 /* sensorId */);
1371                     break;
1372                 case MSG_POWER_BUTTON_PRESSED:
1373                     sendPowerPressed();
1374                     break;
1375                 case MSG_UDFPS_OVERLAY_SHOWN:
1376                     sendUdfpsOverlayShown();
1377                 default:
1378                     Slog.w(TAG, "Unknown message: " + msg.what);
1379 
1380             }
1381         }
1382     }
1383 
sendRemovedResult(Fingerprint fingerprint, int remaining)1384     private void sendRemovedResult(Fingerprint fingerprint, int remaining) {
1385         if (mRemovalCallback == null) {
1386             return;
1387         }
1388 
1389         if (mRemoveTracker == null) {
1390             Slog.w(TAG, "Removal tracker is null");
1391             return;
1392         }
1393 
1394         if (mRemoveTracker.mRemoveRequest == RemoveTracker.REMOVE_SINGLE) {
1395             if (fingerprint == null) {
1396                 Slog.e(TAG, "Received MSG_REMOVED, but fingerprint is null");
1397                 return;
1398             }
1399 
1400             if (mRemoveTracker.mSingleFingerprint == null) {
1401                 Slog.e(TAG, "Missing fingerprint");
1402                 return;
1403             }
1404 
1405             final int fingerId = fingerprint.getBiometricId();
1406             int reqFingerId = mRemoveTracker.mSingleFingerprint.getBiometricId();
1407             if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) {
1408                 Slog.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
1409                 return;
1410             }
1411         }
1412 
1413         mRemovalCallback.onRemovalSucceeded(fingerprint, remaining);
1414     }
1415 
sendEnrollResult(Fingerprint fp, int remaining)1416     private void sendEnrollResult(Fingerprint fp, int remaining) {
1417         if (mEnrollmentCallback != null) {
1418             mEnrollmentCallback.onEnrollmentProgress(remaining);
1419         }
1420     }
1421 
sendAuthenticatedSucceeded(Fingerprint fp, int userId, boolean isStrongBiometric)1422     private void sendAuthenticatedSucceeded(Fingerprint fp, int userId, boolean isStrongBiometric) {
1423         if (mAuthenticationCallback != null) {
1424             final AuthenticationResult result =
1425                     new AuthenticationResult(mCryptoObject, fp, userId, isStrongBiometric);
1426             mAuthenticationCallback.onAuthenticationSucceeded(result);
1427         }
1428     }
1429 
sendAuthenticatedFailed()1430     private void sendAuthenticatedFailed() {
1431         if (mAuthenticationCallback != null) {
1432             mAuthenticationCallback.onAuthenticationFailed();
1433         }
1434     }
1435 
sendAcquiredResult(int acquireInfo, int vendorCode)1436     private void sendAcquiredResult(int acquireInfo, int vendorCode) {
1437         if (mAuthenticationCallback != null) {
1438             mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
1439         }
1440         if (mEnrollmentCallback != null && acquireInfo != FINGERPRINT_ACQUIRED_START) {
1441             mEnrollmentCallback.onAcquired(acquireInfo == FINGERPRINT_ACQUIRED_GOOD);
1442         }
1443         final String msg = getAcquiredString(mContext, acquireInfo, vendorCode);
1444         if (msg == null) {
1445             return;
1446         }
1447         // emulate HAL 2.1 behavior and send real acquiredInfo
1448         final int clientInfo = acquireInfo == FINGERPRINT_ACQUIRED_VENDOR
1449                 ? (vendorCode + FINGERPRINT_ACQUIRED_VENDOR_BASE) : acquireInfo;
1450         if (mEnrollmentCallback != null) {
1451             mEnrollmentCallback.onEnrollmentHelp(clientInfo, msg);
1452         } else if (mAuthenticationCallback != null) {
1453             if (acquireInfo != BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START) {
1454                 mAuthenticationCallback.onAuthenticationHelp(clientInfo, msg);
1455             }
1456         }
1457     }
1458 
sendErrorResult(int errMsgId, int vendorCode)1459     private void sendErrorResult(int errMsgId, int vendorCode) {
1460         // emulate HAL 2.1 behavior and send real errMsgId
1461         final int clientErrMsgId = errMsgId == FINGERPRINT_ERROR_VENDOR
1462                 ? (vendorCode + FINGERPRINT_ERROR_VENDOR_BASE) : errMsgId;
1463         if (mEnrollmentCallback != null) {
1464             mEnrollmentCallback.onEnrollmentError(clientErrMsgId,
1465                     getErrorString(mContext, errMsgId, vendorCode));
1466         } else if (mAuthenticationCallback != null) {
1467             mAuthenticationCallback.onAuthenticationError(clientErrMsgId,
1468                     getErrorString(mContext, errMsgId, vendorCode));
1469         } else if (mRemovalCallback != null) {
1470             final Fingerprint fp = mRemoveTracker != null
1471                     ? mRemoveTracker.mSingleFingerprint : null;
1472             mRemovalCallback.onRemovalError(fp, clientErrMsgId,
1473                     getErrorString(mContext, errMsgId, vendorCode));
1474         }
1475     }
1476 
sendChallengeGenerated(int sensorId, int userId, long challenge)1477     private void sendChallengeGenerated(int sensorId, int userId, long challenge) {
1478         if (mGenerateChallengeCallback == null) {
1479             Slog.e(TAG, "sendChallengeGenerated, callback null");
1480             return;
1481         }
1482         mGenerateChallengeCallback.onChallengeGenerated(sensorId, userId, challenge);
1483     }
1484 
sendFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric)1485     private void sendFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric) {
1486         if (mFingerprintDetectionCallback == null) {
1487             Slog.e(TAG, "sendFingerprintDetected, callback null");
1488             return;
1489         }
1490         mFingerprintDetectionCallback.onFingerprintDetected(sensorId, userId, isStrongBiometric);
1491     }
1492 
sendUdfpsPointerDown(int sensorId)1493     private void sendUdfpsPointerDown(int sensorId) {
1494         if (mAuthenticationCallback == null) {
1495             Slog.e(TAG, "sendUdfpsPointerDown, callback null");
1496         } else {
1497             mAuthenticationCallback.onUdfpsPointerDown(sensorId);
1498         }
1499 
1500         if (mEnrollmentCallback != null) {
1501             mEnrollmentCallback.onUdfpsPointerDown(sensorId);
1502         }
1503     }
1504 
sendUdfpsPointerUp(int sensorId)1505     private void sendUdfpsPointerUp(int sensorId) {
1506         if (mAuthenticationCallback == null) {
1507             Slog.e(TAG, "sendUdfpsPointerUp, callback null");
1508         } else {
1509             mAuthenticationCallback.onUdfpsPointerUp(sensorId);
1510         }
1511         if (mEnrollmentCallback != null) {
1512             mEnrollmentCallback.onUdfpsPointerUp(sensorId);
1513         }
1514     }
1515 
sendPowerPressed()1516     private void sendPowerPressed() {
1517         try {
1518             mService.onPowerPressed();
1519         } catch (RemoteException e) {
1520             Slog.e(TAG, "Error sending power press", e);
1521         }
1522     }
1523 
sendUdfpsOverlayShown()1524     private void sendUdfpsOverlayShown() {
1525         if (mEnrollmentCallback != null) {
1526             mEnrollmentCallback.onUdfpsOverlayShown();
1527         }
1528     }
1529 
1530     /**
1531      * @hide
1532      */
FingerprintManager(Context context, IFingerprintService service)1533     public FingerprintManager(Context context, IFingerprintService service) {
1534         mContext = context;
1535         mService = service;
1536         if (mService == null) {
1537             Slog.v(TAG, "FingerprintService was null");
1538         }
1539         mHandler = new MyHandler(context);
1540         if (context.checkCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL)
1541                 == PackageManager.PERMISSION_GRANTED) {
1542             addAuthenticatorsRegisteredCallback(
1543                     new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
1544                         @Override
1545                         public void onAllAuthenticatorsRegistered(
1546                                 @NonNull List<FingerprintSensorPropertiesInternal> sensors) {
1547                             mProps = sensors;
1548                         }
1549                     });
1550         }
1551     }
1552 
getCurrentUserId()1553     private int getCurrentUserId() {
1554         try {
1555             return ActivityManager.getService().getCurrentUser().id;
1556         } catch (RemoteException e) {
1557             throw e.rethrowFromSystemServer();
1558         }
1559     }
1560 
1561     @Nullable
getFirstFingerprintSensor()1562     private FingerprintSensorPropertiesInternal getFirstFingerprintSensor() {
1563         final List<FingerprintSensorPropertiesInternal> allSensors = getSensorPropertiesInternal();
1564         return allSensors.isEmpty() ? null : allSensors.get(0);
1565     }
1566 
cancelEnrollment(long requestId)1567     private void cancelEnrollment(long requestId) {
1568         if (mService != null) try {
1569             mService.cancelEnrollment(mToken, requestId);
1570         } catch (RemoteException e) {
1571             throw e.rethrowFromSystemServer();
1572         }
1573     }
1574 
cancelAuthentication(long requestId)1575     private void cancelAuthentication(long requestId) {
1576         if (mService != null) try {
1577                 mService.cancelAuthentication(
1578                         mToken,
1579                         mContext.getOpPackageName(),
1580                         mContext.getAttributionTag(),
1581                         requestId);
1582         } catch (RemoteException e) {
1583             throw e.rethrowFromSystemServer();
1584         }
1585     }
1586 
cancelFingerprintDetect(long requestId)1587     private void cancelFingerprintDetect(long requestId) {
1588         if (mService == null) {
1589             return;
1590         }
1591 
1592         try {
1593             mService.cancelFingerprintDetect(mToken, mContext.getOpPackageName(), requestId);
1594         } catch (RemoteException e) {
1595             throw e.rethrowFromSystemServer();
1596         }
1597     }
1598 
1599     /**
1600      * @hide
1601      */
getEnrollStageCount()1602     public int getEnrollStageCount() {
1603         if (mEnrollStageThresholds == null) {
1604             mEnrollStageThresholds = createEnrollStageThresholds(mContext);
1605         }
1606         return mEnrollStageThresholds.length + 1;
1607     }
1608 
1609     /**
1610      * @hide
1611      */
getEnrollStageThreshold(int index)1612     public float getEnrollStageThreshold(int index) {
1613         if (mEnrollStageThresholds == null) {
1614             mEnrollStageThresholds = createEnrollStageThresholds(mContext);
1615         }
1616 
1617         if (index < 0 || index > mEnrollStageThresholds.length) {
1618             Slog.w(TAG, "Unsupported enroll stage index: " + index);
1619             return index < 0 ? 0f : 1f;
1620         }
1621 
1622         // The implicit threshold for the final stage is always 1.
1623         return index == mEnrollStageThresholds.length ? 1f : mEnrollStageThresholds[index];
1624     }
1625 
1626     @NonNull
1627     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
createEnrollStageThresholds(@onNull Context context)1628     private float[] createEnrollStageThresholds(@NonNull Context context) {
1629         // TODO(b/200604947): Fetch this value from FingerprintService, rather than internal config
1630         final String[] enrollStageThresholdStrings;
1631         if (isPowerbuttonFps()) {
1632             enrollStageThresholdStrings = context.getResources().getStringArray(
1633                     com.android.internal.R.array.config_sfps_enroll_stage_thresholds);
1634         } else {
1635             enrollStageThresholdStrings = context.getResources().getStringArray(
1636                     com.android.internal.R.array.config_udfps_enroll_stage_thresholds);
1637         }
1638 
1639         final float[] enrollStageThresholds = new float[enrollStageThresholdStrings.length];
1640         for (int i = 0; i < enrollStageThresholds.length; i++) {
1641             enrollStageThresholds[i] = Float.parseFloat(enrollStageThresholdStrings[i]);
1642         }
1643         return enrollStageThresholds;
1644     }
1645 
1646     /**
1647      * @hide
1648      */
getErrorString(Context context, int errMsg, int vendorCode)1649     public static String getErrorString(Context context, int errMsg, int vendorCode) {
1650         switch (errMsg) {
1651             case FINGERPRINT_ERROR_HW_UNAVAILABLE:
1652                 return context.getString(
1653                         com.android.internal.R.string.fingerprint_error_hw_not_available);
1654             case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
1655                 return context.getString(
1656                     com.android.internal.R.string.fingerprint_error_unable_to_process);
1657             case FINGERPRINT_ERROR_TIMEOUT:
1658                 return context.getString(com.android.internal.R.string.fingerprint_error_timeout);
1659             case FINGERPRINT_ERROR_NO_SPACE:
1660                 return context.getString(
1661                     com.android.internal.R.string.fingerprint_error_no_space);
1662             case FINGERPRINT_ERROR_CANCELED:
1663                 return context.getString(com.android.internal.R.string.fingerprint_error_canceled);
1664             case FINGERPRINT_ERROR_LOCKOUT:
1665                 return context.getString(com.android.internal.R.string.fingerprint_error_lockout);
1666             case FINGERPRINT_ERROR_LOCKOUT_PERMANENT:
1667                 return context.getString(
1668                         com.android.internal.R.string.fingerprint_error_lockout_permanent);
1669             case FINGERPRINT_ERROR_USER_CANCELED:
1670                 return context.getString(
1671                         com.android.internal.R.string.fingerprint_error_user_canceled);
1672             case FINGERPRINT_ERROR_NO_FINGERPRINTS:
1673                 return context.getString(
1674                         com.android.internal.R.string.fingerprint_error_no_fingerprints);
1675             case FINGERPRINT_ERROR_HW_NOT_PRESENT:
1676                 return context.getString(
1677                         com.android.internal.R.string.fingerprint_error_hw_not_present);
1678             case BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED:
1679                 return context.getString(
1680                         com.android.internal.R.string.fingerprint_error_security_update_required);
1681             case FINGERPRINT_ERROR_BAD_CALIBRATION:
1682                 return context.getString(
1683                             com.android.internal.R.string.fingerprint_error_bad_calibration);
1684             case BIOMETRIC_ERROR_POWER_PRESSED:
1685                 return context.getString(
1686                     com.android.internal.R.string.fingerprint_error_power_pressed);
1687             case FINGERPRINT_ERROR_VENDOR: {
1688                 String[] msgArray = context.getResources().getStringArray(
1689                         com.android.internal.R.array.fingerprint_error_vendor);
1690                 if (vendorCode < msgArray.length) {
1691                     return msgArray[vendorCode];
1692                 }
1693             }
1694         }
1695 
1696         // This is used as a last resort in case a vendor string is missing
1697         // It should not happen for anything other than FINGERPRINT_ERROR_VENDOR, but
1698         // warn and use the default if all else fails.
1699         Slog.w(TAG, "Invalid error message: " + errMsg + ", " + vendorCode);
1700         return context.getString(
1701                 com.android.internal.R.string.fingerprint_error_vendor_unknown);
1702     }
1703 
1704     /**
1705      * @hide
1706      */
getAcquiredString(Context context, int acquireInfo, int vendorCode)1707     public static String getAcquiredString(Context context, int acquireInfo, int vendorCode) {
1708         switch (acquireInfo) {
1709             case FINGERPRINT_ACQUIRED_GOOD:
1710                 return null;
1711             case FINGERPRINT_ACQUIRED_PARTIAL:
1712                 return context.getString(
1713                     com.android.internal.R.string.fingerprint_acquired_partial);
1714             case FINGERPRINT_ACQUIRED_INSUFFICIENT:
1715                 return context.getString(
1716                     com.android.internal.R.string.fingerprint_acquired_insufficient);
1717             case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
1718                 return context.getString(
1719                     com.android.internal.R.string.fingerprint_acquired_imager_dirty);
1720             case FINGERPRINT_ACQUIRED_TOO_SLOW:
1721                 return context.getString(
1722                     com.android.internal.R.string.fingerprint_acquired_too_slow);
1723             case FINGERPRINT_ACQUIRED_TOO_FAST:
1724                 return context.getString(
1725                     com.android.internal.R.string.fingerprint_acquired_too_fast);
1726             case FINGERPRINT_ACQUIRED_IMMOBILE:
1727                 return context.getString(
1728                     com.android.internal.R.string.fingerprint_acquired_immobile);
1729             case FINGERPRINT_ACQUIRED_TOO_BRIGHT:
1730                 return context.getString(
1731                    com.android.internal.R.string.fingerprint_acquired_too_bright);
1732             case FINGERPRINT_ACQUIRED_POWER_PRESSED:
1733                 return context.getString(
1734                         com.android.internal.R.string.fingerprint_acquired_power_press);
1735             case FINGERPRINT_ACQUIRED_VENDOR: {
1736                 String[] msgArray = context.getResources().getStringArray(
1737                         com.android.internal.R.array.fingerprint_acquired_vendor);
1738                 if (vendorCode < msgArray.length) {
1739                     return msgArray[vendorCode];
1740                 }
1741             }
1742                 break;
1743             case FINGERPRINT_ACQUIRED_START:
1744                 return null;
1745         }
1746         Slog.w(TAG, "Invalid acquired message: " + acquireInfo + ", " + vendorCode);
1747         return null;
1748     }
1749 
1750     private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
1751 
1752         @Override // binder call
1753         public void onEnrollResult(Fingerprint fp, int remaining) {
1754             mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0, fp).sendToTarget();
1755         }
1756 
1757         @Override // binder call
1758         public void onAcquired(int acquireInfo, int vendorCode) {
1759             mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode).sendToTarget();
1760         }
1761 
1762         @Override // binder call
1763         public void onAuthenticationSucceeded(Fingerprint fp, int userId,
1764                 boolean isStrongBiometric) {
1765             mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, isStrongBiometric ? 1 : 0,
1766                     fp).sendToTarget();
1767         }
1768 
1769         @Override
1770         public void onFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric) {
1771             mHandler.obtainMessage(MSG_FINGERPRINT_DETECTED, sensorId, userId, isStrongBiometric)
1772                     .sendToTarget();
1773         }
1774 
1775         @Override // binder call
1776         public void onAuthenticationFailed() {
1777             mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();
1778         }
1779 
1780         @Override // binder call
1781         public void onError(int error, int vendorCode) {
1782             mHandler.obtainMessage(MSG_ERROR, error, vendorCode).sendToTarget();
1783         }
1784 
1785         @Override // binder call
1786         public void onRemoved(Fingerprint fp, int remaining) {
1787             mHandler.obtainMessage(MSG_REMOVED, remaining, 0, fp).sendToTarget();
1788         }
1789 
1790         @Override // binder call
1791         public void onChallengeGenerated(int sensorId, int userId, long challenge) {
1792             mHandler.obtainMessage(MSG_CHALLENGE_GENERATED, sensorId, userId, challenge)
1793                     .sendToTarget();
1794         }
1795 
1796         @Override // binder call
1797         public void onUdfpsPointerDown(int sensorId) {
1798             mHandler.obtainMessage(MSG_UDFPS_POINTER_DOWN, sensorId, 0).sendToTarget();
1799         }
1800 
1801         @Override // binder call
1802         public void onUdfpsPointerUp(int sensorId) {
1803             mHandler.obtainMessage(MSG_UDFPS_POINTER_UP, sensorId, 0).sendToTarget();
1804         }
1805 
1806         @Override
1807         public void onUdfpsOverlayShown() {
1808             mHandler.obtainMessage(MSG_UDFPS_OVERLAY_SHOWN).sendToTarget();
1809         }
1810     };
1811 
1812 }
1813