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