1 /*
2  * Copyright (C) 2019 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 #define LOG_TAG "biometrics_face_hidl_hal_test"
18 
19 #include <android/hardware/biometrics/face/1.0/IBiometricsFace.h>
20 #include <android/hardware/biometrics/face/1.0/IBiometricsFaceClientCallback.h>
21 
22 #include <VtsHalHidlTargetCallbackBase.h>
23 #include <android-base/logging.h>
24 #include <gtest/gtest.h>
25 #include <hidl/GtestPrinter.h>
26 #include <hidl/ServiceManagement.h>
27 
28 #include <chrono>
29 #include <cstdint>
30 #include <random>
31 
32 using android::sp;
33 using android::hardware::hidl_vec;
34 using android::hardware::Return;
35 using android::hardware::Void;
36 using android::hardware::biometrics::face::V1_0::FaceAcquiredInfo;
37 using android::hardware::biometrics::face::V1_0::FaceError;
38 using android::hardware::biometrics::face::V1_0::Feature;
39 using android::hardware::biometrics::face::V1_0::IBiometricsFace;
40 using android::hardware::biometrics::face::V1_0::IBiometricsFaceClientCallback;
41 using android::hardware::biometrics::face::V1_0::OptionalBool;
42 using android::hardware::biometrics::face::V1_0::OptionalUint64;
43 using android::hardware::biometrics::face::V1_0::Status;
44 
45 namespace {
46 
47 // Arbitrary, nonexistent userId
48 constexpr uint32_t kUserId = 9;
49 // Arbitrary, nonexistent faceId
50 constexpr uint32_t kFaceId = 5;
51 constexpr uint32_t kTimeoutSec = 3;
52 constexpr auto kTimeout = std::chrono::seconds(kTimeoutSec);
53 constexpr int kGenerateChallengeIterations = 10;
54 constexpr char kFacedataDir[] = "/data/vendor_de/0/facedata";
55 constexpr char kCallbackNameOnEnrollResult[] = "onEnrollResult";
56 constexpr char kCallbackNameOnAuthenticated[] = "onAuthenticated";
57 constexpr char kCallbackNameOnAcquired[] = "onAcquired";
58 constexpr char kCallbackNameOnError[] = "onError";
59 constexpr char kCallbackNameOnRemoved[] = "onRemoved";
60 constexpr char kCallbackNameOnEnumerate[] = "onEnumerate";
61 constexpr char kCallbackNameOnLockoutChanged[] = "onLockoutChanged";
62 
63 // Callback arguments that need to be captured for the tests.
64 struct FaceCallbackArgs {
65     // The error passed to the last onError() callback.
66     FaceError error;
67 
68     // The userId passed to the last callback.
69     int32_t userId;
70 };
71 
72 // Test callback class for the BiometricsFace HAL.
73 // The HAL will call these callback methods to notify about completed operations
74 // or encountered errors.
75 class FaceCallback : public ::testing::VtsHalHidlTargetCallbackBase<FaceCallbackArgs>,
76                      public IBiometricsFaceClientCallback {
77   public:
onEnrollResult(uint64_t,uint32_t,int32_t userId,uint32_t)78     Return<void> onEnrollResult(uint64_t, uint32_t, int32_t userId, uint32_t) override {
79         FaceCallbackArgs args = {};
80         args.userId = userId;
81         NotifyFromCallback(kCallbackNameOnEnrollResult, args);
82         return Void();
83     }
84 
onAuthenticated(uint64_t,uint32_t,int32_t userId,const hidl_vec<uint8_t> &)85     Return<void> onAuthenticated(uint64_t, uint32_t, int32_t userId,
86                                  const hidl_vec<uint8_t>&) override {
87         FaceCallbackArgs args = {};
88         args.userId = userId;
89         NotifyFromCallback(kCallbackNameOnAuthenticated, args);
90         return Void();
91     }
92 
onAcquired(uint64_t,int32_t userId,FaceAcquiredInfo,int32_t)93     Return<void> onAcquired(uint64_t, int32_t userId, FaceAcquiredInfo, int32_t) override {
94         FaceCallbackArgs args = {};
95         args.userId = userId;
96         NotifyFromCallback(kCallbackNameOnAcquired, args);
97         return Void();
98     }
99 
onError(uint64_t,int32_t userId,FaceError error,int32_t)100     Return<void> onError(uint64_t, int32_t userId, FaceError error, int32_t) override {
101         FaceCallbackArgs args = {};
102         args.error = error;
103         args.userId = userId;
104         NotifyFromCallback(kCallbackNameOnError, args);
105         return Void();
106     }
107 
onRemoved(uint64_t,const hidl_vec<uint32_t> &,int32_t userId)108     Return<void> onRemoved(uint64_t, const hidl_vec<uint32_t>&, int32_t userId) override {
109         FaceCallbackArgs args = {};
110         args.userId = userId;
111         NotifyFromCallback(kCallbackNameOnRemoved, args);
112         return Void();
113     }
114 
onEnumerate(uint64_t,const hidl_vec<uint32_t> &,int32_t userId)115     Return<void> onEnumerate(uint64_t, const hidl_vec<uint32_t>&, int32_t userId) override {
116         FaceCallbackArgs args = {};
117         args.userId = userId;
118         NotifyFromCallback(kCallbackNameOnEnumerate, args);
119         return Void();
120     }
121 
onLockoutChanged(uint64_t)122     Return<void> onLockoutChanged(uint64_t) override {
123         NotifyFromCallback(kCallbackNameOnLockoutChanged);
124         return Void();
125     }
126 };
127 
128 // Test class for the BiometricsFace HAL.
129 class FaceHidlTest : public ::testing::TestWithParam<std::string> {
130   public:
SetUp()131     void SetUp() override {
132         mService = IBiometricsFace::getService(GetParam());
133         ASSERT_NE(mService, nullptr);
134         mCallback = new FaceCallback();
135         mCallback->SetWaitTimeoutDefault(kTimeout);
136         Return<void> ret1 = mService->setCallback(mCallback, [](const OptionalUint64& res) {
137             ASSERT_EQ(Status::OK, res.status);
138             // Makes sure the "deviceId" represented by "res.value" is not 0.
139             // 0 would mean the HIDL is not available.
140             ASSERT_NE(0UL, res.value);
141         });
142         ASSERT_TRUE(ret1.isOk());
143         Return<Status> ret2 = mService->setActiveUser(kUserId, kFacedataDir);
144         ASSERT_EQ(Status::OK, static_cast<Status>(ret2));
145     }
146 
TearDown()147     void TearDown() override {}
148 
149     sp<IBiometricsFace> mService;
150     sp<FaceCallback> mCallback;
151 };
152 
153 // generateChallenge should always return a unique, cryptographically secure,
154 // non-zero number.
TEST_P(FaceHidlTest,GenerateChallengeTest)155 TEST_P(FaceHidlTest, GenerateChallengeTest) {
156     std::map<uint64_t, int> m;
157     for (int i = 0; i < kGenerateChallengeIterations; ++i) {
158         Return<void> ret =
159                 mService->generateChallenge(kTimeoutSec, [&m](const OptionalUint64& res) {
160                     ASSERT_EQ(Status::OK, res.status);
161                     EXPECT_NE(0UL, res.value);
162                     m[res.value]++;
163                     EXPECT_EQ(1UL, m[res.value]);
164                 });
165         ASSERT_TRUE(ret.isOk());
166     }
167 }
168 
169 // enroll with an invalid (all zeroes) HAT should fail.
TEST_P(FaceHidlTest,EnrollZeroHatTest)170 TEST_P(FaceHidlTest, EnrollZeroHatTest) {
171     // Filling HAT with zeros
172     hidl_vec<uint8_t> token(69);
173     for (size_t i = 0; i < 69; i++) {
174         token[i] = 0;
175     }
176 
177     Return<Status> ret = mService->enroll(token, kTimeoutSec, {});
178     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
179 
180     // onError should be called with a meaningful (nonzero) error.
181     auto res = mCallback->WaitForCallback(kCallbackNameOnError);
182     EXPECT_TRUE(res.no_timeout);
183     EXPECT_EQ(kUserId, res.args->userId);
184     EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
185 }
186 
187 // enroll with an invalid HAT should fail.
TEST_P(FaceHidlTest,EnrollGarbageHatTest)188 TEST_P(FaceHidlTest, EnrollGarbageHatTest) {
189     // Filling HAT with pseudorandom invalid data.
190     // Using default seed to make the test reproducible.
191     std::mt19937 gen(std::mt19937::default_seed);
192     std::uniform_int_distribution<uint8_t> dist;
193     hidl_vec<uint8_t> token(69);
194     for (size_t i = 0; i < 69; ++i) {
195         token[i] = dist(gen);
196     }
197 
198     Return<Status> ret = mService->enroll(token, kTimeoutSec, {});
199     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
200 
201     // onError should be called with a meaningful (nonzero) error.
202     auto res = mCallback->WaitForCallback(kCallbackNameOnError);
203     EXPECT_TRUE(res.no_timeout);
204     EXPECT_EQ(kUserId, res.args->userId);
205     EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
206 }
207 
208 // setFeature with an invalid (all zeros) HAT should fail.
TEST_P(FaceHidlTest,SetFeatureZeroHatTest)209 TEST_P(FaceHidlTest, SetFeatureZeroHatTest) {
210     hidl_vec<uint8_t> token(69);
211     for (size_t i = 0; i < 69; i++) {
212         token[i] = 0;
213     }
214 
215     Return<Status> ret = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0);
216     ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast<Status>(ret));
217 }
218 
219 // setFeature with an invalid HAT should fail.
TEST_P(FaceHidlTest,SetFeatureGarbageHatTest)220 TEST_P(FaceHidlTest, SetFeatureGarbageHatTest) {
221     // Filling HAT with pseudorandom invalid data.
222     // Using default seed to make the test reproducible.
223     std::mt19937 gen(std::mt19937::default_seed);
224     std::uniform_int_distribution<uint8_t> dist;
225     hidl_vec<uint8_t> token(69);
226     for (size_t i = 0; i < 69; ++i) {
227         token[i] = dist(gen);
228     }
229 
230     Return<Status> ret = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0);
231     ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast<Status>(ret));
232 }
233 
assertGetFeatureFails(const sp<IBiometricsFace> & service,uint32_t faceId,Feature feature)234 void assertGetFeatureFails(const sp<IBiometricsFace>& service, uint32_t faceId, Feature feature) {
235     // Features cannot be retrieved for invalid faces.
236     Return<void> res = service->getFeature(feature, faceId, [](const OptionalBool& result) {
237         ASSERT_EQ(Status::ILLEGAL_ARGUMENT, result.status);
238     });
239     ASSERT_TRUE(res.isOk());
240 }
241 
TEST_P(FaceHidlTest,GetFeatureRequireAttentionTest)242 TEST_P(FaceHidlTest, GetFeatureRequireAttentionTest) {
243     assertGetFeatureFails(mService, 0 /* faceId */, Feature::REQUIRE_ATTENTION);
244 }
245 
TEST_P(FaceHidlTest,GetFeatureRequireDiversityTest)246 TEST_P(FaceHidlTest, GetFeatureRequireDiversityTest) {
247     assertGetFeatureFails(mService, 0 /* faceId */, Feature::REQUIRE_DIVERSITY);
248 }
249 
250 // revokeChallenge should always return within the timeout
TEST_P(FaceHidlTest,RevokeChallengeTest)251 TEST_P(FaceHidlTest, RevokeChallengeTest) {
252     auto start = std::chrono::system_clock::now();
253     Return<Status> ret = mService->revokeChallenge();
254     auto elapsed = std::chrono::system_clock::now() - start;
255     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
256     ASSERT_GE(kTimeout, elapsed);
257 }
258 
259 // The call to getAuthenticatorId should succeed.
TEST_P(FaceHidlTest,GetAuthenticatorIdTest)260 TEST_P(FaceHidlTest, GetAuthenticatorIdTest) {
261     Return<void> ret = mService->getAuthenticatorId(
262             [](const OptionalUint64& res) { ASSERT_EQ(Status::OK, res.status); });
263     ASSERT_TRUE(ret.isOk());
264 }
265 
266 // The call to enumerate should succeed.
TEST_P(FaceHidlTest,EnumerateTest)267 TEST_P(FaceHidlTest, EnumerateTest) {
268     Return<Status> ret = mService->enumerate();
269     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
270     auto res = mCallback->WaitForCallback(kCallbackNameOnEnumerate);
271     EXPECT_EQ(kUserId, res.args->userId);
272     EXPECT_TRUE(res.no_timeout);
273 }
274 
275 // The call to remove should succeed for any faceId
TEST_P(FaceHidlTest,RemoveFaceTest)276 TEST_P(FaceHidlTest, RemoveFaceTest) {
277     // Remove a face
278     Return<Status> ret = mService->remove(kFaceId);
279     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
280 }
281 
282 // Remove should accept 0 to delete all faces
TEST_P(FaceHidlTest,RemoveAllFacesTest)283 TEST_P(FaceHidlTest, RemoveAllFacesTest) {
284     // Remove all faces
285     Return<Status> ret = mService->remove(0);
286     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
287 }
288 
289 // Active user should successfully set to a writable location.
TEST_P(FaceHidlTest,SetActiveUserTest)290 TEST_P(FaceHidlTest, SetActiveUserTest) {
291     // Create an active user
292     Return<Status> ret = mService->setActiveUser(2, kFacedataDir);
293     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
294 
295     // Reset active user
296     ret = mService->setActiveUser(kUserId, kFacedataDir);
297     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
298 }
299 
300 // Active user should fail to set to an unwritable location.
TEST_P(FaceHidlTest,SetActiveUserUnwritableTest)301 TEST_P(FaceHidlTest, SetActiveUserUnwritableTest) {
302     // Create an active user to an unwritable location (device root dir)
303     Return<Status> ret = mService->setActiveUser(3, "/");
304     ASSERT_NE(Status::OK, static_cast<Status>(ret));
305 
306     // Reset active user
307     ret = mService->setActiveUser(kUserId, kFacedataDir);
308     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
309 }
310 
311 // Active user should fail to set to a null location.
TEST_P(FaceHidlTest,SetActiveUserNullTest)312 TEST_P(FaceHidlTest, SetActiveUserNullTest) {
313     // Create an active user to a null location.
314     Return<Status> ret = mService->setActiveUser(4, nullptr);
315     ASSERT_NE(Status::OK, static_cast<Status>(ret));
316 
317     // Reset active user
318     ret = mService->setActiveUser(kUserId, kFacedataDir);
319     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
320 }
321 
322 // Cancel should always return CANCELED from any starting state including
323 // the IDLE state.
TEST_P(FaceHidlTest,CancelTest)324 TEST_P(FaceHidlTest, CancelTest) {
325     Return<Status> ret = mService->cancel();
326     // check that we were able to make an IPC request successfully
327     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
328     auto res = mCallback->WaitForCallback(kCallbackNameOnError);
329     // make sure callback was invoked within kRevokeChallengeTimeout
330     EXPECT_TRUE(res.no_timeout);
331     EXPECT_EQ(kUserId, res.args->userId);
332     EXPECT_EQ(FaceError::CANCELED, res.args->error);
333 }
334 
TEST_P(FaceHidlTest,OnLockoutChangedTest)335 TEST_P(FaceHidlTest, OnLockoutChangedTest) {
336     // Update active user and ensure onLockoutChanged was called.
337     Return<Status> ret = mService->setActiveUser(kUserId + 1, kFacedataDir);
338     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
339 
340     // Make sure callback was invoked
341     auto res = mCallback->WaitForCallback(kCallbackNameOnLockoutChanged);
342     EXPECT_TRUE(res.no_timeout);
343 }
344 
345 }  // anonymous namespace
346 
347 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FaceHidlTest);
348 INSTANTIATE_TEST_SUITE_P(
349         PerInstance, FaceHidlTest,
350         testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBiometricsFace::descriptor)),
351         android::hardware::PrintInstanceNameToString);
352