Merge "Start adding documentation for IFingerprint"
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 85d1f57..9cbf343 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,7 @@
 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 setResetLockoutCallback(in android.hardware.biometrics.fingerprint.IResetLockoutCallback 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 android.hardware.biometrics.fingerprint.IRevokeChallengeCallback 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/IGenerateChallengeCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl
index eaf27d2..063be60 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl
@@ -18,5 +18,5 @@
 package android.hardware.biometrics.fingerprint;
 @VintfStability
 interface IGenerateChallengeCallback {
-  oneway void onChallengeGenerated(in int sensorId, in int userId, in long keystoreOperationId, in long challenge);
+  oneway void onChallengeGenerated(in int sensorId, in int userId, in long challenge);
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl
similarity index 82%
rename from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
rename to biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl
index ac0decd..88aabbf 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl
@@ -17,6 +17,8 @@
 
 package android.hardware.biometrics.fingerprint;
 @VintfStability
-interface IResetLockoutCallback {
-  oneway void onLockoutReset(in int sensorId, in int userId, in long durationMilli);
+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/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
index 4709778..57319b2 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
@@ -17,7 +17,7 @@
 package android.hardware.biometrics.fingerprint;
 
 import android.hardware.biometrics.fingerprint.IGenerateChallengeCallback;
-import android.hardware.biometrics.fingerprint.IResetLockoutCallback;
+import android.hardware.biometrics.fingerprint.ILockoutCallback;
 import android.hardware.biometrics.fingerprint.IRevokeChallengeCallback;
 import android.hardware.biometrics.fingerprint.ISession;
 import android.hardware.biometrics.fingerprint.ISessionCallback;
@@ -25,13 +25,144 @@
 
 @VintfStability
 interface IFingerprint {
+    /**
+     * getSensorProps:
+     *
+     * @return A list of properties for all sensors that an instance of the
+     * HAL supports.
+     */
     SensorProps[] getSensorProps();
 
+    /**
+     * createSession:
+     *
+     * Creates a session which can then be used by the framework to perform
+     * operations such as enroll, authenticate, etc for the given sensorId
+     * and userId.
+     *
+     * A physical sensor identified by sensorId typically supports only a
+     * single in-flight session at a time. As such, if a session is currently
+     * in a state other than SessionState::IDLING, the HAL MUST finish or
+     * cancel the current operation and return to SessionState::IDLING before
+     * the new session is created. For example:
+     *   1) If a session for sensorId=0, userId=0
+     *      is currently in a cancellable state (see ICancellationSignal) such
+     *      as SessionState::AUTHENTICATING and the framework requests a new
+     *      session for sensorId=0, userId=10, the HAL must end the current
+     *      session with Error::CANCELED, invoke
+     *      ISessionCallback#onStateChanged with SessionState::IDLING, and
+     *      then return a new session for sensorId=0, userId=10.
+     *   2) If a session for sensorId=0, userId=0 is currently in a
+     *      non-cancellable state such as SessionState::REMOVING_ENROLLMENTS,
+     *      and the framework requests a new session for sensorId=0, userId=10,
+     *      the HAL must finish the current operation before invoking
+     *      ISessionCallback#onStateChanged with SessionState::IDLING, and
+     *      return a new session for sensorId=0, userId=10.
+     *
+     * Implementations must store user-specific state or metadata in
+     * /data/vendor_de/<user>/fpdata as specified by the SeLinux policy. This
+     * directory is created/removed by vold (see vold_prepare_subdirs.cpp).
+     * Implementations may store additional user-specific data, such as
+     * embeddings or templates in StrongBox.
+     *
+     * @param sensorId The sensor with which this session is being created.
+     * @param userId The userId with which this session is being created.
+     * @param cb Used to notify the framework.
+     * @return A new session
+     */
     ISession createSession(in int sensorId, in int userId, in ISessionCallback cb);
 
-    void setResetLockoutCallback(in IResetLockoutCallback 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      | <future_time> |
+     * | 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:
+     *
+     * Begins a secure transaction request. Note that the challenge by itself
+     * is not useful. It only becomes useful when wrapped in a verifiable
+     * message such as a HardwareAuthToken.
+     *
+     * Canonical example:
+     *   1) User requests an operation, such as fingerprint enrollment.
+     *   2) Fingerprint enrollment cannot happen until the user confirms
+     *      their lockscreen credential (PIN/Pattern/Password).
+     *   3) However, the biometric subsystem does not want just "any"
+     *      proof of credential confirmation. It needs proof that the
+     *      user explicitly authenticated credential in order to allow
+     *      addition of biometric enrollments.
+     * To secure this path, the following path is taken:
+     *   1) Upon user requesting fingerprint enroll, the framework requests
+     *      IFingerprint#generateChallenge
+     *   2) Framework sends the challenge to the credential subsystem, and upon
+     *      credential confirmation, a HAT is created, containing the challenge
+     *      in the "challenge" field.
+     *   3) Framework sends the HAT to the HAL, e.g. ISession#enroll.
+     *   4) Implementation verifies the authenticity and integrity of the HAT.
+     *   5) Implementation now has confidence that the user entered their
+     *      credential to allow biometric enrollment.
+     *
+     * Note that the interface allows multiple in-flight challenges. For
+     * example, invoking generateChallenge(0, 0, timeoutSec, cb) twice
+     * does not invalidate the first challenge. The challenge is invalidated
+     * only when:
+     *   1) The provided timeout expires, or
+     *   2) IFingerprint#revokeChallenge is invoked
+     *
+     * For example, the following is a possible table of valid challenges:
+     * ----------------------------------------------
+     * | SensorId | UserId | ValidUntil | Challenge |
+     * |----------|--------|------------|-----------|
+     * | 0        | 0      | <Time1>    | <Random1> |
+     * | 0        | 0      | <Time2>    | <Random2> |
+     * | 1        | 0      | <Time3>    | <Random3> |
+     * | 0        | 10     | <Time4>    | <Random4> |
+     * ----------------------------------------------
+     *
+     * @param sensorId Sensor to associate the challenge with
+     * @param userId User to associate the challenge with
+     * @param timeoutSec Duration for which the challenge is valid for
+     * @param cb Callback to notify the framework
+     */
     void generateChallenge(in int sensorId, in int userId, in int timeoutSec, in IGenerateChallengeCallback cb);
 
-    void revokeChallenge(in int sensorId, in int userId, in IRevokeChallengeCallback cb);
+    /**
+     * revokeChallenge:
+     *
+     * Revokes a challenge that was previously generated. Note that if an
+     * invalid combination of parameters is requested, the implementation
+     * must still notify the framework using the provided callback.
+     *
+     * @param sensorId Sensor that the revocation should apply to.
+     * @param userId User that the revocation should apply to.
+     * @param challenge Challenge that should be revoked.
+     * @param cb Used to notify the framework.
+     */
+    void revokeChallenge(in int sensorId, in int userId, in long challenge, in IRevokeChallengeCallback cb);
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl
index 93a2d7b..a51b188 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IGenerateChallengeCallback.aidl
@@ -18,6 +18,9 @@
 
 @VintfStability
 oneway interface IGenerateChallengeCallback {
-    void onChallengeGenerated(in int sensorId, in int userId, in long keystoreOperationId, in long challenge);
+    /**
+     * Notifies the framework when a challenge is successfully generated.
+     */
+    void onChallengeGenerated(in int sensorId, in int userId, in long challenge);
 }
 
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl
new file mode 100644
index 0000000..4b31a38
--- /dev/null
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ILockoutCallback.aidl
@@ -0,0 +1,60 @@
+/*
+ * 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.
+     *
+     * @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/IResetLockoutCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
deleted file mode 100644
index d97a701..0000000
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IResetLockoutCallback.aidl
+++ /dev/null
@@ -1,23 +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 IResetLockoutCallback {
-    void onLockoutReset(in int sensorId, in int userId, in long durationMilli);
-}
-
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IRevokeChallengeCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IRevokeChallengeCallback.aidl
index cca3453..eadba52 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IRevokeChallengeCallback.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IRevokeChallengeCallback.aidl
@@ -18,6 +18,9 @@
 
 @VintfStability
 oneway interface IRevokeChallengeCallback {
+    /**
+     * Notifies the framework when a challenge has been revoked.
+     */
     void onChallengeRevoked(in int sensorId, in int userId, in long challenge);
 }
 
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
index dd340e8..e2d23a6 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -82,12 +82,14 @@
      * The following only applies to sensors that are configured as
      * SensorStrength::STRONG.
      *
-     * When invoked by the framework, the HAL implementation must perform the
+     * When invoked by the framework, the implementation must perform the
      * following sequence of events:
      *   1) Verify the authenticity and integrity of the provided HAT
-     *   2) Update the authenticatorId with a new entropy-encoded random number
-     *   3) Persist the new authenticatorId to non-ephemeral storage
-     *   4) Notify the framework that the above is completed, via
+     *   2) Verify that the timestamp provided within the HAT is relatively
+     *      recent (e.g. on the order of minutes, not hours).
+     *   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
      *      ISessionCallback#onAuthenticatorInvalidated
      *
      * A practical use case of invalidation would be when the user adds a new
@@ -105,6 +107,26 @@
      */
     void invalidateAuthenticatorId(in int cookie, in HardwareAuthToken hat);
 
+    /**
+     * resetLockout:
+     *
+     * 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).
+     *
+     * 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).
+     *
+     * @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 hat HardwareAuthToken See above documentation.
+     */
     void resetLockout(in int cookie, in HardwareAuthToken hat);
 
 
diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
index a1d9d0a..b3bd4e7 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
@@ -61,8 +61,8 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Fingerprint::setResetLockoutCallback(
-        const std::shared_ptr<IResetLockoutCallback>& /*cb*/) {
+ndk::ScopedAStatus Fingerprint::setLockoutCallback(
+        const std::shared_ptr<ILockoutCallback>& /*cb*/) {
     return ndk::ScopedAStatus::ok();
 }
 
@@ -73,7 +73,7 @@
 }
 
 ndk::ScopedAStatus Fingerprint::revokeChallenge(
-        int32_t /*sensorId*/, int32_t /*userId*/,
+        int32_t /*sensorId*/, int32_t /*userId*/, int64_t /*challenge*/,
         const std::shared_ptr<IRevokeChallengeCallback>& /*cb*/) {
     return ndk::ScopedAStatus::ok();
 }
diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.h b/biometrics/fingerprint/aidl/default/Fingerprint.h
index b5b09c0..463d07d 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.h
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.h
@@ -28,15 +28,15 @@
                                      const std::shared_ptr<ISessionCallback>& cb,
                                      std::shared_ptr<ISession>* _aidl_return) override;
 
-    ndk::ScopedAStatus setResetLockoutCallback(
-            const std::shared_ptr<IResetLockoutCallback>& cb) override;
+    ndk::ScopedAStatus setLockoutCallback(
+            const std::shared_ptr<ILockoutCallback>& cb) override;
 
     ndk::ScopedAStatus generateChallenge(
             int32_t sensorId, int32_t userId, int32_t timeoutSec,
             const std::shared_ptr<IGenerateChallengeCallback>& cb) override;
 
     ndk::ScopedAStatus revokeChallenge(
-            int32_t sensorId, int32_t userId,
+            int32_t sensorId, int32_t userId, int64_t challenge,
             const std::shared_ptr<IRevokeChallengeCallback>& cb) override;
 };