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