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