1 /*
2  * Copyright (C) 2020 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 <aidl/Gtest.h>
18 #include <aidl/Vintf.h>
19 #include <aidl/android/hardware/biometrics/fingerprint/BnFingerprint.h>
20 #include <aidl/android/hardware/biometrics/fingerprint/BnSessionCallback.h>
21 
22 #include <android/binder_manager.h>
23 #include <android/binder_process.h>
24 
25 #include <chrono>
26 #include <future>
27 
28 namespace aidl::android::hardware::biometrics::fingerprint {
29 namespace {
30 
31 using namespace std::literals::chrono_literals;
32 
33 constexpr int kSensorId = 0;
34 constexpr int kUserId = 0;
35 
36 class SessionCallback : public BnSessionCallback {
37   public:
onChallengeGenerated(int64_t challenge)38     ndk::ScopedAStatus onChallengeGenerated(int64_t challenge) override {
39         auto lock = std::lock_guard{mMutex};
40         mOnChallengeGeneratedInvoked = true;
41         mGeneratedChallenge = challenge;
42         mCv.notify_one();
43         return ndk::ScopedAStatus::ok();
44     }
45 
onChallengeRevoked(int64_t challenge)46     ndk::ScopedAStatus onChallengeRevoked(int64_t challenge) override {
47         auto lock = std::lock_guard{mMutex};
48         mOnChallengeRevokedInvoked = true;
49         mRevokedChallenge = challenge;
50         mCv.notify_one();
51         return ndk::ScopedAStatus::ok();
52     }
53 
onAcquired(AcquiredInfo,int32_t)54     ndk::ScopedAStatus onAcquired(AcquiredInfo /*info*/, int32_t /*vendorCode*/) override {
55         return ndk::ScopedAStatus::ok();
56     }
57 
onError(Error error,int32_t)58     ndk::ScopedAStatus onError(Error error, int32_t /*vendorCode*/) override {
59         auto lock = std::lock_guard{mMutex};
60         mError = error;
61         mOnErrorInvoked = true;
62         mCv.notify_one();
63         return ndk::ScopedAStatus::ok();
64     }
65 
onEnrollmentProgress(int32_t,int32_t)66     ndk::ScopedAStatus onEnrollmentProgress(int32_t /*enrollmentId*/,
67                                             int32_t /*remaining*/) override {
68         return ndk::ScopedAStatus::ok();
69     }
70 
onAuthenticationSucceeded(int32_t,const keymaster::HardwareAuthToken &)71     ndk::ScopedAStatus onAuthenticationSucceeded(
72             int32_t /*enrollmentId*/, const keymaster::HardwareAuthToken& /*hat*/) override {
73         return ndk::ScopedAStatus::ok();
74     }
75 
onAuthenticationFailed()76     ndk::ScopedAStatus onAuthenticationFailed() override { return ndk::ScopedAStatus::ok(); }
77 
onLockoutTimed(int64_t)78     ndk::ScopedAStatus onLockoutTimed(int64_t /*durationMillis*/) override {
79         return ndk::ScopedAStatus::ok();
80     }
81 
onLockoutPermanent()82     ndk::ScopedAStatus onLockoutPermanent() override { return ndk::ScopedAStatus::ok(); }
83 
onLockoutCleared()84     ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); }
85 
onInteractionDetected()86     ndk::ScopedAStatus onInteractionDetected() override { return ndk::ScopedAStatus::ok(); }
87 
onEnrollmentsEnumerated(const std::vector<int32_t> &)88     ndk::ScopedAStatus onEnrollmentsEnumerated(
89             const std::vector<int32_t>& /*enrollmentIds*/) override {
90         auto lock = std::lock_guard{mMutex};
91         mOnEnrollmentsEnumeratedInvoked = true;
92         mCv.notify_one();
93         return ndk::ScopedAStatus::ok();
94     }
95 
onEnrollmentsRemoved(const std::vector<int32_t> &)96     ndk::ScopedAStatus onEnrollmentsRemoved(
97             const std::vector<int32_t>& /*enrollmentIds*/) override {
98         auto lock = std::lock_guard{mMutex};
99         mOnEnrollmentsRemovedInvoked = true;
100         mCv.notify_one();
101         return ndk::ScopedAStatus::ok();
102     }
103 
onAuthenticatorIdRetrieved(int64_t)104     ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t /*authenticatorId*/) override {
105         auto lock = std::lock_guard{mMutex};
106         mOnAuthenticatorIdRetrievedInvoked = true;
107         mCv.notify_one();
108         return ndk::ScopedAStatus::ok();
109     }
110 
onAuthenticatorIdInvalidated(int64_t)111     ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t /*newAuthenticatorId*/) override {
112         auto lock = std::lock_guard{mMutex};
113         mOnAuthenticatorIdInvalidatedInvoked = true;
114         mCv.notify_one();
115         return ndk::ScopedAStatus::ok();
116     }
117 
onSessionClosed()118     ndk::ScopedAStatus onSessionClosed() override {
119         auto lock = std::lock_guard{mMutex};
120         mOnSessionClosedInvoked = true;
121         mCv.notify_one();
122         return ndk::ScopedAStatus::ok();
123     }
124 
125     std::mutex mMutex;
126     std::condition_variable mCv;
127     Error mError = Error::UNKNOWN;
128     int64_t mGeneratedChallenge = 0;
129     int64_t mRevokedChallenge = 0;
130     bool mOnChallengeGeneratedInvoked = false;
131     bool mOnChallengeRevokedInvoked = false;
132     bool mOnErrorInvoked = false;
133     bool mOnEnrollmentsEnumeratedInvoked = false;
134     bool mOnEnrollmentsRemovedInvoked = false;
135     bool mOnAuthenticatorIdRetrievedInvoked = false;
136     bool mOnAuthenticatorIdInvalidatedInvoked = false;
137     bool mOnSessionClosedInvoked = false;
138 };
139 
140 class Fingerprint : public testing::TestWithParam<std::string> {
141   protected:
SetUp()142     void SetUp() override {
143         // Prepare the callback.
144         mCb = ndk::SharedRefBase::make<SessionCallback>();
145 
146         int retries = 0;
147         bool isOk = false;
148         // If the first attempt to create a session fails, we try to create a session again. The
149         // first attempt might fail if the framework already has an active session. The AIDL
150         // contract doesn't allow to create a new session without closing the old one. However, we
151         // can't close the framework's session from VTS. The expectation here is that the HAL will
152         // crash after the first illegal attempt to create a session, then it will restart, and then
153         // we'll be able to create a session.
154         do {
155             // Get an instance of the HAL.
156             AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
157             ASSERT_NE(binder, nullptr);
158             mHal = IFingerprint::fromBinder(ndk::SpAIBinder(binder));
159 
160             // Create a session.
161             isOk = mHal->createSession(kSensorId, kUserId, mCb, &mSession).isOk();
162             ++retries;
163         } while (!isOk && retries < 2);
164 
165         ASSERT_TRUE(isOk);
166     }
167 
TearDown()168     void TearDown() override {
169         // Close the mSession.
170         ASSERT_TRUE(mSession->close().isOk());
171 
172         // Make sure the mSession is closed.
173         auto lock = std::unique_lock<std::mutex>(mCb->mMutex);
174         mCb->mCv.wait(lock, [this] { return mCb->mOnSessionClosedInvoked; });
175     }
176 
177     std::shared_ptr<IFingerprint> mHal;
178     std::shared_ptr<SessionCallback> mCb;
179     std::shared_ptr<ISession> mSession;
180 };
181 
TEST_P(Fingerprint,GetSensorPropsWorksTest)182 TEST_P(Fingerprint, GetSensorPropsWorksTest) {
183     std::vector<SensorProps> sensorProps;
184 
185     // Call the method.
186     ASSERT_TRUE(mHal->getSensorProps(&sensorProps).isOk());
187 
188     // Make sure the sensorProps aren't empty.
189     ASSERT_FALSE(sensorProps.empty());
190     ASSERT_FALSE(sensorProps[0].commonProps.componentInfo.empty());
191 }
192 
TEST_P(Fingerprint,EnrollWithBadHatResultsInErrorTest)193 TEST_P(Fingerprint, EnrollWithBadHatResultsInErrorTest) {
194     // Call the method.
195     auto hat = keymaster::HardwareAuthToken{};
196     std::shared_ptr<common::ICancellationSignal> cancellationSignal;
197     ASSERT_TRUE(mSession->enroll(hat, &cancellationSignal).isOk());
198 
199     // Make sure an error is returned.
200     auto lock = std::unique_lock{mCb->mMutex};
201     mCb->mCv.wait(lock, [this] { return mCb->mOnErrorInvoked; });
202 }
203 
TEST_P(Fingerprint,GenerateChallengeProducesUniqueChallengesTest)204 TEST_P(Fingerprint, GenerateChallengeProducesUniqueChallengesTest) {
205     static constexpr int kIterations = 100;
206 
207     auto challenges = std::set<int>{};
208     for (unsigned int i = 0; i < kIterations; ++i) {
209         // Call the method.
210         ASSERT_TRUE(mSession->generateChallenge().isOk());
211 
212         // Check that the generated challenge is unique and not 0.
213         auto lock = std::unique_lock{mCb->mMutex};
214         mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeGeneratedInvoked; });
215         ASSERT_NE(mCb->mGeneratedChallenge, 0);
216         ASSERT_EQ(challenges.find(mCb->mGeneratedChallenge), challenges.end());
217 
218         challenges.insert(mCb->mGeneratedChallenge);
219         mCb->mOnChallengeGeneratedInvoked = false;
220     }
221 }
222 
TEST_P(Fingerprint,RevokeChallengeWorksForNonexistentChallengeTest)223 TEST_P(Fingerprint, RevokeChallengeWorksForNonexistentChallengeTest) {
224     const int64_t nonexistentChallenge = 123;
225 
226     // Call the method.
227     ASSERT_TRUE(mSession->revokeChallenge(nonexistentChallenge).isOk());
228 
229     // Check that the challenge is revoked and matches the requested challenge.
230     auto lock = std::unique_lock{mCb->mMutex};
231     mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeRevokedInvoked; });
232     ASSERT_EQ(mCb->mRevokedChallenge, nonexistentChallenge);
233 }
234 
TEST_P(Fingerprint,RevokeChallengeWorksForExistentChallengeTest)235 TEST_P(Fingerprint, RevokeChallengeWorksForExistentChallengeTest) {
236     // Generate a challenge.
237     ASSERT_TRUE(mSession->generateChallenge().isOk());
238 
239     // Wait for the result.
240     auto lock = std::unique_lock{mCb->mMutex};
241     mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeGeneratedInvoked; });
242     lock.unlock();
243 
244     // Revoke the challenge.
245     ASSERT_TRUE(mSession->revokeChallenge(mCb->mGeneratedChallenge).isOk());
246 
247     // Check that the challenge is revoked and matches the requested challenge.
248     lock.lock();
249     mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeRevokedInvoked; });
250     ASSERT_EQ(mCb->mRevokedChallenge, mCb->mGeneratedChallenge);
251 }
252 
TEST_P(Fingerprint,EnumerateEnrollmentsWorksTest)253 TEST_P(Fingerprint, EnumerateEnrollmentsWorksTest) {
254     // Call the method.
255     ASSERT_TRUE(mSession->enumerateEnrollments().isOk());
256 
257     // Wait for the result.
258     auto lock = std::unique_lock{mCb->mMutex};
259     mCb->mCv.wait(lock, [this] { return mCb->mOnEnrollmentsEnumeratedInvoked; });
260 }
261 
TEST_P(Fingerprint,RemoveEnrollmentsWorksTest)262 TEST_P(Fingerprint, RemoveEnrollmentsWorksTest) {
263     // Call the method.
264     ASSERT_TRUE(mSession->removeEnrollments({}).isOk());
265 
266     // Wait for the result.
267     auto lock = std::unique_lock{mCb->mMutex};
268     mCb->mCv.wait(lock, [this] { return mCb->mOnEnrollmentsRemovedInvoked; });
269 }
270 
TEST_P(Fingerprint,GetAuthenticatorIdWorksTest)271 TEST_P(Fingerprint, GetAuthenticatorIdWorksTest) {
272     // Call the method.
273     ASSERT_TRUE(mSession->getAuthenticatorId().isOk());
274 
275     // Wait for the result.
276     auto lock = std::unique_lock{mCb->mMutex};
277     mCb->mCv.wait(lock, [this] { return mCb->mOnAuthenticatorIdRetrievedInvoked; });
278 }
279 
TEST_P(Fingerprint,InvalidateAuthenticatorIdWorksTest)280 TEST_P(Fingerprint, InvalidateAuthenticatorIdWorksTest) {
281     // Call the method.
282     ASSERT_TRUE(mSession->invalidateAuthenticatorId().isOk());
283 
284     // Wait for the result.
285     auto lock = std::unique_lock{mCb->mMutex};
286     mCb->mCv.wait(lock, [this] { return mCb->mOnAuthenticatorIdInvalidatedInvoked; });
287 }
288 
289 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Fingerprint);
290 INSTANTIATE_TEST_SUITE_P(
291         IFingerprint, Fingerprint,
292         testing::ValuesIn(::android::getAidlHalInstanceNames(IFingerprint::descriptor)),
293         ::android::PrintInstanceNameToString);
294 
295 }  // namespace
296 }  // namespace aidl::android::hardware::biometrics::fingerprint
297 
main(int argc,char ** argv)298 int main(int argc, char** argv) {
299     ::testing::InitGoogleTest(&argc, argv);
300     ABinderProcess_setThreadPoolMaxThreadCount(1);
301     ABinderProcess_startThreadPool();
302     return RUN_ALL_TESTS();
303 }
304