Fingerprint virtual HAL checkin (part 3)

- support randomization
- display touch events
- lockout
- cmd and dumpsys

Bug: 230515082
Bug: 230515086
Test: atest FakeFingerprintEngineTest
      atest FakeFingerprintEngineUdfpsTest
      atest --no-bazel-mode VtsHalBiometricsFingerprintTargetTest

Change-Id: Ia5399c86b7fec90b41d426c2f82cb257f4dc9a8a
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
index 32d01f4..a200b39 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -21,6 +21,7 @@
 #include <aidl/android/hardware/biometrics/fingerprint/BnSessionCallback.h>
 
 #include "FakeFingerprintEngine.h"
+#include "util/Util.h"
 
 using namespace ::android::fingerprint::virt;
 using namespace ::aidl::android::hardware::biometrics::fingerprint;
@@ -118,9 +119,9 @@
 class FakeFingerprintEngineTest : public ::testing::Test {
   protected:
     void SetUp() override {
-        FingerprintHalProperties::operation_enroll_latency(0);
-        FingerprintHalProperties::operation_authenticate_latency(0);
-        FingerprintHalProperties::operation_detect_interaction_latency(0);
+        FingerprintHalProperties::operation_enroll_latency({0});
+        FingerprintHalProperties::operation_authenticate_latency({0});
+        FingerprintHalProperties::operation_detect_interaction_latency({0});
         mCallback = ndk::SharedRefBase::make<TestSessionCallback>();
     }
 
@@ -128,6 +129,9 @@
         FingerprintHalProperties::operation_authenticate_error(0);
         FingerprintHalProperties::operation_detect_interaction_error(0);
         FingerprintHalProperties::operation_authenticate_acquired("");
+        FingerprintHalProperties::operation_enroll_latency({});
+        FingerprintHalProperties::operation_authenticate_latency({});
+        FingerprintHalProperties::operation_detect_interaction_latency({});
     }
 
     FakeFingerprintEngine mEngine;
@@ -291,6 +295,7 @@
 }
 
 TEST_F(FakeFingerprintEngineTest, InteractionDetect) {
+    FingerprintHalProperties::detect_interaction(true);
     FingerprintHalProperties::enrollments({1, 2});
     FingerprintHalProperties::enrollment_hit(2);
     FingerprintHalProperties::operation_detect_interaction_acquired("");
@@ -300,6 +305,7 @@
 }
 
 TEST_F(FakeFingerprintEngineTest, InteractionDetectCancel) {
+    FingerprintHalProperties::detect_interaction(true);
     FingerprintHalProperties::enrollments({1, 2});
     FingerprintHalProperties::enrollment_hit(2);
     mCancel.set_value();
@@ -309,6 +315,7 @@
 }
 
 TEST_F(FakeFingerprintEngineTest, InteractionDetectNotSet) {
+    FingerprintHalProperties::detect_interaction(true);
     FingerprintHalProperties::enrollments({1, 2});
     FingerprintHalProperties::enrollment_hit({});
     mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
@@ -323,6 +330,7 @@
 }
 
 TEST_F(FakeFingerprintEngineTest, InteractionDetectError) {
+    FingerprintHalProperties::detect_interaction(true);
     FingerprintHalProperties::operation_detect_interaction_error(8);
     mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
     ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
@@ -331,6 +339,7 @@
 }
 
 TEST_F(FakeFingerprintEngineTest, InteractionDetectAcquired) {
+    FingerprintHalProperties::detect_interaction(true);
     FingerprintHalProperties::enrollments({1, 2});
     FingerprintHalProperties::enrollment_hit(2);
     FingerprintHalProperties::operation_detect_interaction_acquired("4,1013");
@@ -435,12 +444,29 @@
     std::vector<std::string> badStr{"10c",         "100-5",   "100-[5,6,7", "100-5,6,7]",
                                     "100,2x0,300", "200-[f]", "a,b"};
     std::vector<std::vector<int32_t>> ecV;
-    for (const auto s : badStr) {
+    for (const auto& s : badStr) {
         ecV = mEngine.parseEnrollmentCapture(s);
         ASSERT_EQ(ecV.size(), 0);
     }
 }
 
+TEST_F(FakeFingerprintEngineTest, randomLatency) {
+    FingerprintHalProperties::operation_detect_interaction_latency({});
+    ASSERT_EQ(DEFAULT_LATENCY,
+              mEngine.getLatency(FingerprintHalProperties::operation_detect_interaction_latency()));
+    FingerprintHalProperties::operation_detect_interaction_latency({10});
+    ASSERT_EQ(10,
+              mEngine.getLatency(FingerprintHalProperties::operation_detect_interaction_latency()));
+    FingerprintHalProperties::operation_detect_interaction_latency({1, 1000});
+    std::set<int32_t> latencySet;
+    for (int i = 0; i < 100; i++) {
+        latencySet.insert(mEngine.getLatency(
+                FingerprintHalProperties::operation_detect_interaction_latency()));
+    }
+    ASSERT_TRUE(latencySet.size() > 95);
+    FingerprintHalProperties::operation_detect_interaction_latency({});
+}
+
 }  // namespace aidl::android::hardware::biometrics::fingerprint
 
 int main(int argc, char** argv) {
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp
index 7c0021f..f551899 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <aidl/android/hardware/biometrics/fingerprint/BnSessionCallback.h>
 #include <android/binder_process.h>
 #include <fingerprint.sysprop.h>
 #include <gtest/gtest.h>
@@ -29,6 +30,69 @@
 
 namespace aidl::android::hardware::biometrics::fingerprint {
 
+class TestSessionCallback : public BnSessionCallback {
+  public:
+    ndk::ScopedAStatus onChallengeGenerated(int64_t /*challenge*/) override {
+        return ndk::ScopedAStatus::ok();
+    };
+    ::ndk::ScopedAStatus onChallengeRevoked(int64_t /*challenge*/) override {
+        return ndk::ScopedAStatus::ok();
+    };
+    ::ndk::ScopedAStatus onError(fingerprint::Error /*error*/, int32_t /*vendorCode*/) override {
+        return ndk::ScopedAStatus::ok();
+    };
+    ::ndk::ScopedAStatus onEnrollmentProgress(int32_t /*enrollmentId*/,
+                                              int32_t /*remaining*/) override {
+        mEnrollmentProgress++;
+        return ndk::ScopedAStatus::ok();
+    };
+
+    ::ndk::ScopedAStatus onAuthenticationSucceeded(int32_t /*enrollmentId*/,
+                                                   const keymaster::HardwareAuthToken&) override {
+        mAuthenticationSuccess++;
+        return ndk::ScopedAStatus::ok();
+    };
+    ::ndk::ScopedAStatus onAuthenticationFailed() override {
+        mAuthenticationFailure++;
+        return ndk::ScopedAStatus::ok();
+    };
+    ::ndk::ScopedAStatus onInteractionDetected() override {
+        mDetectInteraction++;
+        return ndk::ScopedAStatus::ok();
+    };
+    ndk::ScopedAStatus onAcquired(AcquiredInfo /*info*/, int32_t /*vendorCode*/) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onEnrollmentsEnumerated(
+            const std::vector<int32_t>& /*enrollmentIds*/) override {
+        return ndk::ScopedAStatus::ok();
+    };
+    ::ndk::ScopedAStatus onEnrollmentsRemoved(
+            const std::vector<int32_t>& /*enrollmentIds*/) override {
+        return ndk::ScopedAStatus::ok();
+    };
+    ::ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t /*authenticatorId*/) override {
+        return ndk::ScopedAStatus::ok();
+    };
+    ::ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t /*authenticatorId*/) override {
+        return ndk::ScopedAStatus::ok();
+    };
+    ::ndk::ScopedAStatus onLockoutPermanent() override { return ndk::ScopedAStatus::ok(); };
+    ndk::ScopedAStatus onLockoutTimed(int64_t /* timeout */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
+
+    int32_t getAuthenticationCount() { return mAuthenticationSuccess + mAuthenticationFailure; }
+    int32_t getDetectInteractionCount() { return mDetectInteraction; }
+
+    int32_t mAuthenticationSuccess = 0;
+    int32_t mAuthenticationFailure = 0;
+    int32_t mEnrollmentProgress = 0;
+    int32_t mDetectInteraction = 0;
+};
+
 class FakeFingerprintEngineUdfpsTest : public ::testing::Test {
   protected:
     void SetUp() override {}
@@ -65,30 +129,56 @@
 }
 
 TEST_F(FakeFingerprintEngineUdfpsTest, getSensorLocationBad) {
-    FingerprintHalProperties::sensor_location("");
-    SensorLocation sc = mEngine.getSensorLocation();
-    ASSERT_TRUE(isDefaultLocation(sc));
-
-    auto loc = "100";
-    FingerprintHalProperties::sensor_location(loc);
-    sc = mEngine.getSensorLocation();
-    ASSERT_TRUE(isDefaultLocation(sc));
-
-    loc = "10:20";
-    FingerprintHalProperties::sensor_location(loc);
-    sc = mEngine.getSensorLocation();
-    ASSERT_TRUE(isDefaultLocation(sc));
-
-    loc = "10,20,5";
-    FingerprintHalProperties::sensor_location(loc);
-    sc = mEngine.getSensorLocation();
-    ASSERT_TRUE(isDefaultLocation(sc));
-
-    loc = "a:b:c";
-    FingerprintHalProperties::sensor_location(loc);
-    sc = mEngine.getSensorLocation();
-    ASSERT_TRUE(isDefaultLocation(sc));
+    const std::vector<std::string> badStr{"", "100", "10:20", "10,20,5", "a:b:c"};
+    SensorLocation sc;
+    for (const auto& s : badStr) {
+        FingerprintHalProperties::sensor_location(s);
+        sc = mEngine.getSensorLocation();
+        ASSERT_TRUE(isDefaultLocation(sc));
+    }
 }
 
+TEST_F(FakeFingerprintEngineUdfpsTest, initialization) {
+    ASSERT_TRUE(mEngine.getWorkMode() == FakeFingerprintEngineUdfps::WorkMode::kIdle);
+}
+
+TEST_F(FakeFingerprintEngineUdfpsTest, authenticate) {
+    std::shared_ptr<TestSessionCallback> cb = ndk::SharedRefBase::make<TestSessionCallback>();
+    std::promise<void> cancel;
+    mEngine.authenticateImpl(cb.get(), 1, cancel.get_future());
+    ASSERT_TRUE(mEngine.getWorkMode() == FakeFingerprintEngineUdfps::WorkMode::kAuthenticate);
+    mEngine.onPointerDownImpl(1, 2, 3, 4.0, 5.0);
+    ASSERT_EQ(cb->getAuthenticationCount(), 0);
+    mEngine.onUiReadyImpl();
+    ASSERT_EQ(cb->getAuthenticationCount(), 1);
+}
+
+TEST_F(FakeFingerprintEngineUdfpsTest, enroll) {
+    std::shared_ptr<TestSessionCallback> cb = ndk::SharedRefBase::make<TestSessionCallback>();
+    std::promise<void> cancel;
+    keymaster::HardwareAuthToken hat{.mac = {5, 6}};
+    FingerprintHalProperties::next_enrollment("5:0,0:true");
+    mEngine.enrollImpl(cb.get(), hat, cancel.get_future());
+    ASSERT_TRUE(mEngine.getWorkMode() == FakeFingerprintEngineUdfps::WorkMode::kEnroll);
+    mEngine.onPointerDownImpl(1, 2, 3, 4.0, 5.0);
+    ASSERT_EQ(cb->mEnrollmentProgress, 0);
+    mEngine.onUiReadyImpl();
+    ASSERT_TRUE(cb->mEnrollmentProgress > 0);
+}
+
+TEST_F(FakeFingerprintEngineUdfpsTest, detectInteraction) {
+    FingerprintHalProperties::detect_interaction(true);
+    FingerprintHalProperties::enrollments({1, 2});
+    FingerprintHalProperties::enrollment_hit(2);
+    FingerprintHalProperties::operation_detect_interaction_acquired("");
+    std::shared_ptr<TestSessionCallback> cb = ndk::SharedRefBase::make<TestSessionCallback>();
+    std::promise<void> cancel;
+    mEngine.detectInteractionImpl(cb.get(), cancel.get_future());
+    ASSERT_TRUE(mEngine.getWorkMode() == FakeFingerprintEngineUdfps::WorkMode::kDetectInteract);
+    mEngine.onPointerDownImpl(1, 2, 3, 4.0, 5.0);
+    ASSERT_EQ(cb->getDetectInteractionCount(), 0);
+    mEngine.onUiReadyImpl();
+    ASSERT_EQ(cb->getDetectInteractionCount(), 1);
+}
 // More
 }  // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp
new file mode 100644
index 0000000..1b071ee
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include <android/binder_process.h>
+#include <fingerprint.sysprop.h>
+#include <gtest/gtest.h>
+
+#include <android-base/logging.h>
+
+#include "FakeLockoutTracker.h"
+#include "util/Util.h"
+
+using namespace ::android::fingerprint::virt;
+using namespace ::aidl::android::hardware::biometrics::fingerprint;
+
+namespace aidl::android::hardware::biometrics::fingerprint {
+
+class FakeLockoutTrackerTest : public ::testing::Test {
+  protected:
+    static constexpr int32_t LOCKOUT_TIMED_THRESHOLD = 3;
+    static constexpr int32_t LOCKOUT_PERMANENT_THRESHOLD = 5;
+    static constexpr int32_t LOCKOUT_TIMED_DURATION = 100;
+
+    void SetUp() override {
+        FingerprintHalProperties::lockout_timed_threshold(LOCKOUT_TIMED_THRESHOLD);
+        FingerprintHalProperties::lockout_timed_duration(LOCKOUT_TIMED_DURATION);
+        FingerprintHalProperties::lockout_permanent_threshold(LOCKOUT_PERMANENT_THRESHOLD);
+    }
+
+    void TearDown() override {
+        // reset to default
+        FingerprintHalProperties::lockout_timed_threshold(5);
+        FingerprintHalProperties::lockout_timed_duration(20);
+        FingerprintHalProperties::lockout_permanent_threshold(10000);
+        FingerprintHalProperties::lockout_enable(false);
+        FingerprintHalProperties::lockout(false);
+    }
+
+    FakeLockoutTracker mLockoutTracker;
+};
+
+TEST_F(FakeLockoutTrackerTest, addFailedAttemptDisable) {
+    FingerprintHalProperties::lockout_enable(false);
+    for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD + 1; i++) mLockoutTracker.addFailedAttempt();
+    ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
+    mLockoutTracker.reset();
+}
+
+TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimed) {
+    FingerprintHalProperties::lockout_enable(true);
+    for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++) mLockoutTracker.addFailedAttempt();
+    ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kTimed);
+    // time left
+    int N = 5;
+    int64_t prevTimeLeft = INT_MIN;
+    for (int i = 0; i < N; i++) {
+        SLEEP_MS(LOCKOUT_TIMED_DURATION / N + 1);
+        int64_t currTimeLeft = mLockoutTracker.getLockoutTimeLeft();
+        ASSERT_TRUE(currTimeLeft > prevTimeLeft);
+        prevTimeLeft = currTimeLeft;
+    }
+    ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
+    mLockoutTracker.reset();
+}
+
+TEST_F(FakeLockoutTrackerTest, addFailedAttemptPermanent) {
+    FingerprintHalProperties::lockout_enable(true);
+    for (int i = 0; i < LOCKOUT_PERMANENT_THRESHOLD - 1; i++) mLockoutTracker.addFailedAttempt();
+    ASSERT_NE(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kPermanent);
+    mLockoutTracker.addFailedAttempt();
+    ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kPermanent);
+    ASSERT_TRUE(FingerprintHalProperties::lockout());
+    mLockoutTracker.reset();
+}
+
+}  // namespace aidl::android::hardware::biometrics::fingerprint
+
+int main(int argc, char** argv) {
+    testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}