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