blob: d448532a8daacffb8fdc150bf4f7f20d63b1ab23 [file] [log] [blame]
Joshua McCloskeydb009a52022-05-10 05:18:20 +00001/*
2 * Copyright (C) 2022 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 <face.sysprop.h>
19#include <gtest/gtest.h>
20
21#include <aidl/android/hardware/biometrics/face/BnSessionCallback.h>
22#include <android-base/logging.h>
23
Jeff Pua3c57362024-06-10 15:03:50 +000024#include "Face.h"
Joshua McCloskeydb009a52022-05-10 05:18:20 +000025#include "FakeFaceEngine.h"
Jeff Pu4aca35e2024-01-04 22:40:33 +000026#include "util/Util.h"
Joshua McCloskeydb009a52022-05-10 05:18:20 +000027
28using namespace ::android::face::virt;
29using namespace ::aidl::android::hardware::biometrics::face;
30using namespace ::aidl::android::hardware::keymaster;
31
32namespace aidl::android::hardware::biometrics::face {
33
34class TestSessionCallback : public BnSessionCallback {
35 public:
36 ndk::ScopedAStatus onChallengeGenerated(int64_t challenge) override {
37 mLastChallenge = challenge;
38 return ndk::ScopedAStatus::ok();
39 };
40 ::ndk::ScopedAStatus onChallengeRevoked(int64_t challenge) override {
41 mLastChallengeRevoked = challenge;
42 return ndk::ScopedAStatus::ok();
43 };
44 ::ndk::ScopedAStatus onError(Error error, int32_t) override {
45 mError = error;
46 return ndk::ScopedAStatus::ok();
47 };
48 ::ndk::ScopedAStatus onEnrollmentProgress(int32_t enrollmentId, int32_t remaining) override {
49 if (remaining == 0) mLastEnrolled = enrollmentId;
Jeff Pu84c60182023-12-04 16:53:04 +000050 mRemaining = remaining;
Joshua McCloskeydb009a52022-05-10 05:18:20 +000051 return ndk::ScopedAStatus::ok();
52 };
53
54 ::ndk::ScopedAStatus onAuthenticationSucceeded(int32_t enrollmentId,
55 const HardwareAuthToken&) override {
56 mLastAuthenticated = enrollmentId;
57 mAuthenticateFailed = false;
58 return ndk::ScopedAStatus::ok();
59 };
60 ::ndk::ScopedAStatus onAuthenticationFailed() override {
61 mLastAuthenticated = 0;
62 mAuthenticateFailed = true;
63 return ndk::ScopedAStatus::ok();
64 };
65 ::ndk::ScopedAStatus onInteractionDetected() override {
66 mInteractionDetectedCount++;
67 return ndk::ScopedAStatus::ok();
68 };
69
70 ::ndk::ScopedAStatus onEnrollmentFrame(const EnrollmentFrame& frame) override {
71 mEnrollmentFrames.push_back(frame.data.vendorCode);
72 return ndk::ScopedAStatus::ok();
73 }
74
75 ::ndk::ScopedAStatus onEnrollmentsEnumerated(
76 const std::vector<int32_t>& enrollmentIds) override {
77 mLastEnrollmentsEnumerated = enrollmentIds;
78 return ndk::ScopedAStatus::ok();
79 };
80 ::ndk::ScopedAStatus onEnrollmentsRemoved(const std::vector<int32_t>& enrollmentIds) override {
81 mLastEnrollmentRemoved = enrollmentIds;
82 return ndk::ScopedAStatus::ok();
83 };
84 ::ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t authenticatorId) override {
85 mLastAuthenticatorId = authenticatorId;
86 return ndk::ScopedAStatus::ok();
87 };
88 ::ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t authenticatorId) override {
89 mLastAuthenticatorId = authenticatorId;
90 mAuthenticatorIdInvalidated = true;
91 return ndk::ScopedAStatus::ok();
92 };
93 ::ndk::ScopedAStatus onAuthenticationFrame(const AuthenticationFrame& /*authFrame*/) override {
94 return ndk::ScopedAStatus::ok();
95 }
96 ::ndk::ScopedAStatus onLockoutPermanent() override {
97 mLockoutPermanent = true;
98 return ndk::ScopedAStatus::ok();
99 };
100 ::ndk::ScopedAStatus onLockoutTimed(int64_t /* timeout */) override {
101 return ndk::ScopedAStatus::ok();
102 }
103 ::ndk::ScopedAStatus onLockoutCleared() override {
104 mLockoutPermanent = false;
105 return ndk::ScopedAStatus::ok();
106 }
107 ::ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
108
109 ::ndk::ScopedAStatus onFeaturesRetrieved(const std::vector<Feature>& features) override {
110 mFeatures = features;
111 return ndk::ScopedAStatus::ok();
112 }
113
114 ::ndk::ScopedAStatus onFeatureSet(Feature feature) override {
115 mLastFeatureSet = feature;
116 return ndk::ScopedAStatus::ok();
117 }
118
119 Error mError = Error::UNKNOWN;
120 int64_t mLastChallenge = -1;
121 int64_t mLastChallengeRevoked = -1;
122 int32_t mLastEnrolled = -1;
123 int32_t mLastAuthenticated = -1;
124 int64_t mLastAuthenticatorId = -1;
125 std::vector<int32_t> mLastEnrollmentsEnumerated;
126 std::vector<int32_t> mLastEnrollmentRemoved;
127 std::vector<Feature> mFeatures;
128 Feature mLastFeatureSet;
129 std::vector<int32_t> mEnrollmentFrames;
130 bool mAuthenticateFailed = false;
131 bool mAuthenticatorIdInvalidated = false;
132 bool mLockoutPermanent = false;
133 int mInteractionDetectedCount = 0;
Jeff Pu84c60182023-12-04 16:53:04 +0000134 int mRemaining = -1;
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000135};
136
137class FakeFaceEngineTest : public ::testing::Test {
138 protected:
139 void SetUp() override {
140 LOG(ERROR) << "JRM SETUP";
141 mCallback = ndk::SharedRefBase::make<TestSessionCallback>();
Jeff Pu4aca35e2024-01-04 22:40:33 +0000142 }
143
144 void TearDown() override {
Jeff Pua3c57362024-06-10 15:03:50 +0000145 Face::cfg().setopt<OptIntVec>("enrollments", {});
146 Face::cfg().set<std::int64_t>("challenge", 0);
147 Face::cfg().setopt<OptIntVec>("features", {});
148 Face::cfg().set<std::int64_t>("authenticator_id", 0);
149 Face::cfg().set<std::string>("strength", "");
150 Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {});
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000151 }
152
153 FakeFaceEngine mEngine;
154 std::shared_ptr<TestSessionCallback> mCallback;
155 std::promise<void> mCancel;
156};
157
158TEST_F(FakeFaceEngineTest, one_eq_one) {
159 ASSERT_EQ(1, 1);
160}
161
162TEST_F(FakeFaceEngineTest, GenerateChallenge) {
163 mEngine.generateChallengeImpl(mCallback.get());
Jeff Pua3c57362024-06-10 15:03:50 +0000164 ASSERT_EQ(Face::cfg().get<std::int64_t>("challenge"), mCallback->mLastChallenge);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000165}
166
167TEST_F(FakeFaceEngineTest, RevokeChallenge) {
Jeff Pua3c57362024-06-10 15:03:50 +0000168 auto challenge = Face::cfg().get<std::int64_t>("challenge");
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000169 mEngine.revokeChallengeImpl(mCallback.get(), challenge);
Jeff Pua3c57362024-06-10 15:03:50 +0000170 ASSERT_FALSE(Face::cfg().get<std::int64_t>("challenge"));
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000171 ASSERT_EQ(challenge, mCallback->mLastChallengeRevoked);
172}
173
174TEST_F(FakeFaceEngineTest, ResetLockout) {
Jeff Pua3c57362024-06-10 15:03:50 +0000175 Face::cfg().set<bool>("lockout", true);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000176 mEngine.resetLockoutImpl(mCallback.get(), {});
177 ASSERT_FALSE(mCallback->mLockoutPermanent);
Jeff Pua3c57362024-06-10 15:03:50 +0000178 ASSERT_FALSE(Face::cfg().get<bool>("lockout"));
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000179}
180
181TEST_F(FakeFaceEngineTest, AuthenticatorId) {
Jeff Pua3c57362024-06-10 15:03:50 +0000182 Face::cfg().set<std::int64_t>("authenticator_id", 50);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000183 mEngine.getAuthenticatorIdImpl(mCallback.get());
184 ASSERT_EQ(50, mCallback->mLastAuthenticatorId);
185 ASSERT_FALSE(mCallback->mAuthenticatorIdInvalidated);
186}
187
188TEST_F(FakeFaceEngineTest, GetAuthenticatorIdWeakReturnsZero) {
Jeff Pua3c57362024-06-10 15:03:50 +0000189 Face::cfg().set<std::string>("strength", "weak");
190 Face::cfg().set<std::int64_t>("authenticator_id", 500);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000191 mEngine.getAuthenticatorIdImpl(mCallback.get());
192 ASSERT_EQ(0, mCallback->mLastAuthenticatorId);
193 ASSERT_FALSE(mCallback->mAuthenticatorIdInvalidated);
194}
195
196TEST_F(FakeFaceEngineTest, AuthenticatorIdInvalidate) {
Jeff Pua3c57362024-06-10 15:03:50 +0000197 Face::cfg().set<std::int64_t>("authenticator_id", 500);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000198 mEngine.invalidateAuthenticatorIdImpl(mCallback.get());
Jeff Pua3c57362024-06-10 15:03:50 +0000199 ASSERT_NE(500, Face::cfg().get<std::int64_t>("authenticator_id"));
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000200 ASSERT_TRUE(mCallback->mAuthenticatorIdInvalidated);
201}
202
203TEST_F(FakeFaceEngineTest, Enroll) {
Jeff Pua3c57362024-06-10 15:03:50 +0000204 Face::cfg().set<std::string>("next_enrollment",
205 "1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:true");
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000206 keymaster::HardwareAuthToken hat{.mac = {2, 4}};
207 mEngine.enrollImpl(mCallback.get(), hat, {} /*enrollmentType*/, {} /*features*/,
208 mCancel.get_future());
Jeff Pua3c57362024-06-10 15:03:50 +0000209 ASSERT_FALSE(Face::cfg().getopt<OptString>("next_enrollment").has_value());
210 ASSERT_EQ(1, Face::cfg().getopt<OptIntVec>("enrollments").size());
211 ASSERT_EQ(1, Face::cfg().getopt<OptIntVec>("enrollments")[0].value());
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000212 ASSERT_EQ(1, mCallback->mLastEnrolled);
Jeff Pu84c60182023-12-04 16:53:04 +0000213 ASSERT_EQ(0, mCallback->mRemaining);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000214}
215
216TEST_F(FakeFaceEngineTest, EnrollFails) {
Jeff Pua3c57362024-06-10 15:03:50 +0000217 Face::cfg().set<std::string>("next_enrollment",
218 "1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:false");
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000219 keymaster::HardwareAuthToken hat{.mac = {2, 4}};
220 mEngine.enrollImpl(mCallback.get(), hat, {} /*enrollmentType*/, {} /*features*/,
221 mCancel.get_future());
Jeff Pua3c57362024-06-10 15:03:50 +0000222 ASSERT_FALSE(Face::cfg().getopt<OptString>("next_enrollment").has_value());
223 ASSERT_EQ(0, Face::cfg().getopt<OptIntVec>("enrollments").size());
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000224}
225
226TEST_F(FakeFaceEngineTest, EnrollCancel) {
Jeff Pua3c57362024-06-10 15:03:50 +0000227 Face::cfg().set<std::string>("next_enrollment", "1:2000-[21,8,9],300:false");
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000228 keymaster::HardwareAuthToken hat{.mac = {2, 4}};
229 mCancel.set_value();
230 mEngine.enrollImpl(mCallback.get(), hat, {} /*enrollmentType*/, {} /*features*/,
231 mCancel.get_future());
232 ASSERT_EQ(Error::CANCELED, mCallback->mError);
233 ASSERT_EQ(-1, mCallback->mLastEnrolled);
Jeff Pua3c57362024-06-10 15:03:50 +0000234 ASSERT_EQ(0, Face::cfg().getopt<OptIntVec>("enrollments").size());
235 ASSERT_FALSE(Face::cfg().get<std::string>("next_enrollment").empty());
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000236}
237
238TEST_F(FakeFaceEngineTest, Authenticate) {
Jeff Pua3c57362024-06-10 15:03:50 +0000239 Face::cfg().setopt<OptIntVec>("enrollments", {100});
240 Face::cfg().set<std::int32_t>("enrollment_hit", 100);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000241 mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
242
243 ASSERT_EQ(100, mCallback->mLastAuthenticated);
244 ASSERT_FALSE(mCallback->mAuthenticateFailed);
245}
246
247TEST_F(FakeFaceEngineTest, AuthenticateCancel) {
Jeff Pua3c57362024-06-10 15:03:50 +0000248 Face::cfg().setopt<OptIntVec>("enrollments", {100});
249 Face::cfg().set<std::int32_t>("enrollment_hit", 100);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000250 mCancel.set_value();
251 mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
252 ASSERT_EQ(Error::CANCELED, mCallback->mError);
253}
254
255TEST_F(FakeFaceEngineTest, AuthenticateFailedForUnEnrolled) {
Jeff Pua3c57362024-06-10 15:03:50 +0000256 Face::cfg().setopt<OptIntVec>("enrollments", {3});
257 Face::cfg().set<std::int32_t>("enrollment_hit", 100);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000258 mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
Jeff Pu484d2e72023-09-25 15:11:19 +0000259 ASSERT_EQ(Error::TIMEOUT, mCallback->mError);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000260 ASSERT_TRUE(mCallback->mAuthenticateFailed);
261}
262
263TEST_F(FakeFaceEngineTest, DetectInteraction) {
Jeff Pua3c57362024-06-10 15:03:50 +0000264 Face::cfg().setopt<OptIntVec>("enrollments", {100});
265 Face::cfg().set<std::int32_t>("enrollment_hit", 100);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000266 ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
267 mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
268 ASSERT_EQ(1, mCallback->mInteractionDetectedCount);
269}
270
271TEST_F(FakeFaceEngineTest, DetectInteractionCancel) {
Jeff Pua3c57362024-06-10 15:03:50 +0000272 Face::cfg().setopt<OptIntVec>("enrollments", {100});
273 Face::cfg().set<std::int32_t>("enrollment_hit", 100);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000274 mCancel.set_value();
275 mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
276 ASSERT_EQ(Error::CANCELED, mCallback->mError);
277}
278
279TEST_F(FakeFaceEngineTest, GetFeatureEmpty) {
280 mEngine.getFeaturesImpl(mCallback.get());
281 ASSERT_TRUE(mCallback->mFeatures.empty());
282}
283
284TEST_F(FakeFaceEngineTest, SetFeature) {
Jeff Pua3c57362024-06-10 15:03:50 +0000285 Face::cfg().setopt<OptIntVec>("enrollments", {1});
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000286 keymaster::HardwareAuthToken hat{.mac = {2, 4}};
287 mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
288 auto features = mCallback->mFeatures;
289 ASSERT_TRUE(features.empty());
290 ASSERT_EQ(Feature::REQUIRE_ATTENTION, mCallback->mLastFeatureSet);
291
292 mEngine.getFeaturesImpl(mCallback.get());
293 features = mCallback->mFeatures;
294 ASSERT_FALSE(features.empty());
295 ASSERT_NE(features.end(),
296 std::find(features.begin(), features.end(), Feature::REQUIRE_ATTENTION));
297}
298
299TEST_F(FakeFaceEngineTest, ToggleFeature) {
Jeff Pua3c57362024-06-10 15:03:50 +0000300 Face::cfg().setopt<OptIntVec>("enrollments", {1});
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000301 keymaster::HardwareAuthToken hat{.mac = {2, 4}};
302 mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
303 mEngine.getFeaturesImpl(mCallback.get());
304 auto features = mCallback->mFeatures;
305 ASSERT_FALSE(features.empty());
306 ASSERT_NE(features.end(),
307 std::find(features.begin(), features.end(), Feature::REQUIRE_ATTENTION));
308
309 mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, false);
310 mEngine.getFeaturesImpl(mCallback.get());
311 features = mCallback->mFeatures;
312 ASSERT_TRUE(features.empty());
313}
314
315TEST_F(FakeFaceEngineTest, TurningOffNonExistentFeatureDoesNothing) {
Jeff Pua3c57362024-06-10 15:03:50 +0000316 Face::cfg().setopt<OptIntVec>("enrollments", {1});
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000317 keymaster::HardwareAuthToken hat{.mac = {2, 4}};
318 mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, false);
319 mEngine.getFeaturesImpl(mCallback.get());
320 auto features = mCallback->mFeatures;
321 ASSERT_TRUE(features.empty());
322}
323
324TEST_F(FakeFaceEngineTest, SetMultipleFeatures) {
Jeff Pua3c57362024-06-10 15:03:50 +0000325 Face::cfg().setopt<OptIntVec>("enrollments", {1});
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000326 keymaster::HardwareAuthToken hat{.mac = {2, 4}};
327 mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
328 mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_DIVERSE_POSES, true);
329 mEngine.setFeatureImpl(mCallback.get(), hat, Feature::DEBUG, true);
330 mEngine.getFeaturesImpl(mCallback.get());
331 auto features = mCallback->mFeatures;
332 ASSERT_EQ(3, features.size());
333 ASSERT_NE(features.end(),
334 std::find(features.begin(), features.end(), Feature::REQUIRE_ATTENTION));
335 ASSERT_NE(features.end(),
336 std::find(features.begin(), features.end(), Feature::REQUIRE_DIVERSE_POSES));
337 ASSERT_NE(features.end(), std::find(features.begin(), features.end(), Feature::DEBUG));
338}
339
340TEST_F(FakeFaceEngineTest, SetMultipleFeaturesAndTurnOffSome) {
Jeff Pua3c57362024-06-10 15:03:50 +0000341 Face::cfg().setopt<OptIntVec>("enrollments", {1});
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000342 keymaster::HardwareAuthToken hat{.mac = {2, 4}};
343 mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
344 mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_DIVERSE_POSES, true);
345 mEngine.setFeatureImpl(mCallback.get(), hat, Feature::DEBUG, true);
346 mEngine.setFeatureImpl(mCallback.get(), hat, Feature::DEBUG, false);
347 mEngine.getFeaturesImpl(mCallback.get());
348 auto features = mCallback->mFeatures;
349 ASSERT_EQ(2, features.size());
350 ASSERT_NE(features.end(),
351 std::find(features.begin(), features.end(), Feature::REQUIRE_ATTENTION));
352 ASSERT_NE(features.end(),
353 std::find(features.begin(), features.end(), Feature::REQUIRE_DIVERSE_POSES));
354 ASSERT_EQ(features.end(), std::find(features.begin(), features.end(), Feature::DEBUG));
355}
356
357TEST_F(FakeFaceEngineTest, Enumerate) {
Jeff Pua3c57362024-06-10 15:03:50 +0000358 Face::cfg().setopt<OptIntVec>("enrollments", {120, 3});
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000359 mEngine.enumerateEnrollmentsImpl(mCallback.get());
360 auto enrolls = mCallback->mLastEnrollmentsEnumerated;
361 ASSERT_FALSE(enrolls.empty());
362 ASSERT_NE(enrolls.end(), std::find(enrolls.begin(), enrolls.end(), 120));
363 ASSERT_NE(enrolls.end(), std::find(enrolls.begin(), enrolls.end(), 3));
364}
365
366TEST_F(FakeFaceEngineTest, RemoveEnrollments) {
Jeff Pua3c57362024-06-10 15:03:50 +0000367 Face::cfg().setopt<OptIntVec>("enrollments", {120, 3, 100});
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000368 mEngine.removeEnrollmentsImpl(mCallback.get(), {120, 100});
369 mEngine.enumerateEnrollmentsImpl(mCallback.get());
370 auto enrolls = mCallback->mLastEnrollmentsEnumerated;
371 ASSERT_FALSE(enrolls.empty());
372 ASSERT_EQ(enrolls.end(), std::find(enrolls.begin(), enrolls.end(), 120));
373 ASSERT_NE(enrolls.end(), std::find(enrolls.begin(), enrolls.end(), 3));
374 ASSERT_EQ(enrolls.end(), std::find(enrolls.begin(), enrolls.end(), 100));
375}
376
377TEST_F(FakeFaceEngineTest, ResetLockoutWithAuth) {
Jeff Pua3c57362024-06-10 15:03:50 +0000378 Face::cfg().set<bool>("lockout", true);
379 Face::cfg().setopt<OptIntVec>("enrollments", {33});
380 Face::cfg().set<std::int32_t>("enrollment_hit", 33);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000381 auto cancelFuture = mCancel.get_future();
382 mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, cancelFuture);
383
384 ASSERT_TRUE(mCallback->mLockoutPermanent);
385
386 mEngine.resetLockoutImpl(mCallback.get(), {} /* hat */);
387 ASSERT_FALSE(mCallback->mLockoutPermanent);
Jeff Pua3c57362024-06-10 15:03:50 +0000388 Face::cfg().set<std::int32_t>("enrollment_hit", 33);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000389 mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, cancelFuture);
390 ASSERT_EQ(33, mCallback->mLastAuthenticated);
391 ASSERT_FALSE(mCallback->mAuthenticateFailed);
392}
393
Jeff Pu4aca35e2024-01-04 22:40:33 +0000394TEST_F(FakeFaceEngineTest, LatencyDefault) {
Jeff Pua3c57362024-06-10 15:03:50 +0000395 Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {});
396 ASSERT_EQ(DEFAULT_LATENCY, mEngine.getLatency(Face::cfg().getopt<OptIntVec>(
397 "operation_detect_interaction_latency")));
Jeff Pu4aca35e2024-01-04 22:40:33 +0000398}
399
400TEST_F(FakeFaceEngineTest, LatencyFixed) {
Jeff Pua3c57362024-06-10 15:03:50 +0000401 Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {10});
402 ASSERT_EQ(10, mEngine.getLatency(
403 Face::cfg().getopt<OptIntVec>("operation_detect_interaction_latency")));
Jeff Pu4aca35e2024-01-04 22:40:33 +0000404}
405
406TEST_F(FakeFaceEngineTest, LatencyRandom) {
Jeff Pua3c57362024-06-10 15:03:50 +0000407 Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {1, 1000});
Jeff Pu4aca35e2024-01-04 22:40:33 +0000408 std::set<int32_t> latencySet;
409 for (int i = 0; i < 100; i++) {
Jeff Pua3c57362024-06-10 15:03:50 +0000410 auto x = mEngine.getLatency(
411 Face::cfg().getopt<OptIntVec>("operation_detect_interaction_latency"));
Jeff Pu4aca35e2024-01-04 22:40:33 +0000412 ASSERT_TRUE(x >= 1 && x <= 1000);
413 latencySet.insert(x);
414 }
415 ASSERT_TRUE(latencySet.size() > 95); // unique values
416}
417
Jeff Pu484d2e72023-09-25 15:11:19 +0000418} // namespace aidl::android::hardware::biometrics::face