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 import static android.Manifest.permission.WRITE_DEVICE_CONFIG; 22 23 import android.annotation.IntDef; 24 import android.annotation.RequiresPermission; 25 import android.annotation.SystemApi; 26 import android.annotation.SystemService; 27 import android.content.Context; 28 import android.os.RemoteException; 29 import android.security.keystore.KeyGenParameterSpec; 30 import android.security.keystore.KeyProperties; 31 import android.util.Slog; 32 33 /** 34 * A class that contains biometric utilities. For authentication, see {@link BiometricPrompt}. 35 */ 36 @SystemService(Context.BIOMETRIC_SERVICE) 37 public class BiometricManager { 38 39 private static final String TAG = "BiometricManager"; 40 41 /** 42 * No error detected. 43 */ 44 public static final int BIOMETRIC_SUCCESS = 45 BiometricConstants.BIOMETRIC_SUCCESS; 46 47 /** 48 * The hardware is unavailable. Try again later. 49 */ 50 public static final int BIOMETRIC_ERROR_HW_UNAVAILABLE = 51 BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE; 52 53 /** 54 * The user does not have any biometrics enrolled. 55 */ 56 public static final int BIOMETRIC_ERROR_NONE_ENROLLED = 57 BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS; 58 59 /** 60 * There is no biometric hardware. 61 */ 62 public static final int BIOMETRIC_ERROR_NO_HARDWARE = 63 BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT; 64 65 /** 66 * A security vulnerability has been discovered and the sensor is unavailable until a 67 * security update has addressed this issue. This error can be received if for example, 68 * authentication was requested with {@link Authenticators#BIOMETRIC_STRONG}, but the 69 * sensor's strength can currently only meet {@link Authenticators#BIOMETRIC_WEAK}. 70 */ 71 public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 72 BiometricConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED; 73 74 @IntDef({BIOMETRIC_SUCCESS, 75 BIOMETRIC_ERROR_HW_UNAVAILABLE, 76 BIOMETRIC_ERROR_NONE_ENROLLED, 77 BIOMETRIC_ERROR_NO_HARDWARE, 78 BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED}) 79 @interface BiometricError {} 80 81 /** 82 * Types of authenticators, defined at a level of granularity supported by 83 * {@link BiometricManager} and {@link BiometricPrompt}. 84 * 85 * <p>Types may combined via bitwise OR into a single integer representing multiple 86 * authenticators (e.g. <code>DEVICE_CREDENTIAL | BIOMETRIC_WEAK</code>). 87 * 88 * @see #canAuthenticate(int) 89 * @see BiometricPrompt.Builder#setAllowedAuthenticators(int) 90 */ 91 public interface Authenticators { 92 /** 93 * An {@link IntDef} representing valid combinations of authenticator types. 94 * @hide 95 */ 96 @IntDef(flag = true, value = { 97 BIOMETRIC_STRONG, 98 BIOMETRIC_WEAK, 99 DEVICE_CREDENTIAL, 100 }) 101 @interface Types {} 102 103 /** 104 * Empty set with no authenticators specified. 105 * 106 * <p>This constant is intended for use by {@link android.provider.DeviceConfig} to adjust 107 * the reported strength of a biometric sensor. It is not a valid parameter for any of the 108 * public {@link android.hardware.biometrics} APIs. 109 * 110 * @hide 111 */ 112 @SystemApi 113 @RequiresPermission(WRITE_DEVICE_CONFIG) 114 int EMPTY_SET = 0x0000; 115 116 /** 117 * Placeholder for the theoretical strongest biometric security tier. 118 * @hide 119 */ 120 int BIOMETRIC_MAX_STRENGTH = 0x0001; 121 122 /** 123 * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the 124 * requirements for <strong>Class 3</strong> (formerly <strong>Strong</strong>), as defined 125 * by the Android CDD. 126 * 127 * <p>This corresponds to {@link KeyProperties#AUTH_BIOMETRIC_STRONG} during key generation. 128 * 129 * @see KeyGenParameterSpec.Builder#setUserAuthenticationParameters(int, int) 130 */ 131 int BIOMETRIC_STRONG = 0x000F; 132 133 /** 134 * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the 135 * requirements for <strong>Class 2</strong> (formerly <strong>Weak</strong>), as defined by 136 * the Android CDD. 137 * 138 * <p>Note that this is a superset of {@link #BIOMETRIC_STRONG} and is defined such that 139 * {@code BIOMETRIC_STRONG | BIOMETRIC_WEAK == BIOMETRIC_WEAK}. 140 */ 141 int BIOMETRIC_WEAK = 0x00FF; 142 143 /** 144 * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the 145 * requirements for <strong>Class 1</strong> (formerly <strong>Convenience</strong>), as 146 * defined by the Android CDD. 147 * 148 * <p>This constant is intended for use by {@link android.provider.DeviceConfig} to adjust 149 * the reported strength of a biometric sensor. It is not a valid parameter for any of the 150 * public {@link android.hardware.biometrics} APIs. 151 * 152 * @hide 153 */ 154 @SystemApi 155 @RequiresPermission(WRITE_DEVICE_CONFIG) 156 int BIOMETRIC_CONVENIENCE = 0x0FFF; 157 158 /** 159 * Placeholder for the theoretical weakest biometric security tier. 160 * @hide 161 */ 162 int BIOMETRIC_MIN_STRENGTH = 0x7FFF; 163 164 /** 165 * The non-biometric credential used to secure the device (i.e., PIN, pattern, or password). 166 * This should typically only be used in combination with a biometric auth type, such as 167 * {@link #BIOMETRIC_WEAK}. 168 * 169 * <p>This corresponds to {@link KeyProperties#AUTH_DEVICE_CREDENTIAL} during key 170 * generation. 171 * 172 * @see KeyGenParameterSpec.Builder#setUserAuthenticationParameters(int, int) 173 */ 174 int DEVICE_CREDENTIAL = 1 << 15; 175 } 176 177 private final Context mContext; 178 private final IAuthService mService; 179 180 /** 181 * @hide 182 * @param context 183 * @param service 184 */ BiometricManager(Context context, IAuthService service)185 public BiometricManager(Context context, IAuthService service) { 186 mContext = context; 187 mService = service; 188 } 189 190 /** 191 * Determine if biometrics can be used. In other words, determine if 192 * {@link BiometricPrompt} can be expected to be shown (hardware available, templates enrolled, 193 * user-enabled). This is the equivalent of {@link #canAuthenticate(int)} with 194 * {@link Authenticators#BIOMETRIC_WEAK} 195 * 196 * @return {@link #BIOMETRIC_ERROR_NONE_ENROLLED} if the user does not have any strong 197 * biometrics enrolled, or {@link #BIOMETRIC_ERROR_HW_UNAVAILABLE} if none are currently 198 * supported/enabled. Returns {@link #BIOMETRIC_SUCCESS} if a strong biometric can currently 199 * be used (enrolled and available). 200 * 201 * @deprecated See {@link #canAuthenticate(int)}. 202 */ 203 @Deprecated 204 @RequiresPermission(USE_BIOMETRIC) canAuthenticate()205 public @BiometricError int canAuthenticate() { 206 return canAuthenticate(Authenticators.BIOMETRIC_WEAK); 207 } 208 209 /** 210 * Determine if any of the provided authenticators can be used. In other words, determine if 211 * {@link BiometricPrompt} can be expected to be shown (hardware available, templates enrolled, 212 * user-enabled). 213 * 214 * For biometric authenticators, determine if the device can currently authenticate with at 215 * least the requested strength. For example, invoking this API with 216 * {@link Authenticators#BIOMETRIC_WEAK} on a device that currently only has 217 * {@link Authenticators#BIOMETRIC_STRONG} enrolled will return {@link #BIOMETRIC_SUCCESS}. 218 * 219 * Invoking this API with {@link Authenticators#DEVICE_CREDENTIAL} can be used to determine 220 * if the user has a PIN/Pattern/Password set up. 221 * 222 * @param authenticators bit field consisting of constants defined in {@link Authenticators}. 223 * If multiple authenticators are queried, a logical OR will be applied. 224 * For example, if {@link Authenticators#DEVICE_CREDENTIAL} | 225 * {@link Authenticators#BIOMETRIC_STRONG} is queried and only 226 * {@link Authenticators#DEVICE_CREDENTIAL} is set up, this API will 227 * return {@link #BIOMETRIC_SUCCESS} 228 * 229 * @return {@link #BIOMETRIC_ERROR_NONE_ENROLLED} if the user does not have any of the 230 * requested authenticators enrolled, or {@link #BIOMETRIC_ERROR_HW_UNAVAILABLE} if none are 231 * currently supported/enabled. Returns {@link #BIOMETRIC_SUCCESS} if one of the requested 232 * authenticators can currently be used (enrolled and available). 233 */ 234 @RequiresPermission(USE_BIOMETRIC) canAuthenticate(@uthenticators.Types int authenticators)235 public @BiometricError int canAuthenticate(@Authenticators.Types int authenticators) { 236 return canAuthenticate(mContext.getUserId(), authenticators); 237 } 238 239 /** 240 * @hide 241 */ 242 @RequiresPermission(USE_BIOMETRIC_INTERNAL) canAuthenticate(int userId, @Authenticators.Types int authenticators)243 public @BiometricError int canAuthenticate(int userId, 244 @Authenticators.Types int authenticators) { 245 if (mService != null) { 246 try { 247 final String opPackageName = mContext.getOpPackageName(); 248 return mService.canAuthenticate(opPackageName, userId, authenticators); 249 } catch (RemoteException e) { 250 throw e.rethrowFromSystemServer(); 251 } 252 } else { 253 Slog.w(TAG, "hasEnrolledBiometrics(): Service not connected"); 254 return BIOMETRIC_ERROR_HW_UNAVAILABLE; 255 } 256 } 257 258 /** 259 * @hide 260 * @param userId 261 * @return 262 */ 263 @RequiresPermission(USE_BIOMETRIC_INTERNAL) hasEnrolledBiometrics(int userId)264 public boolean hasEnrolledBiometrics(int userId) { 265 if (mService != null) { 266 try { 267 return mService.hasEnrolledBiometrics(userId, mContext.getOpPackageName()); 268 } catch (RemoteException e) { 269 Slog.w(TAG, "Remote exception in hasEnrolledBiometrics(): " + e); 270 return false; 271 } 272 } else { 273 return false; 274 } 275 } 276 277 /** 278 * Listens for changes to biometric eligibility on keyguard from user settings. 279 * @param callback 280 * @hide 281 */ 282 @RequiresPermission(USE_BIOMETRIC_INTERNAL) registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback)283 public void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback) { 284 if (mService != null) { 285 try { 286 mService.registerEnabledOnKeyguardCallback(callback); 287 } catch (RemoteException e) { 288 throw e.rethrowFromSystemServer(); 289 } 290 } else { 291 Slog.w(TAG, "registerEnabledOnKeyguardCallback(): Service not connected"); 292 } 293 } 294 295 /** 296 * Sets the active user. 297 * @hide 298 */ 299 @RequiresPermission(USE_BIOMETRIC_INTERNAL) setActiveUser(int userId)300 public void setActiveUser(int userId) { 301 if (mService != null) { 302 try { 303 mService.setActiveUser(userId); 304 } catch (RemoteException e) { 305 throw e.rethrowFromSystemServer(); 306 } 307 } else { 308 Slog.w(TAG, "setActiveUser(): Service not connected"); 309 } 310 } 311 312 /** 313 * Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password) 314 * 315 * @param token an opaque token returned by password confirmation. 316 * @hide 317 */ 318 @RequiresPermission(USE_BIOMETRIC_INTERNAL) resetLockout(byte[] token)319 public void resetLockout(byte[] token) { 320 if (mService != null) { 321 try { 322 mService.resetLockout(token); 323 } catch (RemoteException e) { 324 throw e.rethrowFromSystemServer(); 325 } 326 } else { 327 Slog.w(TAG, "resetLockout(): Service not connected"); 328 } 329 } 330 331 /** 332 * Get a list of AuthenticatorIDs for biometric authenticators which have 1) enrolled templates, 333 * and 2) meet the requirements for integrating with Keystore. The AuthenticatorIDs are known 334 * in Keystore land as SIDs, and are used during key generation. 335 * @hide 336 */ 337 @RequiresPermission(USE_BIOMETRIC_INTERNAL) getAuthenticatorIds()338 public long[] getAuthenticatorIds() { 339 if (mService != null) { 340 try { 341 return mService.getAuthenticatorIds(); 342 } catch (RemoteException e) { 343 throw e.rethrowFromSystemServer(); 344 } 345 } else { 346 Slog.w(TAG, "getAuthenticatorIds(): Service not connected"); 347 return new long[0]; 348 } 349 } 350 351 } 352 353