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