1 /*
2  * Copyright (C) 2017 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 "fingerprint_hidl_hal_test"
18 
19 #include <android-base/logging.h>
20 #include <android-base/properties.h>
21 #include <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprint.h>
22 #include <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.h>
23 #include <gtest/gtest.h>
24 #include <hidl/GtestPrinter.h>
25 #include <hidl/HidlSupport.h>
26 #include <hidl/HidlTransportSupport.h>
27 #include <hidl/ServiceManagement.h>
28 #include <utils/Condition.h>
29 
30 #include <cinttypes>
31 #include <future>
32 #include <utility>
33 
34 using android::base::GetUintProperty;
35 using android::Condition;
36 using android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint;
37 using android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprintClientCallback;
38 using android::hardware::biometrics::fingerprint::V2_1::FingerprintAcquiredInfo;
39 using android::hardware::biometrics::fingerprint::V2_1::FingerprintError;
40 using android::hardware::biometrics::fingerprint::V2_1::RequestStatus;
41 using android::hardware::hidl_vec;
42 using android::hardware::Return;
43 using android::Mutex;
44 using android::sp;
45 
46 namespace {
47 
48 static const uint32_t kTimeout = 3;
49 static const std::chrono::seconds kTimeoutInSeconds = std::chrono::seconds(kTimeout);
50 static const uint32_t kGroupId = 99;
51 static std::string kTmpDir = "";
52 static const uint32_t kIterations = 10;
53 
54 // Wait for a callback to occur (signaled by the given future) up to the
55 // provided timeout. If the future is invalid or the callback does not come
56 // within the given time, returns false.
57 template<class ReturnType>
waitForCallback(std::future<ReturnType> future,std::chrono::milliseconds timeout=kTimeoutInSeconds)58 bool waitForCallback(
59     std::future<ReturnType> future,
60     std::chrono::milliseconds timeout = kTimeoutInSeconds) {
61   auto expiration = std::chrono::system_clock::now() + timeout;
62 
63   EXPECT_TRUE(future.valid());
64   if (future.valid()) {
65     std::future_status status = future.wait_until(expiration);
66     EXPECT_NE(std::future_status::timeout, status)
67         << "Timed out waiting for callback";
68     if (status == std::future_status::ready) {
69       return true;
70     }
71   }
72 
73   return false;
74 }
75 
76 // Base callback implementation that just logs all callbacks by default
77 class FingerprintCallbackBase : public IBiometricsFingerprintClientCallback {
78  public:
79   // implement methods of IBiometricsFingerprintClientCallback
onEnrollResult(uint64_t,uint32_t,uint32_t,uint32_t)80   virtual Return<void> onEnrollResult(uint64_t, uint32_t, uint32_t, uint32_t)
81       override {
82     ALOGD("Enroll callback called.");
83     return Return<void>();
84   }
85 
onAcquired(uint64_t,FingerprintAcquiredInfo,int32_t)86   virtual Return<void> onAcquired(uint64_t, FingerprintAcquiredInfo, int32_t)
87       override {
88     ALOGD("Acquired callback called.");
89     return Return<void>();
90   }
91 
onAuthenticated(uint64_t,uint32_t,uint32_t,const hidl_vec<uint8_t> &)92   virtual Return<void> onAuthenticated(uint64_t, uint32_t, uint32_t,
93       const hidl_vec<uint8_t>&) override {
94     ALOGD("Authenticated callback called.");
95     return Return<void>();
96   }
97 
onError(uint64_t,FingerprintError,int32_t)98   virtual Return<void> onError(uint64_t, FingerprintError, int32_t)
99       override {
100     ALOGD("Error callback called.");
101     EXPECT_TRUE(false);  // fail any test that triggers an error
102     return Return<void>();
103   }
104 
onRemoved(uint64_t,uint32_t,uint32_t,uint32_t)105   virtual Return<void> onRemoved(uint64_t, uint32_t, uint32_t, uint32_t)
106       override {
107     ALOGD("Removed callback called.");
108     return Return<void>();
109   }
110 
onEnumerate(uint64_t,uint32_t,uint32_t,uint32_t)111   virtual Return<void> onEnumerate(uint64_t, uint32_t, uint32_t, uint32_t)
112       override {
113     ALOGD("Enumerate callback called.");
114     return Return<void>();
115   }
116 };
117 
118 class EnumerateCallback : public FingerprintCallbackBase {
119  public:
onEnumerate(uint64_t deviceId,uint32_t fingerId,uint32_t groupId,uint32_t remaining)120   virtual Return<void> onEnumerate(uint64_t deviceId, uint32_t fingerId,
121       uint32_t groupId, uint32_t remaining) override {
122     this->deviceId = deviceId;
123     this->fingerId = fingerId;
124     this->groupId = groupId;
125     this->remaining = remaining;
126 
127     if(remaining == 0UL) {
128       promise.set_value();
129     }
130     return Return<void>();
131   }
132 
133   uint64_t deviceId;
134   uint32_t fingerId;
135   uint32_t groupId;
136   uint32_t remaining;
137   std::promise<void> promise;
138 };
139 
140 class ErrorCallback : public FingerprintCallbackBase {
141  public:
ErrorCallback(bool filterErrors=false,FingerprintError errorType=FingerprintError::ERROR_NO_ERROR)142   ErrorCallback(
143       bool filterErrors=false,
144       FingerprintError errorType=FingerprintError::ERROR_NO_ERROR) {
145     this->filterErrors = filterErrors;
146     this->errorType = errorType;
147   }
148 
onError(uint64_t deviceId,FingerprintError error,int32_t vendorCode)149   virtual Return<void> onError(uint64_t deviceId, FingerprintError error,
150       int32_t vendorCode) override {
151     if ((this->filterErrors && this->errorType == error) || !this->filterErrors) {
152       this->deviceId = deviceId;
153       this->error = error;
154       this->vendorCode = vendorCode;
155       promise.set_value();
156     }
157     return Return<void>();
158   }
159 
160   bool filterErrors;
161   FingerprintError errorType;
162   uint64_t deviceId;
163   FingerprintError error;
164   int32_t vendorCode;
165   std::promise<void> promise;
166 };
167 
168 class RemoveCallback : public FingerprintCallbackBase {
169  public:
RemoveCallback(uint32_t groupId)170   RemoveCallback(uint32_t groupId) {
171     this->removeGroupId = groupId;
172   }
173 
onRemoved(uint64_t,uint32_t,uint32_t groupId,uint32_t remaining)174   virtual Return<void> onRemoved(uint64_t, uint32_t, uint32_t groupId,
175       uint32_t remaining) override {
176     EXPECT_EQ(this->removeGroupId, groupId);
177     if(remaining == 0UL) {
178       promise.set_value();
179     }
180     return Return<void>();
181   }
182 
183   uint32_t removeGroupId;
184   std::promise<void> promise;
185 };
186 
187 class FingerprintHidlTest : public ::testing::TestWithParam<std::string> {
188   public:
SetUp()189     virtual void SetUp() override {
190         mService = IBiometricsFingerprint::getService(GetParam());
191         ASSERT_FALSE(mService == nullptr);
192 
193         /*
194          * Devices shipped from now on will instead store
195          * fingerprint data under /data/vendor_de/<user-id>/fpdata.
196          * Support for /data/vendor_de and /data/vendor_ce has been added to vold.
197          */
198 
199         uint64_t api_level = GetUintProperty<uint64_t>("ro.product.first_api_level", 0);
200         if (api_level == 0) {
201             api_level = GetUintProperty<uint64_t>("ro.build.version.sdk", 0);
202         }
203         ASSERT_TRUE(api_level != 0);
204 
205         // 27 is the API number for O-MR1
206         if (api_level <= 27) {
207             kTmpDir = "/data/system/users/0/fpdata/";
208         } else {
209             kTmpDir = "/data/vendor_de/0/fpdata/";
210         }
211 
212         Return<RequestStatus> res = mService->setActiveGroup(kGroupId, kTmpDir);
213         ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
214     }
215 
TearDown()216     virtual void TearDown() override {}
217 
218     sp<IBiometricsFingerprint> mService;
219 };
220 
221 // The service should be reachable.
TEST_P(FingerprintHidlTest,ConnectTest)222 TEST_P(FingerprintHidlTest, ConnectTest) {
223     sp<FingerprintCallbackBase> cb = new FingerprintCallbackBase();
224     Return<uint64_t> rc = mService->setNotify(cb);
225     ASSERT_NE(0UL, static_cast<uint64_t>(rc));
226 }
227 
228 // Starting the service with null callback should succeed.
TEST_P(FingerprintHidlTest,ConnectNullTest)229 TEST_P(FingerprintHidlTest, ConnectNullTest) {
230     Return<uint64_t> rc = mService->setNotify(NULL);
231     ASSERT_NE(0UL, static_cast<uint64_t>(rc));
232 }
233 
234 // Pre-enroll should always return unique, cryptographically secure, non-zero number
TEST_P(FingerprintHidlTest,PreEnrollTest)235 TEST_P(FingerprintHidlTest, PreEnrollTest) {
236     std::map<uint64_t, uint64_t> m;
237 
238     for (unsigned int i = 0; i < kIterations; ++i) {
239         uint64_t res = static_cast<uint64_t>(mService->preEnroll());
240         EXPECT_NE(0UL, res);
241         m[res]++;
242         EXPECT_EQ(1UL, m[res]);
243     }
244 }
245 
246 // Enroll with an invalid (all zeroes) HAT should fail.
TEST_P(FingerprintHidlTest,EnrollInvalidHatTest)247 TEST_P(FingerprintHidlTest, EnrollInvalidHatTest) {
248     sp<ErrorCallback> cb = new ErrorCallback();
249     Return<uint64_t> rc = mService->setNotify(cb);
250     ASSERT_NE(0UL, static_cast<uint64_t>(rc));
251 
252     uint8_t token[69];
253     for (int i = 0; i < 69; i++) {
254         token[i] = 0;
255     }
256 
257     Return<RequestStatus> res = mService->enroll(token, kGroupId, kTimeout);
258     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
259 
260     // At least one call to onError should occur
261     ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
262     ASSERT_NE(FingerprintError::ERROR_NO_ERROR, cb->error);
263 }
264 
265 // Enroll with an invalid (null) HAT should fail.
TEST_P(FingerprintHidlTest,EnrollNullTest)266 TEST_P(FingerprintHidlTest, EnrollNullTest) {
267     sp<ErrorCallback> cb = new ErrorCallback();
268     Return<uint64_t> rc = mService->setNotify(cb);
269     ASSERT_NE(0UL, static_cast<uint64_t>(rc));
270 
271     uint8_t token[69];
272     Return<RequestStatus> res = mService->enroll(token, kGroupId, kTimeout);
273     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
274 
275     // At least one call to onError should occur
276     ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
277     ASSERT_NE(FingerprintError::ERROR_NO_ERROR, cb->error);
278 }
279 
280 // PostEnroll should always return within 3s
TEST_P(FingerprintHidlTest,PostEnrollTest)281 TEST_P(FingerprintHidlTest, PostEnrollTest) {
282     sp<FingerprintCallbackBase> cb = new FingerprintCallbackBase();
283     Return<uint64_t> rc = mService->setNotify(cb);
284 
285     auto start = std::chrono::system_clock::now();
286     Return<RequestStatus> res = mService->postEnroll();
287     auto elapsed = std::chrono::system_clock::now() - start;
288     ASSERT_GE(kTimeoutInSeconds, elapsed);
289 }
290 
291 // getAuthenticatorId should always return non-zero numbers
TEST_P(FingerprintHidlTest,GetAuthenticatorIdTest)292 TEST_P(FingerprintHidlTest, GetAuthenticatorIdTest) {
293     Return<uint64_t> res = mService->getAuthenticatorId();
294     EXPECT_NE(0UL, static_cast<uint64_t>(res));
295 }
296 
297 // Enumerate should always trigger onEnumerated(fid=0, rem=0) when there are no fingerprints
TEST_P(FingerprintHidlTest,EnumerateTest)298 TEST_P(FingerprintHidlTest, EnumerateTest) {
299     sp<EnumerateCallback> cb = new EnumerateCallback();
300     Return<uint64_t> rc = mService->setNotify(cb);
301     ASSERT_NE(0UL, static_cast<uint64_t>(rc));
302 
303     // Callback will return when rem=0 is found
304     Return<RequestStatus> res = mService->enumerate();
305     ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
306     EXPECT_EQ(0UL, cb->fingerId);
307     EXPECT_EQ(0UL, cb->remaining);
308 }
309 
310 // Remove should succeed on any inputs
311 // At least one callback with "remaining=0" should occur
TEST_P(FingerprintHidlTest,RemoveFingerprintTest)312 TEST_P(FingerprintHidlTest, RemoveFingerprintTest) {
313     // Register callback
314     sp<RemoveCallback> cb = new RemoveCallback(kGroupId);
315     Return<uint64_t> rc = mService->setNotify(cb);
316     ASSERT_NE(0UL, static_cast<uint64_t>(rc));
317 
318     // Remove a fingerprint
319     Return<RequestStatus> res = mService->remove(kGroupId, 1);
320     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
321 
322     // At least one call to onRemove with remaining=0 should occur
323     ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
324 }
325 
326 // Remove should accept 0 to delete all fingerprints
327 // At least one callback with "remaining=0" should occur.
TEST_P(FingerprintHidlTest,RemoveAllFingerprintsTest)328 TEST_P(FingerprintHidlTest, RemoveAllFingerprintsTest) {
329     // Register callback
330     sp<RemoveCallback> cb = new RemoveCallback(kGroupId);
331     Return<uint64_t> rc = mService->setNotify(cb);
332     ASSERT_NE(0UL, static_cast<uint64_t>(rc));
333 
334     // Remove all fingerprints
335     Return<RequestStatus> res = mService->remove(kGroupId, 0);
336     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
337     ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
338 }
339 
340 // Active group should successfully set to a writable location.
TEST_P(FingerprintHidlTest,SetActiveGroupTest)341 TEST_P(FingerprintHidlTest, SetActiveGroupTest) {
342     // Create an active group
343     Return<RequestStatus> res = mService->setActiveGroup(2, kTmpDir);
344     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
345 
346     // Reset active group
347     res = mService->setActiveGroup(kGroupId, kTmpDir);
348     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
349 }
350 
351 // Active group should fail to set to an unwritable location.
TEST_P(FingerprintHidlTest,SetActiveGroupUnwritableTest)352 TEST_P(FingerprintHidlTest, SetActiveGroupUnwritableTest) {
353     // Create an active group to an unwritable location (device root dir)
354     Return<RequestStatus> res = mService->setActiveGroup(3, "/");
355     ASSERT_NE(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
356 
357     // Reset active group
358     res = mService->setActiveGroup(kGroupId, kTmpDir);
359     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
360 }
361 
362 // Active group should fail to set to a null location.
TEST_P(FingerprintHidlTest,SetActiveGroupNullTest)363 TEST_P(FingerprintHidlTest, SetActiveGroupNullTest) {
364     // Create an active group to a null location.
365     Return<RequestStatus> res = mService->setActiveGroup(4, nullptr);
366     ASSERT_NE(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
367 
368     // Reset active group
369     res = mService->setActiveGroup(kGroupId, kTmpDir);
370     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
371 }
372 
373 // Cancel should always return ERROR_CANCELED from any starting state including
374 // the IDLE state.
TEST_P(FingerprintHidlTest,CancelTest)375 TEST_P(FingerprintHidlTest, CancelTest) {
376     sp<ErrorCallback> cb = new ErrorCallback(true, FingerprintError::ERROR_CANCELED);
377     Return<uint64_t> rc = mService->setNotify(cb);
378     ASSERT_NE(0UL, static_cast<uint64_t>(rc));
379 
380     Return<RequestStatus> res = mService->cancel();
381     // check that we were able to make an IPC request successfully
382     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
383 
384     // make sure callback was invoked within kTimeoutInSeconds
385     ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
386     // check error should be ERROR_CANCELED
387     ASSERT_EQ(FingerprintError::ERROR_CANCELED, cb->error);
388 }
389 
390 // A call to cancel should succeed during enroll.
TEST_P(FingerprintHidlTest,CancelEnrollTest)391 TEST_P(FingerprintHidlTest, CancelEnrollTest) {
392     Return<RequestStatus> res = mService->setActiveGroup(kGroupId, kTmpDir);
393     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
394 
395     sp<ErrorCallback> cb = new ErrorCallback(true, FingerprintError::ERROR_CANCELED);
396     Return<uint64_t> rc = mService->setNotify(cb);
397     ASSERT_NE(0U, static_cast<uint64_t>(rc));
398 
399     uint8_t token[69];
400     res = mService->enroll(token, kGroupId, kTimeout);
401     // check that we were able to make an IPC request successfully
402     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
403 
404     res = mService->cancel();
405     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
406 
407     // make sure callback was invoked within kTimeoutInSeconds
408     ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
409 
410     // check error should be ERROR_CANCELED
411     ASSERT_EQ(FingerprintError::ERROR_CANCELED, cb->error);
412 }
413 
414 // A call to cancel should succeed during authentication.
TEST_P(FingerprintHidlTest,CancelAuthTest)415 TEST_P(FingerprintHidlTest, CancelAuthTest) {
416     sp<ErrorCallback> cb = new ErrorCallback(true, FingerprintError::ERROR_CANCELED);
417     Return<uint64_t> rc = mService->setNotify(cb);
418     ASSERT_NE(0U, static_cast<uint64_t>(rc));
419 
420     Return<RequestStatus> res = mService->authenticate(0, kGroupId);
421     // check that we were able to make an IPC request successfully
422     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
423 
424     res = mService->cancel();
425     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
426 
427     // make sure callback was invoked within kTimeoutInSeconds
428     ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
429 
430     // check error should be ERROR_CANCELED
431     ASSERT_EQ(FingerprintError::ERROR_CANCELED, cb->error);
432 }
433 
434 // A call to cancel should succeed during authentication.
TEST_P(FingerprintHidlTest,CancelRemoveTest)435 TEST_P(FingerprintHidlTest, CancelRemoveTest) {
436     sp<ErrorCallback> cb = new ErrorCallback(true, FingerprintError::ERROR_CANCELED);
437     Return<uint64_t> rc = mService->setNotify(cb);
438     ASSERT_NE(0U, static_cast<uint64_t>(rc));
439 
440     // Remove a fingerprint
441     Return<RequestStatus> res = mService->remove(kGroupId, 1);
442     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
443 
444     res = mService->cancel();
445     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
446 
447     // make sure callback was invoked within kTimeoutInSeconds
448     ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
449 
450     // check error should be ERROR_CANCELED
451     ASSERT_EQ(FingerprintError::ERROR_CANCELED, cb->error);
452 }
453 
454 // A call to cancel should succeed during authentication.
TEST_P(FingerprintHidlTest,CancelRemoveAllTest)455 TEST_P(FingerprintHidlTest, CancelRemoveAllTest) {
456     sp<ErrorCallback> cb = new ErrorCallback(true, FingerprintError::ERROR_CANCELED);
457     Return<uint64_t> rc = mService->setNotify(cb);
458     ASSERT_NE(0U, static_cast<uint64_t>(rc));
459 
460     // Remove a fingerprint
461     Return<RequestStatus> res = mService->remove(kGroupId, 0);
462     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
463 
464     res = mService->cancel();
465     ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(res));
466 
467     // make sure callback was invoked within kTimeoutInSeconds
468     ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
469 
470     // check error should be ERROR_CANCELED
471     ASSERT_EQ(FingerprintError::ERROR_CANCELED, cb->error);
472 }
473 }  // anonymous namespace
474 
475 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FingerprintHidlTest);
476 INSTANTIATE_TEST_SUITE_P(PerInstance, FingerprintHidlTest,
477                          testing::ValuesIn(android::hardware::getAllHalInstanceNames(
478                                  IBiometricsFingerprint::descriptor)),
479                          android::hardware::PrintInstanceNameToString);
480