Face Biometric Virtual HAL Authentication Implementation
Bug: 294254230
Test: atest VtsHalBiometricsFaceTargetTest
Test: atest VtsHalBiometricsFingerprintTargetTest
Test: atest android.hardware.biometrics.face.FakeFaceEngineTest
Test: atest android.hardware.biometrics.fingerprint.FakeFingerprintEngineTest
Change-Id: Id7a4698730307235c5de94811f5e396ff4b9c5ae
diff --git a/biometrics/common/util/include/util/Util.h b/biometrics/common/util/include/util/Util.h
index da19dc6..efd66bc 100644
--- a/biometrics/common/util/include/util/Util.h
+++ b/biometrics/common/util/include/util/Util.h
@@ -23,6 +23,9 @@
#include <thread>
#include <vector>
+#include <android-base/parseint.h>
+using ::android::base::ParseInt;
+
namespace aidl::android::hardware::biometrics {
#define SLEEP_MS(x) \
@@ -64,6 +67,87 @@
std::sregex_token_iterator());
return parts;
}
+
+ // Returns a vector of integers for the string separated by comma,
+ // Empty vector is returned if there is any parsing error
+ static std::vector<int32_t> parseIntSequence(const std::string& str,
+ const std::string& sep = ",") {
+ std::vector<std::string> seqs = Util::split(str, sep);
+ std::vector<int32_t> res;
+
+ for (const auto& seq : seqs) {
+ int32_t val;
+ if (ParseInt(seq, &val)) {
+ res.push_back(val);
+ } else {
+ LOG(WARNING) << "Invalid int sequence:" + str + " seq:" + seq;
+ res.clear();
+ break;
+ }
+ }
+
+ return res;
+ }
+
+ // Parses a single enrollment stage string in the format of
+ // enroll_stage_spec: <duration>[-acquiredInfos]
+ // duration: integerInMs
+ // acquiredInfos: [info1,info2,...]
+ //
+ // Returns false if there is parsing error
+ //
+ static bool parseEnrollmentCaptureSingle(const std::string& str,
+ std::vector<std::vector<int32_t>>& res) {
+ std::vector<int32_t> defaultAcquiredInfo = {1};
+ bool aborted = true;
+
+ do {
+ std::smatch sms;
+ // Parses strings like "1000-[5,1]" or "500"
+ std::regex ex("((\\d+)(-\\[([\\d|,]+)\\])?)");
+ if (!regex_match(str.cbegin(), str.cend(), sms, ex)) break;
+ int32_t duration;
+ if (!ParseInt(sms.str(2), &duration)) break;
+ res.push_back({duration});
+ if (!sms.str(4).empty()) {
+ auto acqv = parseIntSequence(sms.str(4));
+ if (acqv.empty()) break;
+ res.push_back(acqv);
+ } else
+ res.push_back(defaultAcquiredInfo);
+ aborted = false;
+ } while (0);
+
+ return !aborted;
+ }
+
+ // Parses enrollment string consisting of one or more stages in the formst of
+ // <enroll_stage_spec>[,enroll_stage_spec,...]
+ // Empty vector is returned in case of parsing error
+ static std::vector<std::vector<int32_t>> parseEnrollmentCapture(const std::string& str) {
+ std::vector<std::vector<int32_t>> res;
+
+ std::string s(str);
+ s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
+ bool aborted = false;
+ std::smatch sms;
+ // Parses strings like "1000-[5,1],500,800-[6,5,1]"
+ // -------------- ----- ---------------
+ // into parts: A B C
+ while (regex_search(s, sms, std::regex("^(,)?(\\d+(-\\[[\\d|,]+\\])?)"))) {
+ if (!parseEnrollmentCaptureSingle(sms.str(2), res)) {
+ aborted = true;
+ break;
+ }
+ s = sms.suffix();
+ }
+ if (aborted || s.length() != 0) {
+ res.clear();
+ LOG(ERROR) << "Failed to parse enrollment captures:" + str;
+ }
+
+ return res;
+ }
};
} // namespace aidl::android::hardware::biometrics
diff --git a/biometrics/face/aidl/default/FakeFaceEngine.cpp b/biometrics/face/aidl/default/FakeFaceEngine.cpp
index 0f088f4..578231d 100644
--- a/biometrics/face/aidl/default/FakeFaceEngine.cpp
+++ b/biometrics/face/aidl/default/FakeFaceEngine.cpp
@@ -136,56 +136,127 @@
const std::future<void>& cancel) {
BEGIN_OP(FaceHalProperties::operation_authenticate_latency().value_or(0));
- // Signal to the framework that we have begun authenticating.
- AuthenticationFrame frame;
- frame.data.acquiredInfo = AcquiredInfo::START;
- frame.data.vendorCode = 0;
- cb->onAuthenticationFrame(frame);
-
- // Also signal that we have opened the camera.
- frame = {};
- frame.data.acquiredInfo = AcquiredInfo::FIRST_FRAME_RECEIVED;
- frame.data.vendorCode = 0;
- cb->onAuthenticationFrame(frame);
-
- auto now = Util::getSystemNanoTime();
- int64_t duration = FaceHalProperties::operation_authenticate_duration().value_or(0);
- if (duration > 0) {
- do {
- SLEEP_MS(5);
- } while (!Util::hasElapsed(now, duration));
- }
-
- if (FaceHalProperties::operation_authenticate_fails().value_or(false)) {
- LOG(ERROR) << "Fail: operation_authenticate_fails";
- cb->onError(Error::VENDOR, 0 /* vendorError */);
- return;
- }
-
- if (FaceHalProperties::lockout().value_or(false)) {
- LOG(ERROR) << "Fail: lockout";
- cb->onLockoutPermanent();
- cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */);
- return;
- }
-
- if (shouldCancel(cancel)) {
- LOG(ERROR) << "Fail: cancel";
- cb->onError(Error::CANCELED, 0 /* vendorCode */);
- return;
- }
-
auto id = FaceHalProperties::enrollment_hit().value_or(0);
auto enrolls = FaceHalProperties::enrollments();
auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
- if (id < 0 || !isEnrolled) {
- LOG(ERROR) << (isEnrolled ? "invalid enrollment hit" : "Fail: not enrolled");
- cb->onAuthenticationFailed();
+
+ auto vec2str = [](std::vector<AcquiredInfo> va) {
+ std::stringstream ss;
+ bool isFirst = true;
+ for (auto ac : va) {
+ if (!isFirst) ss << ",";
+ ss << std::to_string((int8_t)ac);
+ isFirst = false;
+ }
+ return ss.str();
+ };
+
+ // default behavior mimic face sensor in U
+ int64_t defaultAuthDuration = 500;
+ std::string defaultAcquiredInfo =
+ vec2str({AcquiredInfo::START, AcquiredInfo::FIRST_FRAME_RECEIVED});
+ if (!isEnrolled) {
+ std::vector<AcquiredInfo> v;
+ for (int i = 0; i < 56; i++) v.push_back(AcquiredInfo::NOT_DETECTED);
+ defaultAcquiredInfo += "," + vec2str(v);
+ defaultAuthDuration = 2100;
+ } else {
+ defaultAcquiredInfo += "," + vec2str({AcquiredInfo::TOO_BRIGHT, AcquiredInfo::TOO_BRIGHT,
+ AcquiredInfo::TOO_BRIGHT, AcquiredInfo::TOO_BRIGHT,
+ AcquiredInfo::GOOD, AcquiredInfo::GOOD});
+ }
+
+ int64_t now = Util::getSystemNanoTime();
+ int64_t duration =
+ FaceHalProperties::operation_authenticate_duration().value_or(defaultAuthDuration);
+ auto acquired =
+ FaceHalProperties::operation_authenticate_acquired().value_or(defaultAcquiredInfo);
+ auto acquiredInfos = Util::parseIntSequence(acquired);
+ int N = acquiredInfos.size();
+
+ if (N == 0) {
+ LOG(ERROR) << "Fail to parse authentiate acquired info: " + acquired;
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
return;
}
- cb->onAuthenticationSucceeded(id, {} /* hat */);
+ int i = 0;
+ do {
+ if (FaceHalProperties::lockout().value_or(false)) {
+ LOG(ERROR) << "Fail: lockout";
+ cb->onLockoutPermanent();
+ cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */);
+ return;
+ }
+
+ if (FaceHalProperties::operation_authenticate_fails().value_or(false)) {
+ LOG(ERROR) << "Fail: operation_authenticate_fails";
+ cb->onAuthenticationFailed();
+ return;
+ }
+
+ auto err = FaceHalProperties::operation_authenticate_error().value_or(0);
+ if (err != 0) {
+ LOG(ERROR) << "Fail: operation_authenticate_error";
+ auto ec = convertError(err);
+ cb->onError(ec.first, ec.second);
+ return; /* simply terminating current operation for any user inserted error,
+ revisit if tests need*/
+ }
+
+ if (shouldCancel(cancel)) {
+ LOG(ERROR) << "Fail: cancel";
+ cb->onError(Error::CANCELED, 0 /* vendorCode */);
+ return;
+ }
+
+ if (i < N) {
+ auto ac = convertAcquiredInfo(acquiredInfos[i]);
+ AuthenticationFrame frame;
+ frame.data.acquiredInfo = ac.first;
+ frame.data.vendorCode = ac.second;
+ cb->onAuthenticationFrame(frame);
+ LOG(INFO) << "AcquiredInfo:" << i << ": (" << (int)ac.first << "," << (int)ac.second
+ << ")";
+ i++;
+ }
+
+ SLEEP_MS(duration / N);
+ } while (!Util::hasElapsed(now, duration));
+
+ if (id > 0 && isEnrolled) {
+ cb->onAuthenticationSucceeded(id, {} /* hat */);
+ return;
+ } else {
+ LOG(ERROR) << "Fail: face not enrolled";
+ cb->onAuthenticationFailed();
+ cb->onError(Error::TIMEOUT, 0 /* vendorError*/);
+ return;
+ }
+}
+
+std::pair<AcquiredInfo, int32_t> FakeFaceEngine::convertAcquiredInfo(int32_t code) {
+ std::pair<AcquiredInfo, int32_t> res;
+ if (code > FACE_ACQUIRED_VENDOR_BASE) {
+ res.first = AcquiredInfo::VENDOR;
+ res.second = code - FACE_ACQUIRED_VENDOR_BASE;
+ } else {
+ res.first = (AcquiredInfo)code;
+ res.second = 0;
+ }
+ return res;
+}
+
+std::pair<Error, int32_t> FakeFaceEngine::convertError(int32_t code) {
+ std::pair<Error, int32_t> res;
+ if (code > FACE_ERROR_VENDOR_BASE) {
+ res.first = Error::VENDOR;
+ res.second = code - FACE_ERROR_VENDOR_BASE;
+ } else {
+ res.first = (Error)code;
+ res.second = 0;
+ }
+ return res;
}
void FakeFaceEngine::detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel) {
@@ -315,4 +386,4 @@
cb->onLockoutCleared();
}
-} // namespace aidl::android::hardware::biometrics::face
\ No newline at end of file
+} // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/FakeFaceEngine.h b/biometrics/face/aidl/default/FakeFaceEngine.h
index eb99441..06dd396 100644
--- a/biometrics/face/aidl/default/FakeFaceEngine.h
+++ b/biometrics/face/aidl/default/FakeFaceEngine.h
@@ -62,6 +62,12 @@
void resetLockoutImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& /*hat*/);
std::mt19937 mRandom;
+
+ private:
+ static constexpr int32_t FACE_ACQUIRED_VENDOR_BASE = 1000;
+ static constexpr int32_t FACE_ERROR_VENDOR_BASE = 1000;
+ std::pair<AcquiredInfo, int32_t> convertAcquiredInfo(int32_t code);
+ std::pair<Error, int32_t> convertError(int32_t code);
};
} // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/README.md b/biometrics/face/aidl/default/README.md
index 77bfe57..516a7aa 100644
--- a/biometrics/face/aidl/default/README.md
+++ b/biometrics/face/aidl/default/README.md
@@ -18,6 +18,7 @@
Face VHAL enabling is gated by the following two AND conditions:
1. The Face VHAL feature flag (as part of Trunk-development strategy) must be tured until the flags life-cycle ends.
2. The Face VHAL must be enabled via sysprop
+See adb commands below
##Getting Stared
@@ -47,8 +48,7 @@
$ adb shell setprop vendor.face.virtual.operation_authenticate_duration 800
$ adb shell setprop vendor.face.virtual.enrollment_hit 1
```
-Note: At the initial phase of the Face VHAL development, Face-on-camera simulation is not supported, hence
-the authentication immediately occurrs as soon as the authentication request arriving at VHAL.
+Refer to face.sysprop for full supported features of authentication, such as error and acquiredInfo insertion
## Enrollment via Setup
diff --git a/biometrics/face/aidl/default/face.sysprop b/biometrics/face/aidl/default/face.sysprop
index 6b0f37f..be32015 100644
--- a/biometrics/face/aidl/default/face.sysprop
+++ b/biometrics/face/aidl/default/face.sysprop
@@ -157,3 +157,22 @@
access: ReadWrite
api_name: "operation_authenticate_duration"
}
+
+# insert error for authenticate operations
+prop {
+ prop_name: "vendor.face.virtual.operation_authenticate_error"
+ type: Integer
+ scope: Internal
+ access: ReadWrite
+ api_name: "operation_authenticate_error"
+}
+
+# acquired info during authentication in format of sequence
+prop {
+ prop_name: "vendor.face.virtual.operation_authenticate_acquired"
+ type: String
+ scope: Internal
+ access: ReadWrite
+ api_name: "operation_authenticate_acquired"
+}
+
diff --git a/biometrics/face/aidl/default/tests/FakeFaceEngineTest.cpp b/biometrics/face/aidl/default/tests/FakeFaceEngineTest.cpp
index c8ad6b7..6897dc4 100644
--- a/biometrics/face/aidl/default/tests/FakeFaceEngineTest.cpp
+++ b/biometrics/face/aidl/default/tests/FakeFaceEngineTest.cpp
@@ -245,7 +245,7 @@
FaceHalProperties::enrollments({3});
FaceHalProperties::enrollment_hit(100);
mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
- ASSERT_EQ(Error::UNABLE_TO_PROCESS, mCallback->mError);
+ ASSERT_EQ(Error::TIMEOUT, mCallback->mError);
ASSERT_TRUE(mCallback->mAuthenticateFailed);
}
@@ -380,4 +380,4 @@
ASSERT_FALSE(mCallback->mAuthenticateFailed);
}
-} // namespace aidl::android::hardware::biometrics::face
\ No newline at end of file
+} // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
index 54076c8..574570e 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
@@ -142,7 +142,7 @@
return true;
}
auto enrollmentId = std::stoi(parts[0]);
- auto progress = parseEnrollmentCapture(parts[1]);
+ auto progress = Util::parseEnrollmentCapture(parts[1]);
for (size_t i = 0; i < progress.size(); i += 2) {
auto left = (progress.size() - i) / 2 - 1;
auto duration = progress[i][0];
@@ -193,7 +193,7 @@
int64_t now = Util::getSystemNanoTime();
int64_t duration = FingerprintHalProperties::operation_authenticate_duration().value_or(10);
auto acquired = FingerprintHalProperties::operation_authenticate_acquired().value_or("1");
- auto acquiredInfos = parseIntSequence(acquired);
+ auto acquiredInfos = Util::parseIntSequence(acquired);
int N = acquiredInfos.size();
if (N == 0) {
@@ -271,7 +271,7 @@
FingerprintHalProperties::operation_detect_interaction_duration().value_or(10);
auto acquired = FingerprintHalProperties::operation_detect_interaction_acquired().value_or("1");
- auto acquiredInfos = parseIntSequence(acquired);
+ auto acquiredInfos = Util::parseIntSequence(acquired);
int N = acquiredInfos.size();
int64_t now = Util::getSystemNanoTime();
@@ -450,76 +450,6 @@
return SensorLocation();
}
-std::vector<int32_t> FakeFingerprintEngine::parseIntSequence(const std::string& str,
- const std::string& sep) {
- std::vector<std::string> seqs = Util::split(str, sep);
- std::vector<int32_t> res;
-
- for (const auto& seq : seqs) {
- int32_t val;
- if (ParseInt(seq, &val)) {
- res.push_back(val);
- } else {
- LOG(WARNING) << "Invalid int sequence:" + str;
- res.clear();
- break;
- }
- }
-
- return res;
-}
-
-bool FakeFingerprintEngine::parseEnrollmentCaptureSingle(const std::string& str,
- std::vector<std::vector<int32_t>>& res) {
- std::vector<int32_t> defaultAcquiredInfo = {(int32_t)AcquiredInfo::GOOD};
- bool aborted = true;
-
- do {
- std::smatch sms;
- // Parses strings like "1000-[5,1]" or "500"
- std::regex ex("((\\d+)(-\\[([\\d|,]+)\\])?)");
- if (!regex_match(str.cbegin(), str.cend(), sms, ex)) break;
- int32_t duration;
- if (!ParseInt(sms.str(2), &duration)) break;
- res.push_back({duration});
- if (!sms.str(4).empty()) {
- auto acqv = parseIntSequence(sms.str(4));
- if (acqv.empty()) break;
- res.push_back(acqv);
- } else
- res.push_back(defaultAcquiredInfo);
- aborted = false;
- } while (0);
-
- return !aborted;
-}
-
-std::vector<std::vector<int32_t>> FakeFingerprintEngine::parseEnrollmentCapture(
- const std::string& str) {
- std::vector<std::vector<int32_t>> res;
-
- std::string s(str);
- s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
- bool aborted = false;
- std::smatch sms;
- // Parses strings like "1000-[5,1],500,800-[6,5,1]"
- // ---------- --- -----------
- // into parts: A B C
- while (regex_search(s, sms, std::regex("^(,)?(\\d+(-\\[[\\d|,]+\\])?)"))) {
- if (!parseEnrollmentCaptureSingle(sms.str(2), res)) {
- aborted = true;
- break;
- }
- s = sms.suffix();
- }
- if (aborted || s.length() != 0) {
- res.clear();
- LOG(ERROR) << "Failed to parse enrollment captures:" + str;
- }
-
- return res;
-}
-
std::pair<AcquiredInfo, int32_t> FakeFingerprintEngine::convertAcquiredInfo(int32_t code) {
std::pair<AcquiredInfo, int32_t> res;
if (code > FINGERPRINT_ACQUIRED_VENDOR_BASE) {
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
index 2450115..15d8360 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
@@ -68,10 +68,6 @@
virtual void fingerDownAction();
- std::vector<int32_t> parseIntSequence(const std::string& str, const std::string& sep = ",");
-
- std::vector<std::vector<int32_t>> parseEnrollmentCapture(const std::string& str);
-
int32_t getLatency(const std::vector<std::optional<std::int32_t>>& latencyVec);
std::mt19937 mRandom;
@@ -110,8 +106,6 @@
static constexpr int32_t FINGERPRINT_ERROR_VENDOR_BASE = 1000;
std::pair<AcquiredInfo, int32_t> convertAcquiredInfo(int32_t code);
std::pair<Error, int32_t> convertError(int32_t code);
- bool parseEnrollmentCaptureSingle(const std::string& str,
- std::vector<std::vector<int32_t>>& res);
int32_t getRandomInRange(int32_t bound1, int32_t bound2);
bool checkSensorLockout(ISessionCallback*);
void clearLockout(ISessionCallback* cb);
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
index fe405f4..45b5be8 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
@@ -421,29 +421,29 @@
TEST_F(FakeFingerprintEngineTest, parseIntSequence) {
std::vector<int32_t> seqV;
- seqV = mEngine.parseIntSequence("");
+ seqV = Util::parseIntSequence("");
ASSERT_EQ(0, seqV.size());
- seqV = mEngine.parseIntSequence("2");
+ seqV = Util::parseIntSequence("2");
ASSERT_EQ(1, seqV.size());
ASSERT_EQ(2, seqV[0]);
- seqV = mEngine.parseIntSequence("2,3,4");
+ seqV = Util::parseIntSequence("2,3,4");
std::vector<int32_t> expV{2, 3, 4};
ASSERT_EQ(expV, seqV);
- seqV = mEngine.parseIntSequence("2,3,a");
+ seqV = Util::parseIntSequence("2,3,a");
ASSERT_EQ(0, seqV.size());
- seqV = mEngine.parseIntSequence("2, 3, 4");
+ seqV = Util::parseIntSequence("2, 3, 4");
ASSERT_EQ(expV, seqV);
- seqV = mEngine.parseIntSequence("123,456");
+ seqV = Util::parseIntSequence("123,456");
ASSERT_EQ(2, seqV.size());
std::vector<int32_t> expV1{123, 456};
ASSERT_EQ(expV1, seqV);
- seqV = mEngine.parseIntSequence("12f3,456");
+ seqV = Util::parseIntSequence("12f3,456");
ASSERT_EQ(0, seqV.size());
}
TEST_F(FakeFingerprintEngineTest, parseEnrollmentCaptureOk) {
std::vector<std::vector<int32_t>> ecV;
- ecV = mEngine.parseEnrollmentCapture("100,200,300");
+ ecV = Util::parseEnrollmentCapture("100,200,300");
ASSERT_EQ(6, ecV.size());
std::vector<std::vector<int32_t>> expE{{100}, {200}, {300}};
std::vector<int32_t> defC{1};
@@ -451,26 +451,26 @@
ASSERT_EQ(expE[i / 2], ecV[i]);
ASSERT_EQ(defC, ecV[i + 1]);
}
- ecV = mEngine.parseEnrollmentCapture("100");
+ ecV = Util::parseEnrollmentCapture("100");
ASSERT_EQ(2, ecV.size());
ASSERT_EQ(expE[0], ecV[0]);
ASSERT_EQ(defC, ecV[1]);
- ecV = mEngine.parseEnrollmentCapture("100-[5,6,7]");
+ ecV = Util::parseEnrollmentCapture("100-[5,6,7]");
std::vector<int32_t> expC{5, 6, 7};
ASSERT_EQ(2, ecV.size());
for (int i = 0; i < ecV.size(); i += 2) {
ASSERT_EQ(expE[i / 2], ecV[i]);
ASSERT_EQ(expC, ecV[i + 1]);
}
- ecV = mEngine.parseEnrollmentCapture("100-[5,6,7], 200, 300-[9,10]");
+ ecV = Util::parseEnrollmentCapture("100-[5,6,7], 200, 300-[9,10]");
std::vector<std::vector<int32_t>> expC1{{5, 6, 7}, {1}, {9, 10}};
ASSERT_EQ(6, ecV.size());
for (int i = 0; i < ecV.size(); i += 2) {
ASSERT_EQ(expE[i / 2], ecV[i]);
ASSERT_EQ(expC1[i / 2], ecV[i + 1]);
}
- ecV = mEngine.parseEnrollmentCapture("100-[5,6,7], 200-[2,1], 300-[9]");
+ ecV = Util::parseEnrollmentCapture("100-[5,6,7], 200-[2,1], 300-[9]");
std::vector<std::vector<int32_t>> expC2{{5, 6, 7}, {2, 1}, {9}};
ASSERT_EQ(ecV.size(), 6);
for (int i = 0; i < ecV.size(); i += 2) {
@@ -484,7 +484,7 @@
"100,2x0,300", "200-[f]", "a,b"};
std::vector<std::vector<int32_t>> ecV;
for (const auto& s : badStr) {
- ecV = mEngine.parseEnrollmentCapture(s);
+ ecV = Util::parseEnrollmentCapture(s);
ASSERT_EQ(ecV.size(), 0);
}
}
@@ -508,7 +508,7 @@
TEST_F(FakeFingerprintEngineTest, lockoutTimer) {
mEngine.startLockoutTimer(200, mCallback.get());
ASSERT_TRUE(mEngine.getLockoutTimerStarted());
- std::this_thread::sleep_for(std::chrono::milliseconds(210));
+ std::this_thread::sleep_for(std::chrono::milliseconds(230));
ASSERT_FALSE(mEngine.getLockoutTimerStarted());
ASSERT_TRUE(mCallback->mLockoutCleared);
}