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:
SetUp()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 
TearDown()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 
validateNonNegativeInputOfInt32(const char * name,ndk::ScopedAStatus (VirtualHal::* f)(int32_t),const std::vector<int32_t> & in_params_good)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 
TEST_F(VirtualHalTest,init)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 
TEST_F(VirtualHalTest,enrollment_hit_int32)98 TEST_F(VirtualHalTest, enrollment_hit_int32) {
99     mVhal->setEnrollmentHit(11);
100     ASSERT_TRUE(Fingerprint::cfg().get<int32_t>("enrollment_hit") == 11);
101 }
102 
TEST_F(VirtualHalTest,next_enrollment)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 
TEST_F(VirtualHalTest,authenticator_id_int64)124 TEST_F(VirtualHalTest, authenticator_id_int64) {
125     mVhal->setAuthenticatorId(12345678900);
126     ASSERT_TRUE(Fingerprint::cfg().get<int64_t>("authenticator_id") == 12345678900);
127 }
128 
TEST_F(VirtualHalTest,opeationAuthenticateFails_bool)129 TEST_F(VirtualHalTest, opeationAuthenticateFails_bool) {
130     mVhal->setOperationAuthenticateFails(true);
131     ASSERT_TRUE(Fingerprint::cfg().get<bool>("operation_authenticate_fails"));
132 }
133 
TEST_F(VirtualHalTest,operationAuthenticateAcquired_int32_vector)134 TEST_F(VirtualHalTest, operationAuthenticateAcquired_int32_vector) {
135     using Tag = AcquiredInfoAndVendorCode::Tag;
136     std::vector<AcquiredInfoAndVendorCode> ac{
137             {AcquiredInfo::START}, {AcquiredInfo::PARTIAL}, {1023}};
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++) {
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]);
145     }
146 }
147 
TEST_F(VirtualHalTest,type)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 
TEST_F(VirtualHalTest,sensorStrength)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 
TEST_F(VirtualHalTest,sensorLocation)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 
TEST_F(VirtualHalTest,setLatency)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 
TEST_F(VirtualHalTest,setOperationAuthenticateDuration)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 
TEST_F(VirtualHalTest,setOperationDetectInteractionDuration)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 
TEST_F(VirtualHalTest,setLockoutTimedDuration)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 
TEST_F(VirtualHalTest,setLockoutTimedThreshold)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 
TEST_F(VirtualHalTest,setLockoutPermanentThreshold)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 
TEST_F(VirtualHalTest,setOthers)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);
240     mVhal->setOperationDetectInteractionAcquired({{AcquiredInfo::START}, {AcquiredInfo::GOOD}});
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 
main(int argc,char ** argv)253 int main(int argc, char** argv) {
254     testing::InitGoogleTest(&argc, argv);
255     ABinderProcess_startThreadPool();
256     return RUN_ALL_TESTS();
257 }
258