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 return canAuthenticate(mContext.getUserId()); 108 } 109 110 /** 111 * @hide 112 */ 113 @RequiresPermission(USE_BIOMETRIC_INTERNAL) canAuthenticate(int userId)114 public @BiometricError int canAuthenticate(int userId) { 115 if (mService != null) { 116 try { 117 return mService.canAuthenticate(mContext.getOpPackageName(), userId); 118 } catch (RemoteException e) { 119 throw e.rethrowFromSystemServer(); 120 } 121 } else { 122 if (!mHasHardware) { 123 return BIOMETRIC_ERROR_NO_HARDWARE; 124 } else { 125 Slog.w(TAG, "hasEnrolledBiometrics(): Service not connected"); 126 return BIOMETRIC_ERROR_HW_UNAVAILABLE; 127 } 128 } 129 } 130 131 /** 132 * @hide 133 * @param userId 134 * @return 135 */ 136 @RequiresPermission(USE_BIOMETRIC_INTERNAL) hasEnrolledBiometrics(int userId)137 public boolean hasEnrolledBiometrics(int userId) { 138 if (mService != null) { 139 try { 140 return mService.hasEnrolledBiometrics(userId); 141 } catch (RemoteException e) { 142 Slog.w(TAG, "Remote exception in hasEnrolledBiometrics(): " + e); 143 return false; 144 } 145 } else { 146 return false; 147 } 148 } 149 150 /** 151 * Listens for changes to biometric eligibility on keyguard from user settings. 152 * @param callback 153 * @hide 154 */ 155 @RequiresPermission(USE_BIOMETRIC_INTERNAL) registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback)156 public void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback) { 157 if (mService != null) { 158 try { 159 mService.registerEnabledOnKeyguardCallback(callback); 160 } catch (RemoteException e) { 161 throw e.rethrowFromSystemServer(); 162 } 163 } else { 164 Slog.w(TAG, "registerEnabledOnKeyguardCallback(): Service not connected"); 165 } 166 } 167 168 /** 169 * Sets the active user. 170 * @hide 171 */ 172 @RequiresPermission(USE_BIOMETRIC_INTERNAL) setActiveUser(int userId)173 public void setActiveUser(int userId) { 174 if (mService != null) { 175 try { 176 mService.setActiveUser(userId); 177 } catch (RemoteException e) { 178 throw e.rethrowFromSystemServer(); 179 } 180 } else { 181 Slog.w(TAG, "setActiveUser(): Service not connected"); 182 } 183 } 184 185 /** 186 * Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password) 187 * 188 * @param token an opaque token returned by password confirmation. 189 * @hide 190 */ 191 @RequiresPermission(USE_BIOMETRIC_INTERNAL) resetLockout(byte[] token)192 public void resetLockout(byte[] token) { 193 if (mService != null) { 194 try { 195 mService.resetLockout(token); 196 } catch (RemoteException e) { 197 throw e.rethrowFromSystemServer(); 198 } 199 } else { 200 Slog.w(TAG, "resetLockout(): Service not connected"); 201 } 202 } 203 204 /** 205 * TODO(b/123378871): Remove when moved. 206 * @hide 207 */ 208 @RequiresPermission(USE_BIOMETRIC_INTERNAL) onConfirmDeviceCredentialSuccess()209 public void onConfirmDeviceCredentialSuccess() { 210 if (mService != null) { 211 try { 212 mService.onConfirmDeviceCredentialSuccess(); 213 } catch (RemoteException e) { 214 throw e.rethrowFromSystemServer(); 215 } 216 } else { 217 Slog.w(TAG, "onConfirmDeviceCredentialSuccess(): Service not connected"); 218 } 219 } 220 221 /** 222 * TODO(b/123378871): Remove when moved. 223 * @hide 224 */ 225 @RequiresPermission(USE_BIOMETRIC_INTERNAL) onConfirmDeviceCredentialError(int error, String message)226 public void onConfirmDeviceCredentialError(int error, String message) { 227 if (mService != null) { 228 try { 229 mService.onConfirmDeviceCredentialError(error, message); 230 } catch (RemoteException e) { 231 throw e.rethrowFromSystemServer(); 232 } 233 } else { 234 Slog.w(TAG, "onConfirmDeviceCredentialError(): Service not connected"); 235 } 236 } 237 238 /** 239 * TODO(b/123378871): Remove when moved. 240 * @hide 241 */ 242 @RequiresPermission(USE_BIOMETRIC_INTERNAL) registerCancellationCallback(IBiometricConfirmDeviceCredentialCallback callback)243 public void registerCancellationCallback(IBiometricConfirmDeviceCredentialCallback callback) { 244 if (mService != null) { 245 try { 246 mService.registerCancellationCallback(callback); 247 } catch (RemoteException e) { 248 throw e.rethrowFromSystemServer(); 249 } 250 } else { 251 Slog.w(TAG, "registerCancellationCallback(): Service not connected"); 252 } 253 } 254 } 255 256