1 /* 2 * Copyright (C) 2024 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.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD; 20 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START; 21 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR; 22 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR_BASE; 23 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR; 24 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR_BASE; 25 import static android.hardware.fingerprint.FingerprintManager.getAcquiredString; 26 import static android.hardware.fingerprint.FingerprintManager.getErrorString; 27 28 import android.annotation.IntDef; 29 import android.content.Context; 30 import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback; 31 import android.hardware.fingerprint.FingerprintManager.AuthenticationResult; 32 import android.hardware.fingerprint.FingerprintManager.CryptoObject; 33 import android.hardware.fingerprint.FingerprintManager.EnrollmentCallback; 34 import android.hardware.fingerprint.FingerprintManager.FingerprintDetectionCallback; 35 import android.hardware.fingerprint.FingerprintManager.GenerateChallengeCallback; 36 import android.hardware.fingerprint.FingerprintManager.RemovalCallback; 37 import android.util.Slog; 38 39 import androidx.annotation.NonNull; 40 import androidx.annotation.Nullable; 41 42 /** 43 * Encapsulates callbacks and client specific information for each fingerprint related request. 44 * @hide 45 */ 46 public class FingerprintCallback { 47 private static final String TAG = "FingerprintCallback"; 48 public static final int REMOVE_SINGLE = 1; 49 public static final int REMOVE_ALL = 2; 50 @IntDef({REMOVE_SINGLE, REMOVE_ALL}) 51 public @interface RemoveRequest {} 52 @Nullable 53 private AuthenticationCallback mAuthenticationCallback; 54 @Nullable 55 private EnrollmentCallback mEnrollmentCallback; 56 @Nullable 57 private RemovalCallback mRemovalCallback; 58 @Nullable 59 private GenerateChallengeCallback mGenerateChallengeCallback; 60 @Nullable 61 private FingerprintDetectionCallback mFingerprintDetectionCallback; 62 @Nullable 63 private CryptoObject mCryptoObject; 64 @Nullable 65 private @RemoveRequest int mRemoveRequest; 66 @Nullable 67 private Fingerprint mRemoveFingerprint; 68 69 /** 70 * Construction for fingerprint authentication client callback. 71 */ FingerprintCallback(@onNull AuthenticationCallback authenticationCallback, @Nullable CryptoObject cryptoObject)72 FingerprintCallback(@NonNull AuthenticationCallback authenticationCallback, 73 @Nullable CryptoObject cryptoObject) { 74 mAuthenticationCallback = authenticationCallback; 75 mCryptoObject = cryptoObject; 76 } 77 78 /** 79 * Construction for fingerprint detect client callback. 80 */ FingerprintCallback(@onNull FingerprintDetectionCallback fingerprintDetectionCallback)81 FingerprintCallback(@NonNull FingerprintDetectionCallback fingerprintDetectionCallback) { 82 mFingerprintDetectionCallback = fingerprintDetectionCallback; 83 } 84 85 /** 86 * Construction for fingerprint enroll client callback. 87 */ FingerprintCallback(@onNull EnrollmentCallback enrollmentCallback)88 FingerprintCallback(@NonNull EnrollmentCallback enrollmentCallback) { 89 mEnrollmentCallback = enrollmentCallback; 90 } 91 92 /** 93 * Construction for fingerprint generate challenge client callback. 94 */ FingerprintCallback(@onNull GenerateChallengeCallback generateChallengeCallback)95 FingerprintCallback(@NonNull GenerateChallengeCallback generateChallengeCallback) { 96 mGenerateChallengeCallback = generateChallengeCallback; 97 } 98 99 /** 100 * Construction for fingerprint removal client callback. 101 */ FingerprintCallback(@onNull RemovalCallback removalCallback, @RemoveRequest int removeRequest, @Nullable Fingerprint removeFingerprint)102 FingerprintCallback(@NonNull RemovalCallback removalCallback, @RemoveRequest int removeRequest, 103 @Nullable Fingerprint removeFingerprint) { 104 mRemovalCallback = removalCallback; 105 mRemoveRequest = removeRequest; 106 mRemoveFingerprint = removeFingerprint; 107 } 108 109 /** 110 * Propagate enroll progress via the callback. 111 * @param remaining number of enrollment steps remaining 112 */ sendEnrollResult(int remaining)113 public void sendEnrollResult(int remaining) { 114 if (mEnrollmentCallback != null) { 115 mEnrollmentCallback.onEnrollmentProgress(remaining); 116 } 117 } 118 119 /** 120 * Propagate remove face completed via the callback. 121 * @param fingerprint removed identifier 122 * @param remaining number of face enrollments remaining 123 */ sendRemovedResult(@ullable Fingerprint fingerprint, int remaining)124 public void sendRemovedResult(@Nullable Fingerprint fingerprint, int remaining) { 125 if (mRemovalCallback == null) { 126 return; 127 } 128 129 if (mRemoveRequest == REMOVE_SINGLE) { 130 if (fingerprint == null) { 131 Slog.e(TAG, "Received MSG_REMOVED, but fingerprint is null"); 132 return; 133 } 134 135 if (mRemoveFingerprint == null) { 136 Slog.e(TAG, "Missing fingerprint"); 137 return; 138 } 139 140 final int fingerId = fingerprint.getBiometricId(); 141 int reqFingerId = mRemoveFingerprint.getBiometricId(); 142 if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) { 143 Slog.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId); 144 return; 145 } 146 } 147 148 mRemovalCallback.onRemovalSucceeded(fingerprint, remaining); 149 } 150 151 /** 152 * Propagate authentication succeeded via the callback. 153 * @param fingerprint matched identifier 154 * @param userId id of the corresponding user 155 * @param isStrongBiometric if the sensor is strong or not 156 */ sendAuthenticatedSucceeded(@onNull Fingerprint fingerprint, int userId, boolean isStrongBiometric)157 public void sendAuthenticatedSucceeded(@NonNull Fingerprint fingerprint, int userId, 158 boolean isStrongBiometric) { 159 if (mAuthenticationCallback == null) { 160 Slog.e(TAG, "Authentication succeeded but callback is null."); 161 return; 162 } 163 164 final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fingerprint, 165 userId, isStrongBiometric); 166 mAuthenticationCallback.onAuthenticationSucceeded(result); 167 } 168 169 /** 170 * Propagate authentication failed via the callback. 171 */ sendAuthenticatedFailed()172 public void sendAuthenticatedFailed() { 173 if (mAuthenticationCallback != null) { 174 mAuthenticationCallback.onAuthenticationFailed(); 175 } 176 } 177 178 /** 179 * Propagate acquired result via the callback. 180 * @param context corresponding context 181 * @param acquireInfo represents the framework acquired id 182 * @param vendorCode represents the vendor acquired code 183 */ sendAcquiredResult(@onNull Context context, int acquireInfo, int vendorCode)184 public void sendAcquiredResult(@NonNull Context context, int acquireInfo, int vendorCode) { 185 if (mAuthenticationCallback != null) { 186 mAuthenticationCallback.onAuthenticationAcquired(acquireInfo); 187 } 188 if (mEnrollmentCallback != null && acquireInfo != FINGERPRINT_ACQUIRED_START) { 189 mEnrollmentCallback.onAcquired(acquireInfo == FINGERPRINT_ACQUIRED_GOOD); 190 } 191 final String msg = getAcquiredString(context, acquireInfo, vendorCode); 192 if (msg == null) { 193 return; 194 } 195 // emulate HAL 2.1 behavior and send real acquiredInfo 196 final int clientInfo = acquireInfo == FINGERPRINT_ACQUIRED_VENDOR 197 ? (vendorCode + FINGERPRINT_ACQUIRED_VENDOR_BASE) : acquireInfo; 198 if (mEnrollmentCallback != null) { 199 mEnrollmentCallback.onEnrollmentHelp(clientInfo, msg); 200 } else if (mAuthenticationCallback != null) { 201 if (acquireInfo != FINGERPRINT_ACQUIRED_START) { 202 mAuthenticationCallback.onAuthenticationHelp(clientInfo, msg); 203 } 204 } 205 } 206 207 /** 208 * Propagate errors via the callback. 209 * @param context corresponding context 210 * @param errMsgId represents the framework error id 211 * @param vendorCode represents the vendor error code 212 */ sendErrorResult(@onNull Context context, int errMsgId, int vendorCode)213 public void sendErrorResult(@NonNull Context context, int errMsgId, int vendorCode) { 214 // emulate HAL 2.1 behavior and send real errMsgId 215 final int clientErrMsgId = errMsgId == FINGERPRINT_ERROR_VENDOR 216 ? (vendorCode + FINGERPRINT_ERROR_VENDOR_BASE) : errMsgId; 217 if (mEnrollmentCallback != null) { 218 mEnrollmentCallback.onEnrollmentError(clientErrMsgId, 219 getErrorString(context, errMsgId, vendorCode)); 220 } else if (mAuthenticationCallback != null) { 221 mAuthenticationCallback.onAuthenticationError(clientErrMsgId, 222 getErrorString(context, errMsgId, vendorCode)); 223 } else if (mRemovalCallback != null) { 224 mRemovalCallback.onRemovalError(mRemoveFingerprint, clientErrMsgId, 225 getErrorString(context, errMsgId, vendorCode)); 226 } else if (mFingerprintDetectionCallback != null) { 227 mFingerprintDetectionCallback.onDetectionError(errMsgId); 228 mFingerprintDetectionCallback = null; 229 } 230 } 231 232 /** 233 * Propagate challenge generated completed via the callback. 234 * @param sensorId id of the corresponding sensor 235 * @param userId id of the corresponding sensor 236 * @param challenge value of the challenge generated 237 */ sendChallengeGenerated(long challenge, int sensorId, int userId)238 public void sendChallengeGenerated(long challenge, int sensorId, int userId) { 239 if (mGenerateChallengeCallback == null) { 240 Slog.e(TAG, "sendChallengeGenerated, callback null"); 241 return; 242 } 243 mGenerateChallengeCallback.onChallengeGenerated(sensorId, userId, challenge); 244 } 245 246 /** 247 * Propagate fingerprint detected completed via the callback. 248 * @param sensorId id of the corresponding sensor 249 * @param userId id of the corresponding user 250 * @param isStrongBiometric if the sensor is strong or not 251 */ sendFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric)252 public void sendFingerprintDetected(int sensorId, int userId, boolean isStrongBiometric) { 253 if (mFingerprintDetectionCallback == null) { 254 Slog.e(TAG, "sendFingerprintDetected, callback null"); 255 return; 256 } 257 mFingerprintDetectionCallback.onFingerprintDetected(sensorId, userId, isStrongBiometric); 258 } 259 260 /** 261 * Propagate udfps pointer down via the callback. 262 * @param sensorId id of the corresponding sensor 263 */ sendUdfpsPointerDown(int sensorId)264 public void sendUdfpsPointerDown(int sensorId) { 265 if (mAuthenticationCallback == null) { 266 Slog.e(TAG, "sendUdfpsPointerDown, callback null"); 267 } else { 268 mAuthenticationCallback.onUdfpsPointerDown(sensorId); 269 } 270 271 if (mEnrollmentCallback != null) { 272 mEnrollmentCallback.onUdfpsPointerDown(sensorId); 273 } 274 } 275 276 /** 277 * Propagate udfps pointer up via the callback. 278 * @param sensorId id of the corresponding sensor 279 */ sendUdfpsPointerUp(int sensorId)280 public void sendUdfpsPointerUp(int sensorId) { 281 if (mAuthenticationCallback == null) { 282 Slog.e(TAG, "sendUdfpsPointerUp, callback null"); 283 } else { 284 mAuthenticationCallback.onUdfpsPointerUp(sensorId); 285 } 286 if (mEnrollmentCallback != null) { 287 mEnrollmentCallback.onUdfpsPointerUp(sensorId); 288 } 289 } 290 291 /** 292 * Propagate udfps overlay shown via the callback. 293 */ sendUdfpsOverlayShown()294 public void sendUdfpsOverlayShown() { 295 if (mEnrollmentCallback != null) { 296 mEnrollmentCallback.onUdfpsOverlayShown(); 297 } 298 } 299 } 300