From 64c13a083a2dd5226990d805105cbc9df15f02da Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Mon, 21 Sep 2020 12:37:56 -0700 Subject: [PATCH 1/4] Update fingerprint #authenticate interfaces & documentation 1) Split into onAuthenticationSucceeded and onAuthenticaitonFailed. No longer need to use "weird behavior" below: A) authenticated(id=0) == reject B) onEnrolled(id=0) --> previously forbidden C) remove(id=0) --> previously magic number to remove all enrollments. The new interface has remove(int[] ids). 2) Renames keystoreOperationId to operationId, since keystore is only one example of a valid use case. operationId and HATs can be used as attestation for any opaque operation. Bug: 168842956 Bug: 168843220 Test: make -j56 android.hardware.biometrics.fingerprint-update-api Test: make -j56 VtsHalBiometricsFingerprintTargetTest Change-Id: I7ca0365be9cf82539d6cabc6d9fcec916badc323 --- .../biometrics/fingerprint/ISession.aidl | 2 +- .../fingerprint/ISessionCallback.aidl | 3 +- .../biometrics/fingerprint/ISession.aidl | 56 ++++++++++++++++++- .../fingerprint/ISessionCallback.aidl | 22 +++++++- .../VtsHalBiometricsFingerprintTargetTest.cpp | 6 +- 5 files changed, 84 insertions(+), 5 deletions(-) diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl index 06c8623bf5..c1f66e3b1f 100644 --- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl @@ -19,7 +19,7 @@ package android.hardware.biometrics.fingerprint; @VintfStability interface ISession { android.hardware.biometrics.common.ICancellationSignal enroll(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat); - android.hardware.biometrics.common.ICancellationSignal authenticate(in int cookie, in long keystoreOperationId); + android.hardware.biometrics.common.ICancellationSignal authenticate(in int cookie, in long operationId); android.hardware.biometrics.common.ICancellationSignal detectInteraction(in int cookie); void enumerateEnrollments(in int cookie); void removeEnrollments(in int cookie, in int[] enrollmentIds); diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl index 614044790a..114a2d10b1 100644 --- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl @@ -22,7 +22,8 @@ interface ISessionCallback { void onAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfo info, in int vendorCode); void onError(in android.hardware.biometrics.fingerprint.Error error, in int vendorCode); void onEnrollmentProgress(in int enrollmentId, int remaining, int vendorCode); - void onAuthenticated(in int enrollmentId, in android.hardware.keymaster.HardwareAuthToken hat); + void onAuthenticationSucceeded(in int enrollmentId, in android.hardware.keymaster.HardwareAuthToken hat); + void onAuthenticationFailed(); void onInteractionDetected(); void onEnrollmentsEnumerated(in int[] enrollmentIds); void onEnrollmentsRemoved(in int[] enrollmentIds); diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl index e2d23a6160..2d2dcafae9 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl @@ -27,7 +27,61 @@ interface ISession { ICancellationSignal enroll(in int cookie, in HardwareAuthToken hat); - ICancellationSignal authenticate(in int cookie, in long keystoreOperationId); + /** + * authenticate: + * + * A request to start looking for fingerprints to authenticate. + * + * Once the HAL is able to start processing the authentication request, it must + * notify framework via ISessionCallback#onStateChanged with + * SessionState::AUTHENTICATING. + * + * At any point during authentication, if a non-recoverable error occurs, + * the HAL must notify the framework via ISessionCallback#onError with + * the applicable authentication-specific error, and then send + * ISessionCallback#onStateChanged(cookie, SessionState::IDLING). + * + * During authentication, the implementation may notify the framework + * via ISessionCallback#onAcquired with messages that may be used to guide + * the user. This callback can be invoked multiple times if necessary. + * + * The HAL must notify the framework of accepts/rejects via + * ISessionCallback#onAuthentication*. + * + * The authentication lifecycle ends when either + * 1) A fingerprint is accepted, and ISessionCallback#onAuthenticationSucceeded + * is invoked, or + * 2) Any non-recoverable error occurs (such as lockout). See the full + * list of authentication-specific errors in the Error enum. + * + * Note that it is now the HAL's responsibility to keep track of lockout + * states. See IFingerprint#setLockoutCallback and ISession#resetLockout. + * + * Note that upon successful authentication, ONLY sensors configured as + * SensorStrength::STRONG are allowed to create and send a + * HardwareAuthToken to the framework. See the Android CDD for more + * details. For SensorStrength::STRONG sensors, the HardwareAuthToken's + * "challenge" field must be set with the operationId passed in during + * #authenticate. If the sensor is NOT SensorStrength::STRONG, the + * HardwareAuthToken MUST be null. + * + * @param cookie An identifier used to track subsystem operations related + * to this call path. The framework will guarantee that it is + * unique per ISession. + * @param operationId For sensors configured as SensorStrength::STRONG, + * this must be used ONLY upon successful authentication + * and wrapped in the HardwareAuthToken's "challenge" + * field and sent to the framework via + * ISessionCallback#onAuthenticated. The operationId is + * an opaque identifier created from a separate secure + * subsystem such as, but not limited to KeyStore/KeyMaster. + * The HardwareAuthToken can then be used as an attestation + * for the provided operation. For example, this is used + * to unlock biometric-bound auth-per-use keys (see + * setUserAuthenticationParameters in + * KeyGenParameterSpec.Builder and KeyProtection.Builder. + */ + ICancellationSignal authenticate(in int cookie, in long operationId); ICancellationSignal detectInteraction(in int cookie); diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl index c608d65569..d494965f42 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl @@ -31,7 +31,27 @@ interface ISessionCallback { void onEnrollmentProgress(in int enrollmentId, int remaining, int vendorCode); - void onAuthenticated(in int enrollmentId, in HardwareAuthToken hat); + /** + * Used to notify the framework upon successful authentication. Note that the authentication + * lifecycle ends when either 1) a fingerprint is accepted, or 2) an error such as + * Error::LOCKOUT occurred. The authentication lifecycle does NOT end when a fingerprint is + * rejected. + * + * @param enrollmentId Fingerprint that was accepted. + * @param hat If the sensor is configured as SensorStrength::STRONG, a non-null attestation that + * a fingerprint was accepted. The HardwareAuthToken's "challenge" field must be set + * with the operationId passed in during ISession#authenticate. If the sensor is NOT + * SensorStrength::STRONG, the HardwareAuthToken MUST be null. + */ + void onAuthenticationSucceeded(in int enrollmentId, in HardwareAuthToken hat); + + /** + * Used to notify the framework upon rejected attempts. Note that the authentication + * lifecycle ends when either 1) a fingerprint is accepted, or 2) an error such as + * Error::LOCKOUT occurred. The authentication lifecycle does NOT end when a fingerprint is + * rejected. + */ + void onAuthenticationFailed(); void onInteractionDetected(); diff --git a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp index 9590d68000..4651f25879 100644 --- a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp +++ b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp @@ -65,11 +65,15 @@ class SessionCallback : public BnSessionCallback { return ndk::ScopedAStatus::ok(); } - ndk::ScopedAStatus onAuthenticated(int32_t /*enrollmentId*/, + ndk::ScopedAStatus onAuthenticationSucceeded(int32_t /*enrollmentId*/, const keymaster::HardwareAuthToken& /*hat*/) override { return ndk::ScopedAStatus::ok(); } + ndk::ScopedAStatus onAuthenticationFailed() override { + return ndk::ScopedAStatus::ok(); + } + ndk::ScopedAStatus onInteractionDetected() override { return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus onEnrollmentsEnumerated( From 1288c105a7d074963cd0154abb01e65397dae3ab Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Fri, 18 Sep 2020 16:42:44 -0700 Subject: [PATCH 2/4] Minor API changes and additional documentation for IFingerprint 1) Removes vendorCode from onEnrollmentProgress. This is already being sent in ISessionCallback#onAcquired 2) Adds missing SessionState::INVALIDATING_AUTHENTICATOR_ID state Test: make -j56 android.hardware.biometrics.fingerprint-update-api Test: make -j56 VtsHalBiometricsFingerprintTargetTest Test: make -j56 Change-Id: I246153339b336c029c9f156868127456aecf1a04 --- .../fingerprint/ISessionCallback.aidl | 2 +- .../biometrics/fingerprint/SessionState.aidl | 3 +- .../biometrics/fingerprint/Error.aidl | 43 +++++++- .../biometrics/fingerprint/ISession.aidl | 101 +++++++++++++++--- .../fingerprint/ISessionCallback.aidl | 9 +- .../biometrics/fingerprint/SessionState.aidl | 36 +++++++ .../VtsHalBiometricsFingerprintTargetTest.cpp | 4 +- 7 files changed, 177 insertions(+), 21 deletions(-) diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl index 114a2d10b1..cbac890442 100644 --- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl @@ -21,7 +21,7 @@ interface ISessionCallback { void onStateChanged(in int cookie, in android.hardware.biometrics.fingerprint.SessionState state); void onAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfo info, in int vendorCode); void onError(in android.hardware.biometrics.fingerprint.Error error, in int vendorCode); - void onEnrollmentProgress(in int enrollmentId, int remaining, int vendorCode); + void onEnrollmentProgress(in int enrollmentId, int remaining); void onAuthenticationSucceeded(in int enrollmentId, in android.hardware.keymaster.HardwareAuthToken hat); void onAuthenticationFailed(); void onInteractionDetected(); diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl index 38ca1e052b..97f1a1e987 100644 --- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl @@ -25,5 +25,6 @@ enum SessionState { ENUMERATING_ENROLLMENTS = 4, REMOVING_ENROLLMENTS = 5, GETTING_AUTHENTICATOR_ID = 6, - RESETTING_LOCKOUT = 7, + INVALIDATING_AUTHENTICATOR_ID = 7, + RESETTING_LOCKOUT = 8, } diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl index cc79de7b05..da5ee18686 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl @@ -19,14 +19,55 @@ package android.hardware.biometrics.fingerprint; @VintfStability @Backing(type="byte") enum Error { + /** + * A hardware error has occurred that cannot be resolved. For example, I2C failure or a broken + * sensor. + */ HW_UNAVAILABLE, + + /** + * The implementation is unable to process the request. For example, invalid arguments were + * supplied. + */ UNABLE_TO_PROCESS, + + /** + * The current operation took too long to complete. + */ TIMEOUT, + + /** + * No space available to store additional enrollments. + */ NO_SPACE, + + /** + * The operation was canceled. See common::ICancellationSignal. + */ CANCELED, + + /** + * The implementation was unable to remove an enrollment. + * See ISession#removeEnrollments. + */ UNABLE_TO_REMOVE, + + /** + * Authentication is locked out due to too many unsuccessful attempts. This is a rate-limiting + * lockout, and authentication can be restarted after a period of time. See the Android CDD for + * the full set of lockout and rate-limiting requirements. + */ LOCKOUT, + + /** + * Authenticatio nis disabled until the user unlocks with their device credential + * (PIN/Pattern/Password). See ISession#resetLockout. + */ LOCKOUT_PERMANENT, - VENDOR + + /** + * Used to enable vendor-specific error messages. + */ + VENDOR, } diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl index 2d2dcafae9..5fa56e012c 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl @@ -19,12 +19,75 @@ package android.hardware.biometrics.fingerprint; import android.hardware.biometrics.common.ICancellationSignal; import android.hardware.keymaster.HardwareAuthToken; +/** + * Operations that can be performed for unique sessions retrieved via IFingerprint#createSession. + * Methods defined within this interface can be split into the following categories: + * 1) Methods associated with a state (see the SessionState enum). State-based operations are + * handled by the HAL in FIFO order. + * 1a) Cancellable state-based operations. If a cancellable operation is in-progress and the + * framework requests a subsequent state-based operation, the implementation should finish + * the operation via ISessionCallback#onError with Error::CANCELED. + * 1b) Non-cancellable state-based operations. These operations should fully complete before the + * next state-based operation can be started. + * 2) Methods without a state. These methods may be invoked by the framework depending on its + * use case. For example on devices with sensors of FingerprintSensorType::UNDER_DISPLAY_*, + * ISession#onFingerDown may be invoked while the HAL is in SessionState::ENROLLING, + * SessionState::AUTHENTICATING, or SessionState::DETECTING_INTERACTION. + * + * If the HAL has multiple operations in its queue, it is not required to notify the framework + * of SessionState::IDLING between each operation. However, it must notify the framework when all + * work is completed. See ISessionCallback#onStateChanged. For example, the following is a valid + * sequence of ISessionCallback#onStateChanged invocations: SessionState::IDLING --> + * SessionState::ENROLLING --> SessionState::ENUMERATING_ENROLLMENTS --> SessionState::IDLING. + */ @VintfStability interface ISession { /** * Methods applicable to any fingerprint type. */ + /** + * enroll: + * + * A request to add a fingerprint enrollment. + * + * Once the HAL is able to start processing the enrollment request, it must + * notify the framework via ISessionCallback#onStateChanged with + * SessionState::ENROLLING. + * + * At any point during enrollment, if a non-recoverable error occurs, + * the HAL must notify the framework via ISessionCallback#onError with + * the applicable enrollment-specific error, and then send + * ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no + * subsequent operation is in the queue. + * + * Before capturing fingerprint data, the implementation must first + * verify the authenticity and integrity of the provided HardwareAuthToken. + * In addition, it must check that the challenge within the provided + * HardwareAuthToken is valid. See IFingerprint#generateChallenge. + * If any of the above checks fail, the framework must be notified + * via ISessionCallback#onError and the HAL must notify the framework when + * it returns to the idle state. See Error::UNABLE_TO_PROCESS. + * + * During enrollment, the implementation may notify the framework + * via ISessionCallback#onAcquired with messages that may be used to guide + * the user. This callback can be invoked multiple times if necessary. + * Similarly, the framework may be notified of enrollment progress changes + * via ISessionCallback#onEnrollmentProgress. Once the framework is notified + * that there are 0 "remaining" steps, the framework may cache the + * "enrollmentId". See ISessionCallback#onEnrollmentProgress for more info. + * The HAL must notify the framework once it returns to the idle state. + * + * When a finger is successfully added and before the framework is notified + * of remaining=0, the implementation MUST update and associate this + * (sensorId, user) pair with a new new entropy-encoded random identifier. + * See ISession#getAuthenticatorId for more information. + * + * @param cookie An identifier used to track subsystem operations related + * to this call path. The client must guarantee that it is + * unique per ISession. + * @param hat See above documentation. + */ ICancellationSignal enroll(in int cookie, in HardwareAuthToken hat); /** @@ -39,7 +102,8 @@ interface ISession { * At any point during authentication, if a non-recoverable error occurs, * the HAL must notify the framework via ISessionCallback#onError with * the applicable authentication-specific error, and then send - * ISessionCallback#onStateChanged(cookie, SessionState::IDLING). + * ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no + * subsequent operation is in the queue. * * During authentication, the implementation may notify the framework * via ISessionCallback#onAcquired with messages that may be used to guide @@ -66,7 +130,7 @@ interface ISession { * HardwareAuthToken MUST be null. * * @param cookie An identifier used to track subsystem operations related - * to this call path. The framework will guarantee that it is + * to this call path. The client must guarantee that it is * unique per ISession. * @param operationId For sensors configured as SensorStrength::STRONG, * this must be used ONLY upon successful authentication @@ -99,9 +163,10 @@ interface ISession { * The following only applies to sensors that are configured as * SensorStrength::STRONG. * - * The authenticatorId is used during key generation and key import to to - * associate a key (in KeyStore / KeyMaster) with the current set of - * enrolled fingerprints. For example, the following public Android APIs + * The authenticatorId is a (sensorId, user)-specific identifier which + * can be used during key generation and key import to to associate a + * key (in KeyStore / KeyMaster) with the current set of enrolled + * fingerprints. For example, the following public Android APIs * allow for keys to be invalidated when the user adds a new enrollment * after the key was created: * KeyGenParameterSpec.Builder.setInvalidatedByBiometricEnrollment and @@ -120,7 +185,7 @@ interface ISession { * 4) MUST be an entropy-encoded random number * * @param cookie An identifier used to track subsystem operations related - * to this call path. The framework will guarantee that it is + * to this call path. The client must guarantee that it is * unique per ISession. */ void getAuthenticatorId(in int cookie); @@ -138,9 +203,15 @@ interface ISession { * * When invoked by the framework, the implementation must perform the * following sequence of events: - * 1) Verify the authenticity and integrity of the provided HAT + * 1) Verify the authenticity and integrity of the provided HAT. If this + * check fails, the HAL must invoke ISessionCallback#onError with + * Error::UNABLE_TO_PROCESS and return to + * SessionState::IDLING if no subsequent work is in the queue. * 2) Verify that the timestamp provided within the HAT is relatively - * recent (e.g. on the order of minutes, not hours). + * recent (e.g. on the order of minutes, not hours). If this check fails, + * the HAL must invoke ISessionCallback#onError with + * Error::UNABLE_TO_PROCESS and return to SessionState::IDLING + * if no subsequent work is in the queue. * 3) Update the authenticatorId with a new entropy-encoded random number * 4) Persist the new authenticatorId to non-ephemeral storage * 5) Notify the framework that the above is completed, via @@ -154,7 +225,7 @@ interface ISession { * across multiple biometric HALs as necessary. * * @param cookie An identifier used to track subsystem operations related - * to this call path. The framework will guarantee that it is + * to this call path. The client must guarantee that it is * unique per ISession. * @param hat HardwareAuthToken that must be validated before proceeding * with this operation. @@ -169,15 +240,15 @@ interface ISession { * 1) Verify the authenticity and integrity of the provided HAT * 2) Verify that the timestamp provided within the HAT is relatively * recent (e.g. on the order of minutes, not hours). + * If either of the checks fail, the HAL must invoke ISessionCallback#onError + * with Error::UNABLE_TO_PROCESS and return to SessionState::IDLING + * if no subsequent work is in the queue. * - * Upon successful verification, the HAL must notify the framework via - * ILockoutCallback#onLockoutChanged(sensorId, userId, 0). - * - * If verification was uncessful, the HAL must notify the framework via - * ILockoutCallback#onLockoutChanged(sensorId, userId, remaining_time). + * Upon successful verification, the HAL must clear the lockout counter + * and notify the framework via ILockoutCallback#onLockoutChanged(sensorId, userId, 0). * * @param cookie An identifier used to track subsystem operations related - * to this call path. The framework will guarantee that it is + * to this call path. The client must guarantee that it is * unique per ISession. * @param hat HardwareAuthToken See above documentation. */ diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl index d494965f42..7130520ca6 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl @@ -29,7 +29,14 @@ interface ISessionCallback { void onError(in Error error, in int vendorCode); - void onEnrollmentProgress(in int enrollmentId, int remaining, int vendorCode); + /** + * Used to notify the framework of enrollment progress. Enrollment completes when remaining==0, + * + * @param enrollmentId Unique stable identifier for the enrollment that's being added by this + * ISession#enroll invocation. + * @param remaining Remaining number of steps before enrollment is complete. + */ + void onEnrollmentProgress(in int enrollmentId, int remaining); /** * Used to notify the framework upon successful authentication. Note that the authentication diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SessionState.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SessionState.aidl index 3b4ba184e6..405b011b31 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SessionState.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SessionState.aidl @@ -19,13 +19,49 @@ package android.hardware.biometrics.fingerprint; @VintfStability @Backing(type="byte") enum SessionState { + /** + * The HAL is not processing any session requests. + */ IDLING, + + /** + * The HAL is processing the ISession#enroll request. + */ ENROLLING, + + /** + * The HAL is processing the ISession#authenticate request. + */ AUTHENTICATING, + + /** + * The HAL is processing the ISession#detectInteraction request. + */ DETECTING_INTERACTION, + + /** + * The HAL is processing the ISession#enumerateEnrollments request. + */ ENUMERATING_ENROLLMENTS, + + /** + * The HAL is processing the ISession#removeEnrollments request. + */ REMOVING_ENROLLMENTS, + + /** + * The HAL is processing the ISession#getAuthenticatorId request. + */ GETTING_AUTHENTICATOR_ID, + + /** + * The HAL is processing the ISession#invalidateAuthenticatorId request. + */ + INVALIDATING_AUTHENTICATOR_ID, + + /** + * The HAL is processing the ISession#resetLockout request. + */ RESETTING_LOCKOUT } diff --git a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp index 4651f25879..30117862ee 100644 --- a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp +++ b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp @@ -60,8 +60,8 @@ class SessionCallback : public BnSessionCallback { return ndk::ScopedAStatus::ok(); } - ndk::ScopedAStatus onEnrollmentProgress(int32_t /*enrollmentId*/, int32_t /*remaining*/, - int32_t /*vendorCode*/) override { + ndk::ScopedAStatus onEnrollmentProgress(int32_t /*enrollmentId*/, + int32_t /*remaining*/) override { return ndk::ScopedAStatus::ok(); } From 8b3cd5db216becb73b63834bc369a28bd39830d2 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Mon, 21 Sep 2020 17:03:18 -0700 Subject: [PATCH 3/4] Finish remainder of documentation. Note that this doesn't mean documentation is done, it just means that previously undocumented areas now at least have some documentation. Bug: 168843220 Test: Builds Change-Id: I92db9b228d46b3925d3f7ae56698f7c52a0ae1bf --- .../biometrics/fingerprint/AcquiredInfo.aidl | 36 ++++++ .../fingerprint/ILockoutCallback.aidl | 12 +- .../biometrics/fingerprint/ISession.aidl | 111 +++++++++++++++++- .../fingerprint/ISessionCallback.aidl | 75 +++++++++++- 4 files changed, 225 insertions(+), 9 deletions(-) diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl index 8cb78339c4..a3259f6916 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl @@ -19,13 +19,49 @@ package android.hardware.biometrics.fingerprint; @VintfStability @Backing(type="byte") enum AcquiredInfo { + /** + * A high quality fingerprint image was detected, no further user interaction is necessary. + */ GOOD, + + /** + * Not enough of a fingerprint was detected. Reposition the finger, or a longer swipe needed. + */ PARTIAL, + + /** + * Image doesn't contain enough detail for recognition. + */ INSUFFICIENT, + + /** + * The sensor needs to be cleaned. + */ SENSOR_DIRTY, + + /** + * For swipe-type sensors, the swipe was too slow and not enough data was collected. + */ TOO_SLOW, + + /** + * For swipe-type sensors, the swipe was too fast and not enough data was collected. + */ TOO_FAST, + + /** + * This message represents the earliest message sent at the beginning of the authentication + * pipeline. It is expected to be used to measure latency. For example, in a camera-based + * authentication system it's expected to be sent prior to camera initialization. Note this + * should be sent whenever authentication is started or restarted. The framework may measure + * latency based on the time between the last START message and the onAuthenticated callback. + */ START, + + /** + * Vendor-specific acquisition message. See ISessionCallback#onAcquired vendorCode + * documentation. + */ VENDOR } diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl index 4b31a38e52..43cb20ffce 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl @@ -22,9 +22,9 @@ oneway interface ILockoutCallback { * Notifies the framework that the user has just entered the Error::LOCKOUT state. This must be * sent in the following scenarios: * 1) The user just attempted authentication and was rejected, resulting in a timed lockout. - * 2) The framework just created a session for a sensorId/userId pair that has not been + * 2) The framework just created a session for a (sensorId, userId) pair that has not been * created since the HAL started (e.g. there is no active or idle session for this - * sensorId/userId pair. + * (sensorId, userId) pair. * * @param sensorId Sensor for which the user is locked out. * @param userId User for which the sensor is locked out. @@ -36,9 +36,9 @@ oneway interface ILockoutCallback { * Notifies the framework that the user has just entered the Error::LOCKOUT_PERMANENT state. * This must be sent in the following scenarios: * 1) The user just attempted authentication and was rejected, resulting in a permanent lockout. - * 2) The framework just created a session for a sensorId/userId pair that has not been + * 2) The framework just created a session for a (sensorId, userId) pair that has not been * created since the HAL started (e.g. there is no active or idle session for this - * sensorId/userId pair. + * (sensorId, userId) pair. * * @param sensorId Sensor for which the user is locked out. * @param userId User for which the sensor is locked out. @@ -46,11 +46,13 @@ oneway interface ILockoutCallback { void onLockoutPermanent(in int sensorId, in int userId); /** - * Notifies the framework that lockout has been cleared for this sensorId/userId pair. This + * Notifies the framework that lockout has been cleared for this (sensorId, userId) pair. This * can happen in the following scenarios: * 1) A timed lockout has ended (e.g. original durationMillis specified in #onLockoutTimed * has expired. * 2) See ISession#resetLockout. + * 3) The (sensorId, userId) pair is not in any lockout state, and the user successfully + * authenticated with a fingerprint. * * @param sensorId Sensor for which the user's lockout is cleared. * @param userId User for the sensor's lockout is cleared. diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl index 5fa56e012c..946027b5f1 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl @@ -80,7 +80,7 @@ interface ISession { * * When a finger is successfully added and before the framework is notified * of remaining=0, the implementation MUST update and associate this - * (sensorId, user) pair with a new new entropy-encoded random identifier. + * (sensorId, userId) pair with a new new entropy-encoded random identifier. * See ISession#getAuthenticatorId for more information. * * @param cookie An identifier used to track subsystem operations related @@ -147,10 +147,75 @@ interface ISession { */ ICancellationSignal authenticate(in int cookie, in long operationId); + /** + * detectInteraction: + * + * A request to start looking for fingerprints without performing matching. + * + * Once the HAL is able to start processing this request, it must notify the framework via + * ISessionCallback#onStateChanged with SessionState::DETECTING_INTERACTION. + * + * The framework will use this method in cases where determing user presence is required, but + * identifying/authentication is not. For example, when the device is encrypted (first boot) or + * in lockdown mode. + * + * At any point during detectInteraction, if a non-recoverable error occurs, the HAL must notify + * the framework via ISessionCallback#onError with the applicable error, and then send + * ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no subsequent operation is + * in the queue. + * + * The implementation must only check for a fingerprint-like image was detected (e.g. to + * minimize interactions due to non-fingerprint objects), and the lockout counter must not + * be modified. + * + * Upon detecting any fingerprint, the implementation must invoke + * ISessionCallback#onInteractionDetected. + * + * The lifecycle of this operation ends when either + * 1) Any fingerprint is detected and the framework is notified via + * ISessionCallback#onInteractiondetected + * 2) The operation was cancelled by the framework (see ICancellationSignal) + * 3) The HAL ends the operation, for example when a subsequent operation pre-empts this one. + * + * Note that if the operation is canceled, the implementation must notify the framework via + * ISessionCallback#onError with Error::CANCELED. + * + * @param cookie An identifier used to track subsystem operations related to this call path. + * The framework will guarantee that it is unique per ISession. + */ ICancellationSignal detectInteraction(in int cookie); + /* + * enumerateEnrollments: + * + * A request to enumerate (list) the enrollments for this (sensorId, userId) pair. The + * framework typically uses this to ensure that its cache is in sync with the HAL. + * + * Once the HAL is able to start processing this request, it must notify the framework via + * ISessionCallback#onStateChanged with SessionState::ENUMERATING_ENROLLMENTS. + * + * The implementation must then notify the framework with a list of enrollments applicable + * for the current session via ISessionCallback#onEnrollmentsEnumerated. + * + * @param cookie An identifier used to track subsystem operations related to this call path. + * The framework will guarantee that it is unique per ISession. + */ void enumerateEnrollments(in int cookie); + /** + * removeEnrollments: + * + * A request to remove the enrollments for this (sensorId, userId) pair. + * + * Once the HAL is able to start processing this request, it must notify the framework via + * ISessionCallback#onStateChanged with SessionState::REMOVING_ENROLLMENTS. + * + * After removing the enrollmentIds from everywhere necessary (filesystem, secure subsystems, + * etc), the implementation must notify the framework via ISessionCallback#onEnrollmentsRemoved. + * + * @param cookie An identifier used to track subsystem operations related to this call path. + * The framework will guarantee that it is unique per ISession. + */ void removeEnrollments(in int cookie, in int[] enrollmentIds); /** @@ -259,10 +324,54 @@ interface ISession { * Methods for notifying the under-display fingerprint sensor about external events. */ + /** + * onPointerDown: + * + * This method only applies to sensors that are configured as + * FingerprintSensorType::UNDER_DISPLAY_*. If invoked erroneously by the framework for sensors + * of other types, the HAL must treat this as a no-op and return immediately. + * + * For sensors of type FingerprintSensorType::UNDER_DISPLAY_*, this method is used to notify the + * HAL of display touches. This method can be invoked when the session is in one of the + * following states: SessionState::ENROLLING, SessionState::AUTHENTICATING, or + * SessionState::DETECTING_INTERACTION. + * + * Note that the framework will only invoke this method if the event occurred on the display + * on which this sensor is located. + * + * Note that for sensors which require illumination such as + * FingerprintSensorType::UNDER_DISPLAY_OPTICAL, and where illumination is handled below + * the framework, this is a good time to start illuminating. + * + * @param pointerId See android.view.MotionEvent#getPointerId + * @param x The distance in pixels from the left edge of the display. + * @param y The distance in pixels from the top edge of the display. + * @param minor See android.view.MotionEvent#getTouchMinor + * @param major See android.view.MotionEvent#getTouchMajor + */ void onPointerDown(in int pointerId, in int x, in int y, in float minor, in float major); + /** + * onPointerUp: + * + * This method only applies to sensors that are configured as + * FingerprintSensorType::UNDER_DISPLAY_*. If invoked for sensors of other types, the HAL must + * treat this as a no-op and return immediately. + * + * @param pointerId See android.view.MotionEvent#getPointerId + */ void onPointerUp(in int pointerId); + /* + * onUiReady: + * + * This method only applies to sensors that are configured as + * FingerprintSensorType::UNDER_DISPLAY_OPTICAL. If invoked for sensors of other types, the HAL + * must treat this as a no-op and return immediately. + * + * For FingerprintSensorType::UNDER_DISPLAY_OPTICAL where illumination is handled above the + * HAL, the framework will invoke this method to notify that the illumination has started. + */ void onUiReady(); } diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl index 7130520ca6..81a87a8290 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl @@ -23,14 +23,48 @@ import android.hardware.keymaster.HardwareAuthToken; @VintfStability interface ISessionCallback { + /** + * Used to notify the framework of session state changes. See ISession for more information. + */ void onStateChanged(in int cookie, in SessionState state); + /** + * This method must only be used to notify the framework during the following states: + * 1) SessionState::ENROLLING + * 2) SessionState::AUTHENTICATING + * 3) SessionState::DETECTING_INTERACTION + * + * These messages may be used to provide user guidance multiple times if necessary per + * operation. + * + * @param info See the AcquiredInfo enum. + * @param vendorCode Only valid if info == AcquiredInfo::VENDOR. + */ void onAcquired(in AcquiredInfo info, in int vendorCode); + /** + * This method must only be used to notify the framework during the following states: + * 1) SessionState::ENROLLING + * 2) SessionState::AUTHENTICATING + * 3) SessionState::DETECTING_INTERACTION + * 4) SessionState::INVALIDATING_AUTHENTICATOR_ID + * 5) SessionState::RESETTING_LOCKOUT + * + * These messages may be used to notify the framework or user that a non-recoverable error + * has occurred. The operation is finished, and the HAL must proceed with the next operation + * or return to SessionState::IDLING if the queue is empty. + * + * Note that cancellation (see common::ICancellationSignal) and preemption most be followed with + * an Error::CANCELED message. + * + * @param error See the Error enum. + * @param vendorCode Only valid if error == Error::VENDOR. + */ void onError(in Error error, in int vendorCode); /** - * Used to notify the framework of enrollment progress. Enrollment completes when remaining==0, + * This method must only be used to notify the framework during the following state: + * 1) SessionState::ENROLLING * * @param enrollmentId Unique stable identifier for the enrollment that's being added by this * ISession#enroll invocation. @@ -39,6 +73,8 @@ interface ISessionCallback { void onEnrollmentProgress(in int enrollmentId, int remaining); /** + * This method must only be used to notify the framework during SessionState::AUTHENTICATING. + * * Used to notify the framework upon successful authentication. Note that the authentication * lifecycle ends when either 1) a fingerprint is accepted, or 2) an error such as * Error::LOCKOUT occurred. The authentication lifecycle does NOT end when a fingerprint is @@ -53,6 +89,8 @@ interface ISessionCallback { void onAuthenticationSucceeded(in int enrollmentId, in HardwareAuthToken hat); /** + * This method must only be used to notify the framework during SessionState::AUTHENTICATING. + * * Used to notify the framework upon rejected attempts. Note that the authentication * lifecycle ends when either 1) a fingerprint is accepted, or 2) an error such as * Error::LOCKOUT occurred. The authentication lifecycle does NOT end when a fingerprint is @@ -60,19 +98,50 @@ interface ISessionCallback { */ void onAuthenticationFailed(); + /** + * This method must only be used to notify the framework during + * SessionState::DETECTING_INTERACTION + * + * Notifies the framework that user interaction occurred. See ISession#detectInteraction. + */ void onInteractionDetected(); + /** + * This method must only be used to notify the framework during + * SessionState::ENUMERATING_ENROLLMENTS. + * + * Notifies the framework of the current enrollments. See ISession#enumerateEnrollments. + * + * @param enrollmentIds A list of enrollments for the session's (userId, sensorId) pair. + */ void onEnrollmentsEnumerated(in int[] enrollmentIds); + /** + * This method must only be used to notify the framework during + * SessionState::REMOVING_ENROLLMENTS. + * + * Notifies the framework that the specified enrollments are removed. + * + * @param enrollmentIds The enrollments that were removed. + */ void onEnrollmentsRemoved(in int[] enrollmentIds); /** - * A callback invoked when ISession#getAuthenticatorId is invoked. + * This method must only be used to notify the framework during + * SessionState::GETTING_AUTHENTICATOR_ID. + * + * Notifies the framework with the authenticatorId corresponding to this session's + * (userId, sensorId) pair. + * + * @param authenticatorId See the above documentation. */ void onAuthenticatorIdRetrieved(in long authenticatorId); /** - * A callback invoked when ISession#invalidateAuthenticatorId has completed. + * This method must only be used to notify the framework during + * SessionState::INVALIDATING_AUTHENTICATOR_ID. + * + * See ISession#invalidateAuthenticatorId for more information. */ void onAuthenticatorIdInvalidated(); } From ef79d661ba73f7472557b9d48f3cd5b0f84cec69 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Tue, 22 Sep 2020 12:14:44 -0700 Subject: [PATCH 4/4] Move lockout callbacks to ISessionCallback Also fixes backward compatibility for AcquiredInfo and Error constants. For lockout-related changes: 1) If a session doesn't exist, it means the framework (or higher) doesn't care about its lockout state. 2) This allows the ISession#authenticate lifecycle to be clearer, e.g. no need for ILockoutCallback#onLockoutTimed followed by ISessionCallback#onError(LOCKOUT) Bug: 168842956 Bug: 168843220 Test: make -j android.hardware.biometrics.fingerprint-update-api Test: make -j Test: make -j VtsHalBiometricsFingerprintTargetTest Change-Id: I0b7e7ab3b89d0d1d7647535af07766c493a2067b --- .../biometrics/fingerprint/AcquiredInfo.aidl | 4 +- .../biometrics/fingerprint/Error.aidl | 14 +-- .../biometrics/fingerprint/IFingerprint.aidl | 1 - .../fingerprint/ILockoutCallback.aidl | 24 ---- .../fingerprint/ISessionCallback.aidl | 3 + .../biometrics/fingerprint/AcquiredInfo.aidl | 12 +- .../biometrics/fingerprint/Error.aidl | 27 +++-- .../biometrics/fingerprint/IFingerprint.aidl | 31 ----- .../fingerprint/ILockoutCallback.aidl | 62 ---------- .../biometrics/fingerprint/ISession.aidl | 114 ++++++++++-------- .../fingerprint/ISessionCallback.aidl | 49 +++++++- .../fingerprint/aidl/default/Fingerprint.cpp | 5 - .../fingerprint/aidl/default/Fingerprint.h | 3 - .../VtsHalBiometricsFingerprintTargetTest.cpp | 12 ++ 14 files changed, 152 insertions(+), 209 deletions(-) delete mode 100644 biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl delete mode 100644 biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl index 329a35dc49..df30dcae47 100644 --- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl @@ -24,6 +24,6 @@ enum AcquiredInfo { SENSOR_DIRTY = 3, TOO_SLOW = 4, TOO_FAST = 5, - START = 6, - VENDOR = 7, + VENDOR = 6, + START = 7, } diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl index 0298c126c4..6bd71b2d34 100644 --- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl @@ -18,13 +18,11 @@ package android.hardware.biometrics.fingerprint; @Backing(type="byte") @VintfStability enum Error { - HW_UNAVAILABLE = 0, - UNABLE_TO_PROCESS = 1, - TIMEOUT = 2, - NO_SPACE = 3, - CANCELED = 4, - UNABLE_TO_REMOVE = 5, - LOCKOUT = 6, - LOCKOUT_PERMANENT = 7, + HW_UNAVAILABLE = 1, + UNABLE_TO_PROCESS = 2, + TIMEOUT = 3, + NO_SPACE = 4, + CANCELED = 5, + UNABLE_TO_REMOVE = 6, VENDOR = 8, } diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl index 9cbf343181..6ca6d16eb3 100644 --- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl @@ -20,7 +20,6 @@ package android.hardware.biometrics.fingerprint; interface IFingerprint { android.hardware.biometrics.fingerprint.SensorProps[] getSensorProps(); android.hardware.biometrics.fingerprint.ISession createSession(in int sensorId, in int userId, in android.hardware.biometrics.fingerprint.ISessionCallback cb); - void setLockoutCallback(in android.hardware.biometrics.fingerprint.ILockoutCallback cb); void generateChallenge(in int sensorId, in int userId, in int timeoutSec, in android.hardware.biometrics.fingerprint.IGenerateChallengeCallback cb); void revokeChallenge(in int sensorId, in int userId, in long challenge, in android.hardware.biometrics.fingerprint.IRevokeChallengeCallback cb); } diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl deleted file mode 100644 index 88aabbf487..0000000000 --- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl +++ /dev/null @@ -1,24 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // -/////////////////////////////////////////////////////////////////////////////// - -// This file is a snapshot of an AIDL interface (or parcelable). Do not try to -// edit this file. It looks like you are doing that because you have modified -// an AIDL interface in a backward-incompatible way, e.g., deleting a function -// from an interface or a field from a parcelable and it broke the build. That -// breakage is intended. -// -// You must not make a backward incompatible changes to the AIDL files built -// with the aidl_interface module type with versions property set. The module -// type is used to build AIDL files in a way that they can be used across -// independently updatable components of the system. If a device is shipped -// with such a backward incompatible change, it has a high risk of breaking -// later when a module using the interface is updated, e.g., Mainline modules. - -package android.hardware.biometrics.fingerprint; -@VintfStability -interface ILockoutCallback { - oneway void onLockoutTimed(in int sensorId, in int userId, in long durationMillis); - oneway void onLockoutPermanent(in int sensorId, in int userId); - oneway void onLockoutCleared(in int sensorId, in int userId); -} diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl index cbac890442..74ec07774c 100644 --- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl +++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl @@ -24,6 +24,9 @@ interface ISessionCallback { void onEnrollmentProgress(in int enrollmentId, int remaining); void onAuthenticationSucceeded(in int enrollmentId, in android.hardware.keymaster.HardwareAuthToken hat); void onAuthenticationFailed(); + void onLockoutTimed(in long durationMillis); + void onLockoutPermanent(); + void onLockoutCleared(); void onInteractionDetected(); void onEnrollmentsEnumerated(in int[] enrollmentIds); void onEnrollmentsRemoved(in int[] enrollmentIds); diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl index a3259f6916..adb1c78cb2 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl @@ -49,6 +49,12 @@ enum AcquiredInfo { */ TOO_FAST, + /** + * Vendor-specific acquisition message. See ISessionCallback#onAcquired vendorCode + * documentation. + */ + VENDOR, + /** * This message represents the earliest message sent at the beginning of the authentication * pipeline. It is expected to be used to measure latency. For example, in a camera-based @@ -57,11 +63,5 @@ enum AcquiredInfo { * latency based on the time between the last START message and the onAuthenticated callback. */ START, - - /** - * Vendor-specific acquisition message. See ISessionCallback#onAcquired vendorCode - * documentation. - */ - VENDOR } diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl index da5ee18686..014a4c032a 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl @@ -19,11 +19,16 @@ package android.hardware.biometrics.fingerprint; @VintfStability @Backing(type="byte") enum Error { + /** + * Used for testing, and to keep subsequent numbering consistent with older HIDLs. + */ + // NO_ERROR = 0, + /** * A hardware error has occurred that cannot be resolved. For example, I2C failure or a broken * sensor. */ - HW_UNAVAILABLE, + HW_UNAVAILABLE = 1, /** * The implementation is unable to process the request. For example, invalid arguments were @@ -53,21 +58,19 @@ enum Error { UNABLE_TO_REMOVE, /** - * Authentication is locked out due to too many unsuccessful attempts. This is a rate-limiting - * lockout, and authentication can be restarted after a period of time. See the Android CDD for - * the full set of lockout and rate-limiting requirements. + * Reserved to maintain backwards compatibility. See ISessionCallback#onLockoutTimed instead. */ - LOCKOUT, - - /** - * Authenticatio nis disabled until the user unlocks with their device credential - * (PIN/Pattern/Password). See ISession#resetLockout. - */ - LOCKOUT_PERMANENT, + // LOCKOUT = 7, /** * Used to enable vendor-specific error messages. */ - VENDOR, + VENDOR = 8, + + /** + * Reserved to maintain backwards compatibility. See ISessionCallback#onLockoutPermanent + * instead. + */ + // LOCKOUT_PERMANENT = 9, } diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl index 57319b2906..0c8ebc534b 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl @@ -17,7 +17,6 @@ package android.hardware.biometrics.fingerprint; import android.hardware.biometrics.fingerprint.IGenerateChallengeCallback; -import android.hardware.biometrics.fingerprint.ILockoutCallback; import android.hardware.biometrics.fingerprint.IRevokeChallengeCallback; import android.hardware.biometrics.fingerprint.ISession; import android.hardware.biometrics.fingerprint.ISessionCallback; @@ -72,36 +71,6 @@ interface IFingerprint { */ ISession createSession(in int sensorId, in int userId, in ISessionCallback cb); - /** - * setLockoutCallback: - * - * Sets a callback to notify the framework lockout changes. Note - * that lockout is user AND sensor specific. In other words, there is a - * separate lockout state for each (user, sensor) pair. For example, the - * following is a valid state on a multi-sensor device: - * ------------------------------------------------------------------ - * | SensorId | UserId | FailedAttempts | LockedOut | LockedUntil | - * |----------|--------|----------------|-----------|---------------| - * | 0 | 0 | 1 | false | x | - * | 1 | 0 | 5 | true | | - * | 0 | 10 | 0 | false | x | - * | 1 | 10 | 0 | false | x | - * ------------------------------------------------------------------ - * - * Lockout may be cleared in the following ways: - * 1) ISession#resetLockout - * 2) After a period of time, according to a rate-limiter. - * - * In addition, lockout states MUST persist after device reboots, HAL - * crashes, etc. - * - * See the Android CDD section 7.3.10 for the full set of lockout and - * rate-limiting requirements. - * - * @param cb Used to notify the framework of lockout changes. - */ - void setLockoutCallback(in ILockoutCallback cb); - /** * generateChallenge: * diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl deleted file mode 100644 index 43cb20ffce..0000000000 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware.biometrics.fingerprint; - -@VintfStability -oneway interface ILockoutCallback { - /** - * Notifies the framework that the user has just entered the Error::LOCKOUT state. This must be - * sent in the following scenarios: - * 1) The user just attempted authentication and was rejected, resulting in a timed lockout. - * 2) The framework just created a session for a (sensorId, userId) pair that has not been - * created since the HAL started (e.g. there is no active or idle session for this - * (sensorId, userId) pair. - * - * @param sensorId Sensor for which the user is locked out. - * @param userId User for which the sensor is locked out. - * @param durationMillis Remaining duration of the lockout. - */ - void onLockoutTimed(in int sensorId, in int userId, in long durationMillis); - - /** - * Notifies the framework that the user has just entered the Error::LOCKOUT_PERMANENT state. - * This must be sent in the following scenarios: - * 1) The user just attempted authentication and was rejected, resulting in a permanent lockout. - * 2) The framework just created a session for a (sensorId, userId) pair that has not been - * created since the HAL started (e.g. there is no active or idle session for this - * (sensorId, userId) pair. - * - * @param sensorId Sensor for which the user is locked out. - * @param userId User for which the sensor is locked out. - */ - void onLockoutPermanent(in int sensorId, in int userId); - - /** - * Notifies the framework that lockout has been cleared for this (sensorId, userId) pair. This - * can happen in the following scenarios: - * 1) A timed lockout has ended (e.g. original durationMillis specified in #onLockoutTimed - * has expired. - * 2) See ISession#resetLockout. - * 3) The (sensorId, userId) pair is not in any lockout state, and the user successfully - * authenticated with a fingerprint. - * - * @param sensorId Sensor for which the user's lockout is cleared. - * @param userId User for the sensor's lockout is cleared. - */ - void onLockoutCleared(in int sensorId, in int userId); -} - diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl index 946027b5f1..d0f546a41f 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl @@ -95,55 +95,46 @@ interface ISession { * * A request to start looking for fingerprints to authenticate. * - * Once the HAL is able to start processing the authentication request, it must - * notify framework via ISessionCallback#onStateChanged with - * SessionState::AUTHENTICATING. + * Once the HAL is able to start processing the authentication request, it must notify framework + * via ISessionCallback#onStateChanged with SessionState::AUTHENTICATING. * - * At any point during authentication, if a non-recoverable error occurs, - * the HAL must notify the framework via ISessionCallback#onError with - * the applicable authentication-specific error, and then send - * ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no + * At any point during authentication, if a non-recoverable error occurs, the HAL must notify + * the framework via ISessionCallback#onError with the applicable authentication-specific error, + * and then send ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no * subsequent operation is in the queue. * - * During authentication, the implementation may notify the framework - * via ISessionCallback#onAcquired with messages that may be used to guide - * the user. This callback can be invoked multiple times if necessary. + * During authentication, the implementation may notify the framework via + * ISessionCallback#onAcquired with messages that may be used to guide the user. This callback + * can be invoked multiple times if necessary. * - * The HAL must notify the framework of accepts/rejects via - * ISessionCallback#onAuthentication*. + * The HAL must notify the framework of accepts/rejects via ISessionCallback#onAuthentication*. * * The authentication lifecycle ends when either - * 1) A fingerprint is accepted, and ISessionCallback#onAuthenticationSucceeded - * is invoked, or - * 2) Any non-recoverable error occurs (such as lockout). See the full - * list of authentication-specific errors in the Error enum. + * 1) A fingerprint is accepted, and ISessionCallback#onAuthenticationSucceeded is invoked, or + * 2) Any non-recoverable error occurs (such as lockout). See the full list of + * authentication-specific errors in the Error enum. * - * Note that it is now the HAL's responsibility to keep track of lockout - * states. See IFingerprint#setLockoutCallback and ISession#resetLockout. + * Note that upon successful authentication, the lockout counter for this (sensorId, userId) + * pair must be cleared. * - * Note that upon successful authentication, ONLY sensors configured as - * SensorStrength::STRONG are allowed to create and send a - * HardwareAuthToken to the framework. See the Android CDD for more - * details. For SensorStrength::STRONG sensors, the HardwareAuthToken's - * "challenge" field must be set with the operationId passed in during - * #authenticate. If the sensor is NOT SensorStrength::STRONG, the - * HardwareAuthToken MUST be null. + * Note that upon successful authentication, ONLY sensors configured as SensorStrength::STRONG + * are allowed to create and send a HardwareAuthToken to the framework. See the Android CDD for + * more details. For SensorStrength::STRONG sensors, the HardwareAuthToken's "challenge" field + * must be set with the operationId passed in during #authenticate. If the sensor is NOT + * SensorStrength::STRONG, the HardwareAuthToken MUST be null. * - * @param cookie An identifier used to track subsystem operations related - * to this call path. The client must guarantee that it is - * unique per ISession. - * @param operationId For sensors configured as SensorStrength::STRONG, - * this must be used ONLY upon successful authentication - * and wrapped in the HardwareAuthToken's "challenge" - * field and sent to the framework via - * ISessionCallback#onAuthenticated. The operationId is - * an opaque identifier created from a separate secure - * subsystem such as, but not limited to KeyStore/KeyMaster. - * The HardwareAuthToken can then be used as an attestation - * for the provided operation. For example, this is used + * @param cookie An identifier used to track subsystem operations related to this call path. The + * client must guarantee that it is unique per ISession. + * @param operationId For sensors configured as SensorStrength::STRONG, this must be used ONLY + * upon successful authentication and wrapped in the HardwareAuthToken's + * "challenge" field and sent to the framework via + * ISessionCallback#onAuthenticated. The operationId is an opaque identifier + * created from a separate secure subsystem such as, but not limited to + * KeyStore/KeyMaster. The HardwareAuthToken can then be used as an + * attestation for the provided operation. For example, this is used * to unlock biometric-bound auth-per-use keys (see - * setUserAuthenticationParameters in - * KeyGenParameterSpec.Builder and KeyProtection.Builder. + * setUserAuthenticationParameters in KeyGenParameterSpec.Builder and + * KeyProtection.Builder. */ ICancellationSignal authenticate(in int cookie, in long operationId); @@ -300,17 +291,43 @@ interface ISession { /** * resetLockout: * - * Requests the implementation to clear the lockout counter. Upon receiving - * this request, the implementation must perform the following: + * Requests the implementation to clear the lockout counter. Upon receiving this request, the + * implementation must perform the following: * 1) Verify the authenticity and integrity of the provided HAT - * 2) Verify that the timestamp provided within the HAT is relatively - * recent (e.g. on the order of minutes, not hours). - * If either of the checks fail, the HAL must invoke ISessionCallback#onError - * with Error::UNABLE_TO_PROCESS and return to SessionState::IDLING - * if no subsequent work is in the queue. + * 2) Verify that the timestamp provided within the HAT is relatively recent (e.g. on the + * order of minutes, not hours). + * If either of the checks fail, the HAL must invoke ISessionCallback#onError with + * Error::UNABLE_TO_PROCESS and return to SessionState::IDLING if no subsequent work is in the + * queue. * - * Upon successful verification, the HAL must clear the lockout counter - * and notify the framework via ILockoutCallback#onLockoutChanged(sensorId, userId, 0). + * Upon successful verification, the HAL must clear the lockout counter and notify the framework + * via ISessionCallback#onLockoutCleared. + * + * Note that lockout is user AND sensor specific. In other words, there is a separate lockout + * state for each (user, sensor) pair. For example, the following is a valid state on a + * multi-sensor device: + * ------------------------------------------------------------------ + * | SensorId | UserId | FailedAttempts | LockedOut | LockedUntil | + * |----------|--------|----------------|-----------|---------------| + * | 0 | 0 | 1 | false | x | + * | 1 | 0 | 5 | true | | + * | 0 | 10 | 0 | false | x | + * | 1 | 10 | 0 | false | x | + * ------------------------------------------------------------------ + * + * Lockout may be cleared in the following ways: + * 1) ISession#resetLockout + * 2) After a period of time, according to a rate-limiter. + * + * Note that the "FailedAttempts" counter must be cleared upon successful fingerprint + * authentication. For example, if SensorId=0 UserId=0 FailedAttempts=1, and a successful + * fingerprint authentication occurs, the counter for that (SensorId, UserId) pair must be reset + * to 0. + * + * In addition, lockout states MUST persist after device reboots, HAL crashes, etc. + * + * See the Android CDD section 7.3.10 for the full set of lockout and rate-limiting + * requirements. * * @param cookie An identifier used to track subsystem operations related * to this call path. The client must guarantee that it is @@ -319,7 +336,6 @@ interface ISession { */ void resetLockout(in int cookie, in HardwareAuthToken hat); - /** * Methods for notifying the under-display fingerprint sensor about external events. */ diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl index 81a87a8290..33a93e59b4 100644 --- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl +++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl @@ -76,9 +76,8 @@ interface ISessionCallback { * This method must only be used to notify the framework during SessionState::AUTHENTICATING. * * Used to notify the framework upon successful authentication. Note that the authentication - * lifecycle ends when either 1) a fingerprint is accepted, or 2) an error such as - * Error::LOCKOUT occurred. The authentication lifecycle does NOT end when a fingerprint is - * rejected. + * lifecycle ends when either 1) a fingerprint is accepted, or 2) an error occurred. The + * authentication lifecycle does NOT end when a fingerprint is rejected. * * @param enrollmentId Fingerprint that was accepted. * @param hat If the sensor is configured as SensorStrength::STRONG, a non-null attestation that @@ -92,12 +91,50 @@ interface ISessionCallback { * This method must only be used to notify the framework during SessionState::AUTHENTICATING. * * Used to notify the framework upon rejected attempts. Note that the authentication - * lifecycle ends when either 1) a fingerprint is accepted, or 2) an error such as - * Error::LOCKOUT occurred. The authentication lifecycle does NOT end when a fingerprint is - * rejected. + * lifecycle ends when either 1) a fingerprint is accepted, or 2) an occurred. The + * authentication lifecycle does NOT end when a fingerprint is rejected. */ void onAuthenticationFailed(); + /** + * This method must only be used to notify the framework during SessionState::AUTHENTICATING. + * + * Authentication is locked out due to too many unsuccessful attempts. This is a rate-limiting + * lockout, and authentication can be restarted after a period of time. See + * ISession#resetLockout. + * + * @param sensorId Sensor for which the user is locked out. + * @param userId User for which the sensor is locked out. + * @param durationMillis Remaining duration of the lockout. + */ + void onLockoutTimed(in long durationMillis); + + /** + * This method must only be used to notify the framework during SessionState::AUTHENTICATING. + * + * Authentication is disabled until the user unlocks with their device credential + * (PIN/Pattern/Password). See ISession#resetLockout. + * + * @param sensorId Sensor for which the user is locked out. + * @param userId User for which the sensor is locked out. + */ + void onLockoutPermanent(); + + /** + * Notifies the framework that lockout has been cleared for this (sensorId, userId) pair. + * + * Note that this method can be used to notify the framework during any state. + * + * Lockout can be cleared in the following scenarios: + * 1) A timed lockout has ended (e.g. durationMillis specified in previous #onLockoutTimed + * has expired. + * 2) See ISession#resetLockout. + * + * @param sensorId Sensor for which the user's lockout is cleared. + * @param userId User for the sensor's lockout is cleared. + */ + void onLockoutCleared(); + /** * This method must only be used to notify the framework during * SessionState::DETECTING_INTERACTION diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp index b3bd4e7a29..b907bf1d31 100644 --- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp +++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp @@ -61,11 +61,6 @@ ndk::ScopedAStatus Fingerprint::createSession(int32_t /*sensorId*/, int32_t /*us return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus Fingerprint::setLockoutCallback( - const std::shared_ptr& /*cb*/) { - return ndk::ScopedAStatus::ok(); -} - ndk::ScopedAStatus Fingerprint::generateChallenge( int32_t /*sensorId*/, int32_t /*userId*/, int32_t /*timeoutSec*/, const std::shared_ptr& /*cb*/) { diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.h b/biometrics/fingerprint/aidl/default/Fingerprint.h index 463d07db13..59cdd441fc 100644 --- a/biometrics/fingerprint/aidl/default/Fingerprint.h +++ b/biometrics/fingerprint/aidl/default/Fingerprint.h @@ -28,9 +28,6 @@ class Fingerprint : public BnFingerprint { const std::shared_ptr& cb, std::shared_ptr* _aidl_return) override; - ndk::ScopedAStatus setLockoutCallback( - const std::shared_ptr& cb) override; - ndk::ScopedAStatus generateChallenge( int32_t sensorId, int32_t userId, int32_t timeoutSec, const std::shared_ptr& cb) override; diff --git a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp index 30117862ee..496badc741 100644 --- a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp +++ b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp @@ -74,6 +74,18 @@ class SessionCallback : public BnSessionCallback { return ndk::ScopedAStatus::ok(); } + ndk::ScopedAStatus onLockoutTimed(int64_t /*durationMillis*/) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onLockoutPermanent() override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus onLockoutCleared() override { + return ndk::ScopedAStatus::ok(); + } + ndk::ScopedAStatus onInteractionDetected() override { return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus onEnrollmentsEnumerated(