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