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