blob: 1cd8c769f2b1acfbb4030eb0ac2704c1477c2745 [file] [log] [blame]
Ilya Matyukhin14412df2020-08-27 14:26:06 -07001/*
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 */
Ilya Matyukhin5e09b822021-02-26 12:24:18 -080016
Ilya Matyukhin14412df2020-08-27 14:26:06 -070017#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
Ilya Matyukhincaa67672021-03-23 19:00:36 -070025#include <chrono>
Ilya Matyukhin14412df2020-08-27 14:26:06 -070026#include <future>
27
28namespace aidl::android::hardware::biometrics::fingerprint {
29namespace {
30
Ilya Matyukhincaa67672021-03-23 19:00:36 -070031using namespace std::literals::chrono_literals;
32
Ilya Matyukhin14412df2020-08-27 14:26:06 -070033constexpr int kSensorId = 0;
34constexpr int kUserId = 0;
Ilya Matyukhin14412df2020-08-27 14:26:06 -070035
36class SessionCallback : public BnSessionCallback {
37 public:
Ilya Matyukhin04247242021-07-02 20:34:52 +000038 ndk::ScopedAStatus onChallengeGenerated(int64_t challenge) override {
39 auto lock = std::lock_guard{mMutex};
40 mOnChallengeGeneratedInvoked = true;
41 mGeneratedChallenge = challenge;
42 mCv.notify_one();
Ilya Matyukhin3d54f452020-10-15 17:32:09 -070043 return ndk::ScopedAStatus::ok();
44 }
45
Ilya Matyukhin04247242021-07-02 20:34:52 +000046 ndk::ScopedAStatus onChallengeRevoked(int64_t challenge) override {
47 auto lock = std::lock_guard{mMutex};
48 mOnChallengeRevokedInvoked = true;
49 mRevokedChallenge = challenge;
50 mCv.notify_one();
Ilya Matyukhin3d54f452020-10-15 17:32:09 -070051 return ndk::ScopedAStatus::ok();
52 }
53
Ilya Matyukhin14412df2020-08-27 14:26:06 -070054 ndk::ScopedAStatus onAcquired(AcquiredInfo /*info*/, int32_t /*vendorCode*/) override {
55 return ndk::ScopedAStatus::ok();
56 }
57
Ilya Matyukhin04247242021-07-02 20:34:52 +000058 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();
Ilya Matyukhin14412df2020-08-27 14:26:06 -070063 return ndk::ScopedAStatus::ok();
64 }
65
Kevin Chyn1288c102020-09-18 16:42:44 -070066 ndk::ScopedAStatus onEnrollmentProgress(int32_t /*enrollmentId*/,
67 int32_t /*remaining*/) override {
Ilya Matyukhin14412df2020-08-27 14:26:06 -070068 return ndk::ScopedAStatus::ok();
69 }
70
Ilya Matyukhin5e09b822021-02-26 12:24:18 -080071 ndk::ScopedAStatus onAuthenticationSucceeded(
72 int32_t /*enrollmentId*/, const keymaster::HardwareAuthToken& /*hat*/) override {
Ilya Matyukhin14412df2020-08-27 14:26:06 -070073 return ndk::ScopedAStatus::ok();
74 }
75
Ilya Matyukhin5e09b822021-02-26 12:24:18 -080076 ndk::ScopedAStatus onAuthenticationFailed() override { return ndk::ScopedAStatus::ok(); }
Kevin Chyn64c13a02020-09-21 12:37:56 -070077
Kevin Chynef79d662020-09-22 12:14:44 -070078 ndk::ScopedAStatus onLockoutTimed(int64_t /*durationMillis*/) override {
79 return ndk::ScopedAStatus::ok();
80 }
81
Ilya Matyukhin5e09b822021-02-26 12:24:18 -080082 ndk::ScopedAStatus onLockoutPermanent() override { return ndk::ScopedAStatus::ok(); }
Kevin Chynef79d662020-09-22 12:14:44 -070083
Ilya Matyukhin5e09b822021-02-26 12:24:18 -080084 ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); }
Kevin Chynef79d662020-09-22 12:14:44 -070085
Ilya Matyukhin14412df2020-08-27 14:26:06 -070086 ndk::ScopedAStatus onInteractionDetected() override { return ndk::ScopedAStatus::ok(); }
87
88 ndk::ScopedAStatus onEnrollmentsEnumerated(
89 const std::vector<int32_t>& /*enrollmentIds*/) override {
Ilya Matyukhin04247242021-07-02 20:34:52 +000090 auto lock = std::lock_guard{mMutex};
91 mOnEnrollmentsEnumeratedInvoked = true;
92 mCv.notify_one();
Ilya Matyukhin14412df2020-08-27 14:26:06 -070093 return ndk::ScopedAStatus::ok();
94 }
95
96 ndk::ScopedAStatus onEnrollmentsRemoved(
97 const std::vector<int32_t>& /*enrollmentIds*/) override {
Ilya Matyukhin04247242021-07-02 20:34:52 +000098 auto lock = std::lock_guard{mMutex};
99 mOnEnrollmentsRemovedInvoked = true;
100 mCv.notify_one();
Ilya Matyukhin14412df2020-08-27 14:26:06 -0700101 return ndk::ScopedAStatus::ok();
102 }
103
Kevin Chyn6e862c32020-09-16 18:27:37 -0700104 ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t /*authenticatorId*/) override {
Ilya Matyukhin04247242021-07-02 20:34:52 +0000105 auto lock = std::lock_guard{mMutex};
106 mOnAuthenticatorIdRetrievedInvoked = true;
107 mCv.notify_one();
Kevin Chyn6e862c32020-09-16 18:27:37 -0700108 return ndk::ScopedAStatus::ok();
109 }
110
Kevin Chynf7890cc2021-01-11 17:08:36 -0800111 ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t /*newAuthenticatorId*/) override {
Ilya Matyukhin04247242021-07-02 20:34:52 +0000112 auto lock = std::lock_guard{mMutex};
113 mOnAuthenticatorIdInvalidatedInvoked = true;
114 mCv.notify_one();
Kevin Chyn6e862c32020-09-16 18:27:37 -0700115 return ndk::ScopedAStatus::ok();
116 }
117
Ilya Matyukhincaa67672021-03-23 19:00:36 -0700118 ndk::ScopedAStatus onSessionClosed() override {
Ilya Matyukhin04247242021-07-02 20:34:52 +0000119 auto lock = std::lock_guard{mMutex};
120 mOnSessionClosedInvoked = true;
121 mCv.notify_one();
Ilya Matyukhincaa67672021-03-23 19:00:36 -0700122 return ndk::ScopedAStatus::ok();
123 }
Ilya Matyukhincbbfa932021-03-22 13:25:15 -0700124
Ilya Matyukhin04247242021-07-02 20:34:52 +0000125 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;
Ilya Matyukhin14412df2020-08-27 14:26:06 -0700138};
139
140class Fingerprint : public testing::TestWithParam<std::string> {
141 protected:
142 void SetUp() override {
Ilya Matyukhin04247242021-07-02 20:34:52 +0000143 // 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
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; });
Ilya Matyukhin14412df2020-08-27 14:26:06 -0700175 }
176
Ilya Matyukhin5e09b822021-02-26 12:24:18 -0800177 std::shared_ptr<IFingerprint> mHal;
Ilya Matyukhin04247242021-07-02 20:34:52 +0000178 std::shared_ptr<SessionCallback> mCb;
179 std::shared_ptr<ISession> mSession;
Ilya Matyukhin14412df2020-08-27 14:26:06 -0700180};
181
Ilya Matyukhin04247242021-07-02 20:34:52 +0000182TEST_P(Fingerprint, GetSensorPropsWorksTest) {
183 std::vector<SensorProps> sensorProps;
Ilya Matyukhin14412df2020-08-27 14:26:06 -0700184
Ilya Matyukhin04247242021-07-02 20:34:52 +0000185 // Call the method.
186 ASSERT_TRUE(mHal->getSensorProps(&sensorProps).isOk());
Ilya Matyukhin14412df2020-08-27 14:26:06 -0700187
Ilya Matyukhin04247242021-07-02 20:34:52 +0000188 // Make sure the sensorProps aren't empty.
189 ASSERT_FALSE(sensorProps.empty());
190 ASSERT_FALSE(sensorProps[0].commonProps.componentInfo.empty());
191}
192
193TEST_P(Fingerprint, EnrollWithBadHatResultsInErrorTest) {
194 // Call the method.
195 auto hat = keymaster::HardwareAuthToken{};
Ilya Matyukhin5e09b822021-02-26 12:24:18 -0800196 std::shared_ptr<common::ICancellationSignal> cancellationSignal;
Ilya Matyukhin04247242021-07-02 20:34:52 +0000197 ASSERT_TRUE(mSession->enroll(hat, &cancellationSignal).isOk());
Ilya Matyukhin14412df2020-08-27 14:26:06 -0700198
Ilya Matyukhin04247242021-07-02 20:34:52 +0000199 // Make sure an error is returned.
200 auto lock = std::unique_lock{mCb->mMutex};
201 mCb->mCv.wait(lock, [this] { return mCb->mOnErrorInvoked; });
202}
Ilya Matyukhin5e09b822021-02-26 12:24:18 -0800203
Ilya Matyukhin04247242021-07-02 20:34:52 +0000204TEST_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
223TEST_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
235TEST_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
253TEST_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
262TEST_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
271TEST_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
280TEST_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; });
Ilya Matyukhin14412df2020-08-27 14:26:06 -0700287}
288
289GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Fingerprint);
290INSTANTIATE_TEST_SUITE_P(
291 IFingerprint, Fingerprint,
292 testing::ValuesIn(::android::getAidlHalInstanceNames(IFingerprint::descriptor)),
293 ::android::PrintInstanceNameToString);
294
295} // namespace
Ilya Matyukhin5e09b822021-02-26 12:24:18 -0800296} // namespace aidl::android::hardware::biometrics::fingerprint
Ilya Matyukhin14412df2020-08-27 14:26:06 -0700297
298int main(int argc, char** argv) {
299 ::testing::InitGoogleTest(&argc, argv);
300 ABinderProcess_setThreadPoolMaxThreadCount(1);
301 ABinderProcess_startThreadPool();
302 return RUN_ALL_TESTS();
303}