Jeff Pu | df81c96 | 2024-03-06 10:58:17 -0500 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2024 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include <android/binder_process.h> |
| 18 | #include <fingerprint.sysprop.h> |
| 19 | #include <gtest/gtest.h> |
| 20 | |
| 21 | #include <android-base/logging.h> |
| 22 | |
| 23 | #include "Fingerprint.h" |
| 24 | #include "VirtualHal.h" |
| 25 | |
| 26 | using namespace ::android::fingerprint::virt; |
| 27 | using namespace ::aidl::android::hardware::biometrics::fingerprint; |
| 28 | |
| 29 | namespace aidl::android::hardware::biometrics::fingerprint { |
| 30 | |
| 31 | class VirtualHalTest : public ::testing::Test { |
| 32 | public: |
| 33 | static const int32_t STATUS_FAILED_TO_SET_PARAMETER = 2; |
| 34 | |
| 35 | protected: |
| 36 | void SetUp() override { |
| 37 | mHal = ndk::SharedRefBase::make<Fingerprint>(); |
| 38 | mVhal = ndk::SharedRefBase::make<VirtualHal>(mHal.get()); |
| 39 | ASSERT_TRUE(mVhal != nullptr); |
| 40 | mHal->resetConfigToDefault(); |
| 41 | } |
| 42 | |
| 43 | void TearDown() override { mHal->resetConfigToDefault(); } |
| 44 | |
| 45 | std::shared_ptr<VirtualHal> mVhal; |
| 46 | |
| 47 | ndk::ScopedAStatus validateNonNegativeInputOfInt32(const char* name, |
| 48 | ndk::ScopedAStatus (VirtualHal::*f)(int32_t), |
| 49 | const std::vector<int32_t>& in_good); |
| 50 | |
| 51 | private: |
| 52 | std::shared_ptr<Fingerprint> mHal; |
| 53 | }; |
| 54 | |
| 55 | ndk::ScopedAStatus VirtualHalTest::validateNonNegativeInputOfInt32( |
| 56 | const char* name, ndk::ScopedAStatus (VirtualHal::*f)(int32_t), |
| 57 | const std::vector<int32_t>& in_params_good) { |
| 58 | ndk::ScopedAStatus status; |
| 59 | for (auto& param : in_params_good) { |
| 60 | status = (*mVhal.*f)(param); |
| 61 | if (!status.isOk()) return status; |
| 62 | if (Fingerprint::cfg().get<int32_t>(name) != param) { |
| 63 | return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( |
| 64 | VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER, |
| 65 | "Error: fail to set non-negative parameter")); |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | int32_t old_param = Fingerprint::cfg().get<int32_t>(name); |
| 70 | status = (*mVhal.*f)(-1); |
| 71 | if (status.isOk()) { |
| 72 | return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( |
| 73 | VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER, "Error: should return NOK")); |
| 74 | } |
| 75 | if (status.getServiceSpecificError() != IVirtualHal::STATUS_INVALID_PARAMETER) { |
| 76 | return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( |
| 77 | VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER, |
| 78 | "Error: unexpected return error code")); |
| 79 | } |
| 80 | if (Fingerprint::cfg().get<int32_t>(name) != old_param) { |
| 81 | return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( |
| 82 | VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER, |
| 83 | "Error: unexpected parameter change on failed attempt")); |
| 84 | } |
| 85 | return ndk::ScopedAStatus::ok(); |
| 86 | } |
| 87 | |
| 88 | TEST_F(VirtualHalTest, init) { |
| 89 | mVhal->setLockout(false); |
| 90 | ASSERT_TRUE(Fingerprint::cfg().get<bool>("lockout") == false); |
| 91 | ASSERT_TRUE(Fingerprint::cfg().get<std::string>("type") == "rear"); |
| 92 | ASSERT_TRUE(Fingerprint::cfg().get<std::int32_t>("sensor_strength") == 2); |
| 93 | std::int64_t id = Fingerprint::cfg().get<std::int64_t>("authenticator_id"); |
| 94 | ASSERT_TRUE(Fingerprint::cfg().get<std::int64_t>("authenticator_id") == 0); |
| 95 | ASSERT_TRUE(Fingerprint::cfg().getopt<OptIntVec>("enrollments") == OptIntVec()); |
| 96 | } |
| 97 | |
| 98 | TEST_F(VirtualHalTest, enrollment_hit_int32) { |
| 99 | mVhal->setEnrollmentHit(11); |
| 100 | ASSERT_TRUE(Fingerprint::cfg().get<int32_t>("enrollment_hit") == 11); |
| 101 | } |
| 102 | |
Jeff Pu | 3bc1f06 | 2024-04-19 19:37:45 +0000 | [diff] [blame] | 103 | TEST_F(VirtualHalTest, next_enrollment) { |
| 104 | struct { |
| 105 | std::string nextEnrollmentStr; |
| 106 | fingerprint::NextEnrollment nextEnrollment; |
| 107 | } testData[] = { |
| 108 | {"1:20:true", {1, {{20}}, true}}, |
| 109 | {"1:50,60,70:true", {1, {{50}, {60}, {70}}, true}}, |
| 110 | {"2:50-[8],60,70-[2,1002,1]:false", |
| 111 | {2, |
| 112 | {{50, {{AcquiredInfo::START}}}, |
| 113 | {60}, |
| 114 | {70, {{AcquiredInfo::PARTIAL}, {1002}, {AcquiredInfo::GOOD}}}}, |
| 115 | false}}, |
| 116 | }; |
| 117 | |
| 118 | for (auto& d : testData) { |
| 119 | mVhal->setNextEnrollment(d.nextEnrollment); |
| 120 | ASSERT_TRUE(Fingerprint::cfg().get<std::string>("next_enrollment") == d.nextEnrollmentStr); |
| 121 | } |
| 122 | } |
| 123 | |
Jeff Pu | df81c96 | 2024-03-06 10:58:17 -0500 | [diff] [blame] | 124 | TEST_F(VirtualHalTest, authenticator_id_int64) { |
| 125 | mVhal->setAuthenticatorId(12345678900); |
| 126 | ASSERT_TRUE(Fingerprint::cfg().get<int64_t>("authenticator_id") == 12345678900); |
| 127 | } |
| 128 | |
| 129 | TEST_F(VirtualHalTest, opeationAuthenticateFails_bool) { |
| 130 | mVhal->setOperationAuthenticateFails(true); |
| 131 | ASSERT_TRUE(Fingerprint::cfg().get<bool>("operation_authenticate_fails")); |
| 132 | } |
| 133 | |
| 134 | TEST_F(VirtualHalTest, operationAuthenticateAcquired_int32_vector) { |
Jeff Pu | 3bc1f06 | 2024-04-19 19:37:45 +0000 | [diff] [blame] | 135 | using Tag = AcquiredInfoAndVendorCode::Tag; |
| 136 | std::vector<AcquiredInfoAndVendorCode> ac{ |
| 137 | {AcquiredInfo::START}, {AcquiredInfo::PARTIAL}, {1023}}; |
Jeff Pu | df81c96 | 2024-03-06 10:58:17 -0500 | [diff] [blame] | 138 | mVhal->setOperationAuthenticateAcquired(ac); |
| 139 | OptIntVec ac_get = Fingerprint::cfg().getopt<OptIntVec>("operation_authenticate_acquired"); |
| 140 | ASSERT_TRUE(ac_get.size() == ac.size()); |
| 141 | for (int i = 0; i < ac.size(); i++) { |
Jeff Pu | 3bc1f06 | 2024-04-19 19:37:45 +0000 | [diff] [blame] | 142 | int acCode = (ac[i].getTag() == Tag::acquiredInfo) ? (int)ac[i].get<Tag::acquiredInfo>() |
| 143 | : ac[i].get<Tag::vendorCode>(); |
| 144 | ASSERT_TRUE(acCode == ac_get[i]); |
Jeff Pu | df81c96 | 2024-03-06 10:58:17 -0500 | [diff] [blame] | 145 | } |
| 146 | } |
| 147 | |
| 148 | TEST_F(VirtualHalTest, type) { |
| 149 | struct { |
| 150 | FingerprintSensorType type; |
| 151 | const char* typeStr; |
| 152 | } typeMap[] = {{FingerprintSensorType::REAR, "rear"}, |
| 153 | {FingerprintSensorType::POWER_BUTTON, "side"}, |
| 154 | {FingerprintSensorType::UNDER_DISPLAY_OPTICAL, "udfps"}, |
| 155 | {FingerprintSensorType::UNDER_DISPLAY_ULTRASONIC, "udfps"}, |
| 156 | {FingerprintSensorType::UNKNOWN, "unknown"}}; |
| 157 | for (auto const& x : typeMap) { |
| 158 | mVhal->setType(x.type); |
| 159 | ASSERT_TRUE(Fingerprint::cfg().get<std::string>("type") == x.typeStr); |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | TEST_F(VirtualHalTest, sensorStrength) { |
| 164 | SensorStrength strengths[] = {SensorStrength::CONVENIENCE, SensorStrength::WEAK, |
| 165 | SensorStrength::STRONG}; |
| 166 | |
| 167 | for (auto const& strength : strengths) { |
| 168 | mVhal->setSensorStrength(strength); |
| 169 | ASSERT_TRUE(Fingerprint::cfg().get<int32_t>("sensor_strength") == (int32_t)(strength)); |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | TEST_F(VirtualHalTest, sensorLocation) { |
| 174 | SensorLocation loc = {.sensorLocationX = 1, .sensorLocationY = 2, .sensorRadius = 3}; |
| 175 | mVhal->setSensorLocation(loc); |
| 176 | ASSERT_TRUE(Fingerprint::cfg().get<std::string>("sensor_location") == "1:2:3"); |
| 177 | } |
| 178 | |
| 179 | TEST_F(VirtualHalTest, setLatency) { |
| 180 | ndk::ScopedAStatus status; |
| 181 | std::vector<int32_t> in_lats[] = {{1}, {2, 3}, {5, 4}}; |
| 182 | for (auto const& in_lat : in_lats) { |
| 183 | status = mVhal->setOperationAuthenticateLatency(in_lat); |
| 184 | ASSERT_TRUE(status.isOk()); |
| 185 | OptIntVec out_lat = Fingerprint::cfg().getopt<OptIntVec>("operation_authenticate_latency"); |
| 186 | ASSERT_TRUE(in_lat.size() == out_lat.size()); |
| 187 | for (int i = 0; i < in_lat.size(); i++) { |
| 188 | ASSERT_TRUE(in_lat[i] == out_lat[i]); |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | std::vector<int32_t> bad_in_lats[] = {{}, {1, 2, 3}, {1, -3}}; |
| 193 | for (auto const& in_lat : bad_in_lats) { |
| 194 | status = mVhal->setOperationAuthenticateLatency(in_lat); |
| 195 | ASSERT_TRUE(!status.isOk()); |
| 196 | ASSERT_TRUE(status.getServiceSpecificError() == IVirtualHal::STATUS_INVALID_PARAMETER); |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | TEST_F(VirtualHalTest, setOperationAuthenticateDuration) { |
| 201 | ndk::ScopedAStatus status = validateNonNegativeInputOfInt32( |
| 202 | "operation_authenticate_duration", &IVirtualHal::setOperationAuthenticateDuration, |
| 203 | {0, 33}); |
| 204 | ASSERT_TRUE(status.isOk()); |
| 205 | } |
| 206 | |
| 207 | TEST_F(VirtualHalTest, setOperationDetectInteractionDuration) { |
| 208 | ndk::ScopedAStatus status = validateNonNegativeInputOfInt32( |
| 209 | "operation_detect_interaction_duration", |
| 210 | &IVirtualHal::setOperationDetectInteractionDuration, {0, 34}); |
| 211 | ASSERT_TRUE(status.isOk()); |
| 212 | } |
| 213 | |
| 214 | TEST_F(VirtualHalTest, setLockoutTimedDuration) { |
| 215 | ndk::ScopedAStatus status = validateNonNegativeInputOfInt32( |
| 216 | "lockout_timed_duration", &IVirtualHal::setLockoutTimedDuration, {0, 35}); |
| 217 | ASSERT_TRUE(status.isOk()); |
| 218 | } |
| 219 | |
| 220 | TEST_F(VirtualHalTest, setLockoutTimedThreshold) { |
| 221 | ndk::ScopedAStatus status = validateNonNegativeInputOfInt32( |
| 222 | "lockout_timed_threshold", &IVirtualHal::setLockoutTimedThreshold, {0, 36}); |
| 223 | ASSERT_TRUE(status.isOk()); |
| 224 | } |
| 225 | |
| 226 | TEST_F(VirtualHalTest, setLockoutPermanentThreshold) { |
| 227 | ndk::ScopedAStatus status = validateNonNegativeInputOfInt32( |
| 228 | "lockout_permanent_threshold", &IVirtualHal::setLockoutPermanentThreshold, {0, 37}); |
| 229 | ASSERT_TRUE(status.isOk()); |
| 230 | } |
| 231 | |
| 232 | TEST_F(VirtualHalTest, setOthers) { |
| 233 | // Verify that there is no CHECK() failures |
| 234 | mVhal->setEnrollments({7, 6, 5}); |
| 235 | mVhal->setChallenge(111222333444555666); |
| 236 | mVhal->setOperationAuthenticateError(4); |
| 237 | mVhal->setOperationEnrollError(5); |
| 238 | mVhal->setOperationEnrollLatency({4, 5}); |
| 239 | mVhal->setOperationDetectInteractionError(6); |
Jeff Pu | 3bc1f06 | 2024-04-19 19:37:45 +0000 | [diff] [blame] | 240 | mVhal->setOperationDetectInteractionAcquired({{AcquiredInfo::START}, {AcquiredInfo::GOOD}}); |
Jeff Pu | df81c96 | 2024-03-06 10:58:17 -0500 | [diff] [blame] | 241 | mVhal->setLockout(false); |
| 242 | mVhal->setLockoutEnable(false); |
| 243 | mVhal->setSensorId(5); |
| 244 | mVhal->setMaxEnrollmentPerUser(6); |
| 245 | mVhal->setNavigationGuesture(false); |
| 246 | mVhal->setDetectInteraction(false); |
| 247 | mVhal->setDisplayTouch(false); |
| 248 | mVhal->setControlIllumination(false); |
| 249 | } |
| 250 | |
| 251 | } // namespace aidl::android::hardware::biometrics::fingerprint |
| 252 | |
| 253 | int main(int argc, char** argv) { |
| 254 | testing::InitGoogleTest(&argc, argv); |
| 255 | ABinderProcess_startThreadPool(); |
| 256 | return RUN_ALL_TESTS(); |
| 257 | } |