• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.biometrics;
18 
19 import static android.Manifest.permission.USE_BIOMETRIC;
20 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
21 
22 import android.annotation.IntDef;
23 import android.annotation.RequiresPermission;
24 import android.annotation.SystemService;
25 import android.content.Context;
26 import android.content.pm.PackageManager;
27 import android.os.RemoteException;
28 import android.util.Slog;
29 
30 /**
31  * A class that contains biometric utilities. For authentication, see {@link BiometricPrompt}.
32  */
33 @SystemService(Context.BIOMETRIC_SERVICE)
34 public class BiometricManager {
35 
36     private static final String TAG = "BiometricManager";
37 
38     /**
39      * No error detected.
40      */
41     public static final int BIOMETRIC_SUCCESS =
42             BiometricConstants.BIOMETRIC_SUCCESS;
43 
44     /**
45      * The hardware is unavailable. Try again later.
46      */
47     public static final int BIOMETRIC_ERROR_HW_UNAVAILABLE =
48             BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
49 
50     /**
51      * The user does not have any biometrics enrolled.
52      */
53     public static final int BIOMETRIC_ERROR_NONE_ENROLLED =
54             BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS;
55 
56     /**
57      * There is no biometric hardware.
58      */
59     public static final int BIOMETRIC_ERROR_NO_HARDWARE =
60             BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT;
61 
62     @IntDef({BIOMETRIC_SUCCESS,
63             BIOMETRIC_ERROR_HW_UNAVAILABLE,
64             BIOMETRIC_ERROR_NONE_ENROLLED,
65             BIOMETRIC_ERROR_NO_HARDWARE})
66     @interface BiometricError {}
67 
68     private final Context mContext;
69     private final IBiometricService mService;
70     private final boolean mHasHardware;
71 
72     /**
73      * @param context
74      * @return
75      * @hide
76      */
hasBiometrics(Context context)77     public static boolean hasBiometrics(Context context) {
78         final PackageManager pm = context.getPackageManager();
79         return pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
80                 || pm.hasSystemFeature(PackageManager.FEATURE_IRIS)
81                 || pm.hasSystemFeature(PackageManager.FEATURE_FACE);
82     }
83 
84     /**
85      * @hide
86      * @param context
87      * @param service
88      */
BiometricManager(Context context, IBiometricService service)89     public BiometricManager(Context context, IBiometricService service) {
90         mContext = context;
91         mService = service;
92 
93         mHasHardware = hasBiometrics(context);
94     }
95 
96     /**
97      * Determine if biometrics can be used. In other words, determine if {@link BiometricPrompt}
98      * can be expected to be shown (hardware available, templates enrolled, user-enabled).
99      *
100      * @return Returns {@link #BIOMETRIC_ERROR_NONE_ENROLLED} if the user does not have any
101      *     enrolled, or {@link #BIOMETRIC_ERROR_HW_UNAVAILABLE} if none are currently
102      *     supported/enabled. Returns {@link #BIOMETRIC_SUCCESS} if a biometric can currently be
103      *     used (enrolled and available).
104      */
105     @RequiresPermission(USE_BIOMETRIC)
canAuthenticate()106     public @BiometricError int canAuthenticate() {
107         if (mService != null) {
108             try {
109                 return mService.canAuthenticate(mContext.getOpPackageName());
110             } catch (RemoteException e) {
111                 throw e.rethrowFromSystemServer();
112             }
113         } else {
114             if (!mHasHardware) {
115                 return BIOMETRIC_ERROR_NO_HARDWARE;
116             } else {
117                 Slog.w(TAG, "hasEnrolledBiometrics(): Service not connected");
118                 return BIOMETRIC_ERROR_HW_UNAVAILABLE;
119             }
120         }
121     }
122 
123     /**
124      * Listens for changes to biometric eligibility on keyguard from user settings.
125      * @param callback
126      * @hide
127      */
128     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback)129     public void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback) {
130         if (mService != null) {
131             try {
132                 mService.registerEnabledOnKeyguardCallback(callback);
133             } catch (RemoteException e) {
134                 throw e.rethrowFromSystemServer();
135             }
136         } else {
137             Slog.w(TAG, "registerEnabledOnKeyguardCallback(): Service not connected");
138         }
139     }
140 
141     /**
142      * Sets the active user.
143      * @hide
144      */
145     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
setActiveUser(int userId)146     public void setActiveUser(int userId) {
147         if (mService != null) {
148             try {
149                 mService.setActiveUser(userId);
150             } catch (RemoteException e) {
151                 throw e.rethrowFromSystemServer();
152             }
153         } else {
154             Slog.w(TAG, "setActiveUser(): Service not connected");
155         }
156     }
157 
158     /**
159      * Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password)
160      *
161      * @param token an opaque token returned by password confirmation.
162      * @hide
163      */
164     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
resetLockout(byte[] token)165     public void resetLockout(byte[] token) {
166         if (mService != null) {
167             try {
168                 mService.resetLockout(token);
169             } catch (RemoteException e) {
170                 throw e.rethrowFromSystemServer();
171             }
172         } else {
173             Slog.w(TAG, "resetLockout(): Service not connected");
174         }
175     }
176 
177     /**
178      * TODO(b/123378871): Remove when moved.
179      * @hide
180      */
181     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
onConfirmDeviceCredentialSuccess()182     public void onConfirmDeviceCredentialSuccess() {
183         if (mService != null) {
184             try {
185                 mService.onConfirmDeviceCredentialSuccess();
186             } catch (RemoteException e) {
187                 throw e.rethrowFromSystemServer();
188             }
189         } else {
190             Slog.w(TAG, "onConfirmDeviceCredentialSuccess(): Service not connected");
191         }
192     }
193 
194     /**
195      * TODO(b/123378871): Remove when moved.
196      * @hide
197      */
198     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
onConfirmDeviceCredentialError(int error, String message)199     public void onConfirmDeviceCredentialError(int error, String message) {
200         if (mService != null) {
201             try {
202                 mService.onConfirmDeviceCredentialError(error, message);
203             } catch (RemoteException e) {
204                 throw e.rethrowFromSystemServer();
205             }
206         } else {
207             Slog.w(TAG, "onConfirmDeviceCredentialError(): Service not connected");
208         }
209     }
210 
211     /**
212      * TODO(b/123378871): Remove when moved.
213      * @hide
214      */
215     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
registerCancellationCallback(IBiometricConfirmDeviceCredentialCallback callback)216     public void registerCancellationCallback(IBiometricConfirmDeviceCredentialCallback callback) {
217         if (mService != null) {
218             try {
219                 mService.registerCancellationCallback(callback);
220             } catch (RemoteException e) {
221                 throw e.rethrowFromSystemServer();
222             }
223         } else {
224             Slog.w(TAG, "registerCancellationCallback(): Service not connected");
225         }
226     }
227 }
228 
229