blob: 742d9335fd33854cfd4d3d6dc6f595d7edac8590 [file] [log] [blame]
Joe Bolingerde94aa02021-12-09 17:00:32 -08001/*
2 * Copyright (C) 2021 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 <aidl/android/hardware/biometrics/fingerprint/BnSessionCallback.h>
22
23#include "FakeFingerprintEngine.h"
24
25using namespace ::android::fingerprint::virt;
26using namespace ::aidl::android::hardware::biometrics::fingerprint;
27using namespace ::aidl::android::hardware::keymaster;
28
29namespace aidl::android::hardware::biometrics::fingerprint {
30
31class TestSessionCallback : public BnSessionCallback {
32 public:
33 ndk::ScopedAStatus onChallengeGenerated(int64_t challenge) override {
34 mLastChallenge = challenge;
35 return ndk::ScopedAStatus::ok();
36 };
37 ::ndk::ScopedAStatus onChallengeRevoked(int64_t challenge) override {
38 mLastChallengeRevoked = challenge;
39 return ndk::ScopedAStatus::ok();
40 };
41 ::ndk::ScopedAStatus onError(fingerprint::Error error, int32_t) override {
42 mError = error;
43 return ndk::ScopedAStatus::ok();
44 };
45 ::ndk::ScopedAStatus onEnrollmentProgress(int32_t enrollmentId, int32_t remaining) override {
46 if (remaining == 0) mLastEnrolled = enrollmentId;
47 return ndk::ScopedAStatus::ok();
48 };
49
50 ::ndk::ScopedAStatus onAuthenticationSucceeded(int32_t enrollmentId,
51 const keymaster::HardwareAuthToken&) override {
52 mLastAuthenticated = enrollmentId;
53 mAuthenticateFailed = false;
54 return ndk::ScopedAStatus::ok();
55 };
56 ::ndk::ScopedAStatus onAuthenticationFailed() override {
57 mLastAuthenticated = 0;
58 mAuthenticateFailed = true;
59 return ndk::ScopedAStatus::ok();
60 };
61 ::ndk::ScopedAStatus onInteractionDetected() override {
62 mInteractionDetectedCount++;
63 return ndk::ScopedAStatus::ok();
64 };
65 ndk::ScopedAStatus onAcquired(AcquiredInfo /*info*/, int32_t /*vendorCode*/) override {
66 return ndk::ScopedAStatus::ok();
67 }
68 ::ndk::ScopedAStatus onEnrollmentsEnumerated(
69 const std::vector<int32_t>& enrollmentIds) override {
70 mLastEnrollmentEnumerated = enrollmentIds;
71 return ndk::ScopedAStatus::ok();
72 };
73 ::ndk::ScopedAStatus onEnrollmentsRemoved(const std::vector<int32_t>& enrollmentIds) override {
74 mLastEnrollmentRemoved = enrollmentIds;
75 return ndk::ScopedAStatus::ok();
76 };
77 ::ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t authenticatorId) override {
78 mLastAuthenticatorId = authenticatorId;
79 return ndk::ScopedAStatus::ok();
80 };
81 ::ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t authenticatorId) override {
82 mLastAuthenticatorId = authenticatorId;
83 mAuthenticatorIdInvalidated = true;
84 return ndk::ScopedAStatus::ok();
85 };
86 ::ndk::ScopedAStatus onLockoutPermanent() override {
87 mLockoutPermanent = true;
88 return ndk::ScopedAStatus::ok();
89 };
90 ndk::ScopedAStatus onLockoutTimed(int64_t /* timeout */) override {
91 return ndk::ScopedAStatus::ok();
92 }
93 ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); }
94 ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
95
96 Error mError = Error::UNKNOWN;
97 int64_t mLastChallenge = -1;
98 int64_t mLastChallengeRevoked = -1;
99 int32_t mLastEnrolled = -1;
100 int32_t mLastAuthenticated = -1;
101 int64_t mLastAuthenticatorId = -1;
102 std::vector<int32_t> mLastEnrollmentEnumerated;
103 std::vector<int32_t> mLastEnrollmentRemoved;
104 bool mAuthenticateFailed = false;
105 bool mAuthenticatorIdInvalidated = false;
106 bool mLockoutPermanent = false;
107 int mInteractionDetectedCount = 0;
108};
109
110class FakeFingerprintEngineTest : public ::testing::Test {
111 protected:
112 void SetUp() override {
113 FingerprintHalProperties::operation_enroll_latency(0);
114 FingerprintHalProperties::operation_authenticate_latency(0);
115 FingerprintHalProperties::operation_detect_interaction_latency(0);
116 mCallback = ndk::SharedRefBase::make<TestSessionCallback>();
117 }
118
119 FakeFingerprintEngine mEngine;
120 std::shared_ptr<TestSessionCallback> mCallback;
121 std::promise<void> mCancel;
122};
123
124TEST_F(FakeFingerprintEngineTest, GenerateChallenge) {
125 mEngine.generateChallengeImpl(mCallback.get());
126 ASSERT_EQ(FingerprintHalProperties::challenge().value(), mCallback->mLastChallenge);
127}
128
129TEST_F(FakeFingerprintEngineTest, RevokeChallenge) {
130 auto challenge = FingerprintHalProperties::challenge().value_or(10);
131 mEngine.revokeChallengeImpl(mCallback.get(), challenge);
132 ASSERT_FALSE(FingerprintHalProperties::challenge().has_value());
133 ASSERT_EQ(challenge, mCallback->mLastChallengeRevoked);
134}
135
136TEST_F(FakeFingerprintEngineTest, ResetLockout) {
137 FingerprintHalProperties::lockout(true);
138 mEngine.resetLockoutImpl(mCallback.get(), {});
139 ASSERT_FALSE(FingerprintHalProperties::lockout().value_or(true));
140}
141
142TEST_F(FakeFingerprintEngineTest, AuthenticatorId) {
143 FingerprintHalProperties::authenticator_id(50);
144 mEngine.getAuthenticatorIdImpl(mCallback.get());
145 ASSERT_EQ(50, mCallback->mLastAuthenticatorId);
146 ASSERT_FALSE(mCallback->mAuthenticatorIdInvalidated);
147}
148
149TEST_F(FakeFingerprintEngineTest, AuthenticatorIdInvalidate) {
150 FingerprintHalProperties::authenticator_id(500);
151 mEngine.invalidateAuthenticatorIdImpl(mCallback.get());
152 ASSERT_NE(500, FingerprintHalProperties::authenticator_id().value());
153 ASSERT_TRUE(mCallback->mAuthenticatorIdInvalidated);
154}
155
156TEST_F(FakeFingerprintEngineTest, Enroll) {
157 FingerprintHalProperties::enrollments({});
158 FingerprintHalProperties::next_enrollment("4:0,0:true");
159 keymaster::HardwareAuthToken hat{.mac = {2, 4}};
160 mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future());
161 ASSERT_FALSE(FingerprintHalProperties::next_enrollment().has_value());
162 ASSERT_EQ(1, FingerprintHalProperties::enrollments().size());
163 ASSERT_EQ(4, FingerprintHalProperties::enrollments()[0].value());
164 ASSERT_EQ(4, mCallback->mLastEnrolled);
165}
166
167TEST_F(FakeFingerprintEngineTest, EnrollCancel) {
168 FingerprintHalProperties::enrollments({});
169 auto next = "4:0,0:true";
170 FingerprintHalProperties::next_enrollment(next);
171 keymaster::HardwareAuthToken hat{.mac = {2, 4}};
172 mCancel.set_value();
173 mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future());
174 ASSERT_EQ(Error::CANCELED, mCallback->mError);
175 ASSERT_EQ(-1, mCallback->mLastEnrolled);
176 ASSERT_EQ(0, FingerprintHalProperties::enrollments().size());
177 ASSERT_EQ(next, FingerprintHalProperties::next_enrollment().value_or(""));
178}
179
180TEST_F(FakeFingerprintEngineTest, EnrollFail) {
181 FingerprintHalProperties::enrollments({});
182 auto next = "2:0,0:false";
183 FingerprintHalProperties::next_enrollment(next);
184 keymaster::HardwareAuthToken hat{.mac = {2, 4}};
185 mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future());
186 ASSERT_EQ(Error::UNABLE_TO_PROCESS, mCallback->mError);
187 ASSERT_EQ(-1, mCallback->mLastEnrolled);
188 ASSERT_EQ(0, FingerprintHalProperties::enrollments().size());
189 ASSERT_FALSE(FingerprintHalProperties::next_enrollment().has_value());
190}
191
192TEST_F(FakeFingerprintEngineTest, Authenticate) {
193 FingerprintHalProperties::enrollments({1, 2});
194 FingerprintHalProperties::enrollment_hit(2);
195 mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
196 ASSERT_FALSE(mCallback->mAuthenticateFailed);
197 ASSERT_EQ(2, mCallback->mLastAuthenticated);
198}
199
200TEST_F(FakeFingerprintEngineTest, AuthenticateCancel) {
201 FingerprintHalProperties::enrollments({2});
202 FingerprintHalProperties::enrollment_hit(2);
203 mCancel.set_value();
204 mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
205 ASSERT_EQ(Error::CANCELED, mCallback->mError);
206 ASSERT_EQ(-1, mCallback->mLastAuthenticated);
207}
208
209TEST_F(FakeFingerprintEngineTest, AuthenticateNotSet) {
210 FingerprintHalProperties::enrollments({1, 2});
211 FingerprintHalProperties::enrollment_hit({});
212 mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
213 ASSERT_TRUE(mCallback->mAuthenticateFailed);
214 ASSERT_EQ(mCallback->mError, Error::UNABLE_TO_PROCESS);
215}
216
217TEST_F(FakeFingerprintEngineTest, AuthenticateNotEnrolled) {
218 FingerprintHalProperties::enrollments({1, 2});
219 FingerprintHalProperties::enrollment_hit(3);
220 mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
221 ASSERT_TRUE(mCallback->mAuthenticateFailed);
222 ASSERT_EQ(mCallback->mError, Error::UNABLE_TO_PROCESS);
223}
224
225TEST_F(FakeFingerprintEngineTest, AuthenticateLockout) {
226 FingerprintHalProperties::enrollments({22, 2});
227 FingerprintHalProperties::enrollment_hit(2);
228 FingerprintHalProperties::lockout(true);
229 mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
230 ASSERT_TRUE(mCallback->mLockoutPermanent);
231 ASSERT_NE(mCallback->mError, Error::UNKNOWN);
232}
233
234TEST_F(FakeFingerprintEngineTest, InteractionDetect) {
235 FingerprintHalProperties::enrollments({1, 2});
236 FingerprintHalProperties::enrollment_hit(2);
237 mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
238 ASSERT_EQ(1, mCallback->mInteractionDetectedCount);
239}
240
241TEST_F(FakeFingerprintEngineTest, InteractionDetectCancel) {
242 FingerprintHalProperties::enrollments({1, 2});
243 FingerprintHalProperties::enrollment_hit(2);
244 mCancel.set_value();
245 mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
246 ASSERT_EQ(Error::CANCELED, mCallback->mError);
247 ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
248}
249
250TEST_F(FakeFingerprintEngineTest, InteractionDetectNotSet) {
251 FingerprintHalProperties::enrollments({1, 2});
252 FingerprintHalProperties::enrollment_hit({});
253 mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
254 ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
255}
256
257TEST_F(FakeFingerprintEngineTest, InteractionDetectNotEnrolled) {
258 FingerprintHalProperties::enrollments({1, 2});
259 FingerprintHalProperties::enrollment_hit(25);
260 mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
261 ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
262}
263
264TEST_F(FakeFingerprintEngineTest, EnumerateEnrolled) {
265 FingerprintHalProperties::enrollments({2, 4, 8});
266 mEngine.enumerateEnrollmentsImpl(mCallback.get());
267 ASSERT_EQ(3, mCallback->mLastEnrollmentEnumerated.size());
268 for (auto id : FingerprintHalProperties::enrollments()) {
269 ASSERT_TRUE(std::find(mCallback->mLastEnrollmentEnumerated.begin(),
270 mCallback->mLastEnrollmentEnumerated.end(),
271 id) != mCallback->mLastEnrollmentEnumerated.end());
272 }
273}
274
275TEST_F(FakeFingerprintEngineTest, RemoveEnrolled) {
276 FingerprintHalProperties::enrollments({2, 4, 8, 1});
277 mEngine.removeEnrollmentsImpl(mCallback.get(), {2, 8});
278 auto enrolls = FingerprintHalProperties::enrollments();
279 ASSERT_EQ(2, mCallback->mLastEnrollmentRemoved.size());
280 for (auto id : {2, 8}) {
281 ASSERT_TRUE(std::find(mCallback->mLastEnrollmentRemoved.begin(),
282 mCallback->mLastEnrollmentRemoved.end(),
283 id) != mCallback->mLastEnrollmentRemoved.end());
284 }
285 ASSERT_EQ(2, enrolls.size());
286 for (auto id : {1, 4}) {
287 ASSERT_TRUE(std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end());
288 }
289}
290
291} // namespace aidl::android::hardware::biometrics::fingerprint
292
293int main(int argc, char** argv) {
294 testing::InitGoogleTest(&argc, argv);
295 ABinderProcess_startThreadPool();
296 return RUN_ALL_TESTS();
297}