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