mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 10:44:41 +00:00
Fingerprint virtual HAL checkin (part 3)
- support randomization
- display touch events
- lockout
- cmd and dumpsys
Bug: 230515082
Bug: 230515086
Test: atest FakeFingerprintEngineTest
atest FakeFingerprintEngineUdfpsTest
atest --no-bazel-mode VtsHalBiometricsFingerprintTargetTest
Change-Id: Ia5399c86b7fec90b41d426c2f82cb257f4dc9a8a
This commit is contained in:
@@ -40,7 +40,7 @@ namespace aidl::android::hardware::biometrics {
|
||||
// by parts of the UI or fail if there is no latency. For example, the
|
||||
// Face settings page constantly runs auth and the enrollment UI uses a
|
||||
// cancel/restart cycle that requires some latency while the activities change.
|
||||
#define DEFAULT_LATENCY 800
|
||||
#define DEFAULT_LATENCY 400
|
||||
|
||||
class Util {
|
||||
public:
|
||||
@@ -66,4 +66,4 @@ class Util {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics
|
||||
} // namespace aidl::android::hardware::biometrics
|
||||
|
||||
@@ -15,6 +15,7 @@ cc_binary {
|
||||
vintf_fragments: ["fingerprint-example.xml"],
|
||||
local_include_dirs: ["include"],
|
||||
srcs: [
|
||||
"FakeLockoutTracker.cpp",
|
||||
"FakeFingerprintEngine.cpp",
|
||||
"FakeFingerprintEngineRear.cpp",
|
||||
"FakeFingerprintEngineUdfps.cpp",
|
||||
@@ -40,6 +41,7 @@ cc_test {
|
||||
srcs: [
|
||||
"tests/FakeFingerprintEngineTest.cpp",
|
||||
"FakeFingerprintEngine.cpp",
|
||||
"FakeLockoutTracker.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
@@ -65,6 +67,31 @@ cc_test {
|
||||
"tests/FakeFingerprintEngineUdfpsTest.cpp",
|
||||
"FakeFingerprintEngineUdfps.cpp",
|
||||
"FakeFingerprintEngine.cpp",
|
||||
"FakeLockoutTracker.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
],
|
||||
static_libs: [
|
||||
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
|
||||
"android.hardware.biometrics.fingerprint-V2-ndk",
|
||||
"android.hardware.biometrics.common-V2-ndk",
|
||||
"android.hardware.keymaster-V3-ndk",
|
||||
"android.hardware.biometrics.common.util",
|
||||
],
|
||||
vendor: true,
|
||||
test_suites: ["general-tests"],
|
||||
require_root: true,
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "android.hardware.biometrics.fingerprint.FakeLockoutTrackerTest",
|
||||
local_include_dirs: ["include"],
|
||||
srcs: [
|
||||
"tests/FakeLockoutTrackerTest.cpp",
|
||||
"FakeLockoutTracker.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "FakeFingerprintEngine.h"
|
||||
#include <regex>
|
||||
#include "Fingerprint.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
@@ -47,7 +48,7 @@ void FakeFingerprintEngine::revokeChallengeImpl(ISessionCallback* cb, int64_t ch
|
||||
void FakeFingerprintEngine::enrollImpl(ISessionCallback* cb,
|
||||
const keymaster::HardwareAuthToken& hat,
|
||||
const std::future<void>& cancel) {
|
||||
BEGIN_OP(FingerprintHalProperties::operation_enroll_latency().value_or(DEFAULT_LATENCY));
|
||||
BEGIN_OP(getLatency(FingerprintHalProperties::operation_enroll_latency()));
|
||||
|
||||
// Do proper HAT verification in the real implementation.
|
||||
if (hat.mac.empty()) {
|
||||
@@ -117,7 +118,7 @@ void FakeFingerprintEngine::enrollImpl(ISessionCallback* cb,
|
||||
|
||||
void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t /* operationId */,
|
||||
const std::future<void>& cancel) {
|
||||
BEGIN_OP(FingerprintHalProperties::operation_authenticate_latency().value_or(DEFAULT_LATENCY));
|
||||
BEGIN_OP(getLatency(FingerprintHalProperties::operation_authenticate_latency()));
|
||||
|
||||
int64_t now = Util::getSystemNanoTime();
|
||||
int64_t duration = FingerprintHalProperties::operation_authenticate_duration().value_or(10);
|
||||
@@ -131,10 +132,23 @@ void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t /* op
|
||||
return;
|
||||
}
|
||||
|
||||
// got lockout?
|
||||
FakeLockoutTracker::LockoutMode lockoutMode = mLockoutTracker.getMode();
|
||||
if (lockoutMode == FakeLockoutTracker::LockoutMode::kPermanent) {
|
||||
LOG(ERROR) << "Fail: lockout permanent";
|
||||
cb->onLockoutPermanent();
|
||||
return;
|
||||
} else if (lockoutMode == FakeLockoutTracker::LockoutMode::kTimed) {
|
||||
int64_t timeLeft = mLockoutTracker.getLockoutTimeLeft();
|
||||
LOG(ERROR) << "Fail: lockout timed " << timeLeft;
|
||||
cb->onLockoutTimed(timeLeft);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
do {
|
||||
if (FingerprintHalProperties::operation_authenticate_fails().value_or(false)) {
|
||||
LOG(ERROR) << "Fail: operation_authenticate_fails";
|
||||
mLockoutTracker.addFailedAttempt();
|
||||
cb->onAuthenticationFailed();
|
||||
return;
|
||||
}
|
||||
@@ -174,20 +188,30 @@ void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t /* op
|
||||
auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
|
||||
if (id > 0 && isEnrolled) {
|
||||
cb->onAuthenticationSucceeded(id, {} /* hat */);
|
||||
mLockoutTracker.reset();
|
||||
return;
|
||||
} else {
|
||||
LOG(ERROR) << "Fail: fingerprint not enrolled";
|
||||
cb->onAuthenticationFailed();
|
||||
mLockoutTracker.addFailedAttempt();
|
||||
}
|
||||
}
|
||||
|
||||
void FakeFingerprintEngine::detectInteractionImpl(ISessionCallback* cb,
|
||||
const std::future<void>& cancel) {
|
||||
BEGIN_OP(FingerprintHalProperties::operation_detect_interaction_latency().value_or(
|
||||
DEFAULT_LATENCY));
|
||||
BEGIN_OP(getLatency(FingerprintHalProperties::operation_detect_interaction_latency()));
|
||||
|
||||
int64_t duration =
|
||||
FingerprintHalProperties::operation_detect_interaction_duration().value_or(10);
|
||||
|
||||
auto detectInteractionSupported =
|
||||
FingerprintHalProperties::detect_interaction().value_or(false);
|
||||
if (!detectInteractionSupported) {
|
||||
LOG(ERROR) << "Detect interaction is not supported";
|
||||
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
|
||||
return;
|
||||
}
|
||||
|
||||
auto acquired = FingerprintHalProperties::operation_detect_interaction_acquired().value_or("1");
|
||||
auto acquiredInfos = parseIntSequence(acquired);
|
||||
int N = acquiredInfos.size();
|
||||
@@ -308,6 +332,7 @@ void FakeFingerprintEngine::resetLockoutImpl(ISessionCallback* cb,
|
||||
}
|
||||
FingerprintHalProperties::lockout(false);
|
||||
cb->onLockoutCleared();
|
||||
mLockoutTracker.reset();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus FakeFingerprintEngine::onPointerDownImpl(int32_t /*pointerId*/, int32_t /*x*/,
|
||||
@@ -383,49 +408,52 @@ std::vector<int32_t> FakeFingerprintEngine::parseIntSequence(const std::string&
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<std::vector<int32_t>> FakeFingerprintEngine::parseEnrollmentCapture(
|
||||
const std::string& str) {
|
||||
bool FakeFingerprintEngine::parseEnrollmentCaptureSingle(const std::string& str,
|
||||
std::vector<std::vector<int32_t>>& res) {
|
||||
std::vector<int32_t> defaultAcquiredInfo = {(int32_t)AcquiredInfo::GOOD};
|
||||
std::vector<std::vector<int32_t>> res;
|
||||
int i = 0, N = str.length();
|
||||
std::size_t found = 0;
|
||||
bool aborted = true;
|
||||
|
||||
while (found != std::string::npos) {
|
||||
std::string durationStr, acquiredStr;
|
||||
found = str.find_first_of("-,", i);
|
||||
if (found == std::string::npos) {
|
||||
if (N - i < 1) break;
|
||||
durationStr = str.substr(i, N - i);
|
||||
} else {
|
||||
durationStr = str.substr(i, found - i);
|
||||
if (str[found] == '-') {
|
||||
found = str.find_first_of('[', found + 1);
|
||||
if (found == std::string::npos) break;
|
||||
i = found + 1;
|
||||
found = str.find_first_of(']', found + 1);
|
||||
if (found == std::string::npos) break;
|
||||
acquiredStr = str.substr(i, found - i);
|
||||
found = str.find_first_of(',', found + 1);
|
||||
}
|
||||
}
|
||||
std::vector<int32_t> duration{0};
|
||||
if (!ParseInt(durationStr, &duration[0])) break;
|
||||
res.push_back(duration);
|
||||
if (!acquiredStr.empty()) {
|
||||
std::vector<int32_t> acquiredInfo = parseIntSequence(acquiredStr);
|
||||
if (acquiredInfo.empty()) break;
|
||||
res.push_back(acquiredInfo);
|
||||
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);
|
||||
|
||||
i = found + 1;
|
||||
if (found == std::string::npos || found == N - 1) aborted = false;
|
||||
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) {
|
||||
LOG(ERROR) << "Failed to parse enrollment captures:" + str;
|
||||
if (aborted || s.length() != 0) {
|
||||
res.clear();
|
||||
LOG(ERROR) << "Failed to parse enrollment captures:" + str;
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -455,4 +483,34 @@ std::pair<Error, int32_t> FakeFingerprintEngine::convertError(int32_t code) {
|
||||
return res;
|
||||
}
|
||||
|
||||
int32_t FakeFingerprintEngine::getLatency(
|
||||
const std::vector<std::optional<std::int32_t>>& latencyIn) {
|
||||
int32_t res = DEFAULT_LATENCY;
|
||||
|
||||
std::vector<int32_t> latency;
|
||||
for (auto x : latencyIn)
|
||||
if (x.has_value()) latency.push_back(*x);
|
||||
|
||||
switch (latency.size()) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
res = latency[0];
|
||||
break;
|
||||
case 2:
|
||||
res = getRandomInRange(latency[0], latency[1]);
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "ERROR: unexpected input of size " << latency.size();
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int32_t FakeFingerprintEngine::getRandomInRange(int32_t bound1, int32_t bound2) {
|
||||
std::uniform_int_distribution<int32_t> dist(std::min(bound1, bound2), std::max(bound1, bound2));
|
||||
return dist(mRandom);
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
|
||||
@@ -23,10 +23,16 @@
|
||||
#include "util/CancellationSignal.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "FingerprintVirtualHalUdfps"
|
||||
|
||||
using namespace ::android::fingerprint::virt;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
FakeFingerprintEngineUdfps::FakeFingerprintEngineUdfps()
|
||||
: FakeFingerprintEngine(), mWorkMode(WorkMode::kIdle), mPointerDownTime(0), mUiReadyTime(0) {}
|
||||
|
||||
SensorLocation FakeFingerprintEngineUdfps::defaultSensorLocation() {
|
||||
return {0 /* displayId (not used) */, defaultSensorLocationX /* sensorLocationX */,
|
||||
defaultSensorLocationY /* sensorLocationY */, defaultSensorRadius /* sensorRadius */,
|
||||
@@ -37,22 +43,95 @@ ndk::ScopedAStatus FakeFingerprintEngineUdfps::onPointerDownImpl(int32_t /*point
|
||||
int32_t /*x*/, int32_t /*y*/,
|
||||
float /*minor*/, float /*major*/) {
|
||||
BEGIN_OP(0);
|
||||
|
||||
// TODO(b/230515082): if need to handle display touch events
|
||||
|
||||
// verify whetehr touch coordinates/area matching sensor location ?
|
||||
mPointerDownTime = Util::getSystemNanoTime();
|
||||
if (FingerprintHalProperties::control_illumination().value_or(false)) {
|
||||
fingerDownAction();
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus FakeFingerprintEngineUdfps::onPointerUpImpl(int32_t /*pointerId*/) {
|
||||
BEGIN_OP(0);
|
||||
// TODO(b/230515082)
|
||||
mUiReadyTime = 0;
|
||||
mPointerDownTime = 0;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus FakeFingerprintEngineUdfps::onUiReadyImpl() {
|
||||
BEGIN_OP(0);
|
||||
// TODO(b/230515082)
|
||||
|
||||
if (Util::hasElapsed(mPointerDownTime, uiReadyTimeoutInMs * 100)) {
|
||||
LOG(ERROR) << "onUiReady() arrives too late after onPointerDown()";
|
||||
} else {
|
||||
fingerDownAction();
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
void FakeFingerprintEngineUdfps::fingerDownAction() {
|
||||
switch (mWorkMode) {
|
||||
case WorkMode::kAuthenticate:
|
||||
onAuthenticateFingerDown();
|
||||
break;
|
||||
case WorkMode::kEnroll:
|
||||
onEnrollFingerDown();
|
||||
break;
|
||||
case WorkMode::kDetectInteract:
|
||||
onDetectInteractFingerDown();
|
||||
break;
|
||||
default:
|
||||
LOG(WARNING) << "unexpected call: onUiReady()";
|
||||
break;
|
||||
}
|
||||
|
||||
mUiReadyTime = 0;
|
||||
mPointerDownTime = 0;
|
||||
}
|
||||
|
||||
void FakeFingerprintEngineUdfps::onAuthenticateFingerDown() {
|
||||
FakeFingerprintEngine::authenticateImpl(mCb, mOperationId, mCancelVec[0]);
|
||||
}
|
||||
|
||||
void FakeFingerprintEngineUdfps::onEnrollFingerDown() {
|
||||
// Any use case to emulate display touch for each capture during enrollment?
|
||||
FakeFingerprintEngine::enrollImpl(mCb, mHat, mCancelVec[0]);
|
||||
}
|
||||
|
||||
void FakeFingerprintEngineUdfps::onDetectInteractFingerDown() {
|
||||
FakeFingerprintEngine::detectInteractionImpl(mCb, mCancelVec[0]);
|
||||
}
|
||||
|
||||
void FakeFingerprintEngineUdfps::enrollImpl(ISessionCallback* cb,
|
||||
const keymaster::HardwareAuthToken& hat,
|
||||
const std::future<void>& cancel) {
|
||||
updateContext(WorkMode::kEnroll, cb, const_cast<std::future<void>&>(cancel), 0, hat);
|
||||
}
|
||||
|
||||
void FakeFingerprintEngineUdfps::authenticateImpl(ISessionCallback* cb, int64_t operationId,
|
||||
const std::future<void>& cancel) {
|
||||
updateContext(WorkMode::kAuthenticate, cb, const_cast<std::future<void>&>(cancel), operationId,
|
||||
keymaster::HardwareAuthToken());
|
||||
}
|
||||
|
||||
void FakeFingerprintEngineUdfps::detectInteractionImpl(ISessionCallback* cb,
|
||||
const std::future<void>& cancel) {
|
||||
updateContext(WorkMode::kDetectInteract, cb, const_cast<std::future<void>&>(cancel), 0,
|
||||
keymaster::HardwareAuthToken());
|
||||
}
|
||||
|
||||
void FakeFingerprintEngineUdfps::updateContext(WorkMode mode, ISessionCallback* cb,
|
||||
std::future<void>& cancel, int64_t operationId,
|
||||
const keymaster::HardwareAuthToken& hat) {
|
||||
mPointerDownTime = 0;
|
||||
mUiReadyTime = 0;
|
||||
mCancelVec.clear();
|
||||
|
||||
mCancelVec.push_back(std::move(cancel));
|
||||
mWorkMode = mode;
|
||||
mCb = cb;
|
||||
mOperationId = operationId;
|
||||
mHat = hat;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
|
||||
77
biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp
Normal file
77
biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "FakeLockoutTracker.h"
|
||||
#include <fingerprint.sysprop.h>
|
||||
#include "util/Util.h"
|
||||
|
||||
using namespace ::android::fingerprint::virt;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
void FakeLockoutTracker::reset() {
|
||||
mFailedCount = 0;
|
||||
mLockoutTimedStart = 0;
|
||||
mCurrentMode = LockoutMode::kNone;
|
||||
}
|
||||
|
||||
void FakeLockoutTracker::addFailedAttempt() {
|
||||
bool enabled = FingerprintHalProperties::lockout_enable().value_or(false);
|
||||
if (enabled) {
|
||||
mFailedCount++;
|
||||
int32_t lockoutTimedThreshold =
|
||||
FingerprintHalProperties::lockout_timed_threshold().value_or(5);
|
||||
int32_t lockoutPermanetThreshold =
|
||||
FingerprintHalProperties::lockout_permanent_threshold().value_or(20);
|
||||
if (mFailedCount >= lockoutPermanetThreshold) {
|
||||
mCurrentMode = LockoutMode::kPermanent;
|
||||
FingerprintHalProperties::lockout(true);
|
||||
} else if (mFailedCount >= lockoutTimedThreshold) {
|
||||
if (mCurrentMode == LockoutMode::kNone) {
|
||||
mCurrentMode = LockoutMode::kTimed;
|
||||
mLockoutTimedStart = Util::getSystemNanoTime();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
FakeLockoutTracker::LockoutMode FakeLockoutTracker::getMode() {
|
||||
if (mCurrentMode == LockoutMode::kTimed) {
|
||||
int32_t lockoutTimedDuration =
|
||||
FingerprintHalProperties::lockout_timed_duration().value_or(10 * 100);
|
||||
if (Util::hasElapsed(mLockoutTimedStart, lockoutTimedDuration)) {
|
||||
mCurrentMode = LockoutMode::kNone;
|
||||
mLockoutTimedStart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return mCurrentMode;
|
||||
}
|
||||
|
||||
int64_t FakeLockoutTracker::getLockoutTimeLeft() {
|
||||
int64_t res = 0;
|
||||
|
||||
if (mLockoutTimedStart > 0) {
|
||||
auto now = Util::getSystemNanoTime();
|
||||
auto left = now - mLockoutTimedStart;
|
||||
res = (left > 0) ? (left / 1000000LL) : 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
@@ -15,11 +15,13 @@
|
||||
*/
|
||||
|
||||
#include "Fingerprint.h"
|
||||
|
||||
#include <fingerprint.sysprop.h>
|
||||
#include "Session.h"
|
||||
|
||||
#include <fingerprint.sysprop.h>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
|
||||
using namespace ::android::fingerprint::virt;
|
||||
|
||||
@@ -64,7 +66,6 @@ ndk::ScopedAStatus Fingerprint::getSensorProps(std::vector<SensorProps>* out) {
|
||||
{HW_COMPONENT_ID, HW_VERSION, FW_VERSION, SERIAL_NUMBER, "" /* softwareVersion */},
|
||||
{SW_COMPONENT_ID, "" /* hardwareVersion */, "" /* firmwareVersion */,
|
||||
"" /* serialNumber */, SW_VERSION}};
|
||||
|
||||
auto sensorId = FingerprintHalProperties::sensor_id().value_or(SENSOR_ID);
|
||||
auto sensorStrength =
|
||||
FingerprintHalProperties::sensor_strength().value_or((int)SENSOR_STRENGTH);
|
||||
@@ -80,7 +81,8 @@ ndk::ScopedAStatus Fingerprint::getSensorProps(std::vector<SensorProps>* out) {
|
||||
|
||||
SensorLocation sensorLocation = mEngine->getSensorLocation();
|
||||
|
||||
LOG(INFO) << "sensor type:" << (int)mSensorType << " location:" << sensorLocation.toString();
|
||||
LOG(INFO) << "sensor type:" << ::android::internal::ToString(mSensorType)
|
||||
<< " location:" << sensorLocation.toString();
|
||||
|
||||
*out = {{commonProps,
|
||||
mSensorType,
|
||||
@@ -104,4 +106,96 @@ ndk::ScopedAStatus Fingerprint::createSession(int32_t sensorId, int32_t userId,
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
binder_status_t Fingerprint::dump(int fd, const char** /*args*/, uint32_t numArgs) {
|
||||
if (fd < 0) {
|
||||
LOG(ERROR) << "Fingerprint::dump fd invalid: " << fd;
|
||||
return STATUS_BAD_VALUE;
|
||||
} else {
|
||||
LOG(INFO) << "Fingerprint::dump fd:" << fd << "numArgs:" << numArgs;
|
||||
}
|
||||
|
||||
dprintf(fd, "----- FingerprintVirtualHal::dump -----\n");
|
||||
std::vector<SensorProps> sps(1);
|
||||
getSensorProps(&sps);
|
||||
for (auto& sp : sps) {
|
||||
::android::base::WriteStringToFd(sp.toString(), fd);
|
||||
}
|
||||
::android::base::WriteStringToFd(mEngine->toString(), fd);
|
||||
|
||||
fsync(fd);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
binder_status_t Fingerprint::handleShellCommand(int in, int out, int err, const char** args,
|
||||
uint32_t numArgs) {
|
||||
LOG(INFO) << "Fingerprint::handleShellCommand in:" << in << " out:" << out << " err:" << err
|
||||
<< " numArgs:" << numArgs;
|
||||
|
||||
if (numArgs == 0) {
|
||||
LOG(INFO) << "Fingerprint::handleShellCommand: available commands";
|
||||
onHelp(out);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
for (auto&& str : std::vector<std::string_view>(args, args + numArgs)) {
|
||||
std::string option = str.data();
|
||||
if (option.find("clearconfig") != std::string::npos ||
|
||||
option.find("resetconfig") != std::string::npos) {
|
||||
resetConfigToDefault();
|
||||
}
|
||||
if (option.find("help") != std::string::npos) {
|
||||
onHelp(out);
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
void Fingerprint::onHelp(int fd) {
|
||||
dprintf(fd, "Virtual HAL commands:\n");
|
||||
dprintf(fd, " help: print this help\n");
|
||||
dprintf(fd, " resetconfig: reset all configuration to default\n");
|
||||
dprintf(fd, "\n");
|
||||
fsync(fd);
|
||||
}
|
||||
|
||||
void Fingerprint::resetConfigToDefault() {
|
||||
LOG(INFO) << "reset virtual HAL configuration to default";
|
||||
#define RESET_CONFIG_O(__NAME__) \
|
||||
if (FingerprintHalProperties::__NAME__()) FingerprintHalProperties::__NAME__(std::nullopt)
|
||||
#define RESET_CONFIG_V(__NAME__) \
|
||||
if (!FingerprintHalProperties::__NAME__().empty()) \
|
||||
FingerprintHalProperties::__NAME__({std::nullopt})
|
||||
|
||||
RESET_CONFIG_O(type);
|
||||
RESET_CONFIG_V(enrollments);
|
||||
RESET_CONFIG_O(enrollment_hit);
|
||||
RESET_CONFIG_O(authenticator_id);
|
||||
RESET_CONFIG_O(challenge);
|
||||
RESET_CONFIG_O(lockout);
|
||||
RESET_CONFIG_O(operation_authenticate_fails);
|
||||
RESET_CONFIG_O(operation_detect_interaction_error);
|
||||
RESET_CONFIG_O(operation_enroll_error);
|
||||
RESET_CONFIG_V(operation_authenticate_latency);
|
||||
RESET_CONFIG_V(operation_detect_interaction_latency);
|
||||
RESET_CONFIG_V(operation_enroll_latency);
|
||||
RESET_CONFIG_O(operation_authenticate_duration);
|
||||
RESET_CONFIG_O(operation_authenticate_error);
|
||||
RESET_CONFIG_O(sensor_location);
|
||||
RESET_CONFIG_O(operation_authenticate_acquired);
|
||||
RESET_CONFIG_O(operation_detect_interaction_duration);
|
||||
RESET_CONFIG_O(operation_detect_interaction_acquired);
|
||||
RESET_CONFIG_O(sensor_id);
|
||||
RESET_CONFIG_O(sensor_strength);
|
||||
RESET_CONFIG_O(max_enrollments);
|
||||
RESET_CONFIG_O(navigation_guesture);
|
||||
RESET_CONFIG_O(detect_interaction);
|
||||
RESET_CONFIG_O(display_touch);
|
||||
RESET_CONFIG_O(control_illumination);
|
||||
RESET_CONFIG_O(lockout_enable);
|
||||
RESET_CONFIG_O(lockout_timed_threshold);
|
||||
RESET_CONFIG_O(lockout_timed_duration);
|
||||
RESET_CONFIG_O(lockout_permanent_threshold);
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
|
||||
@@ -57,6 +57,7 @@ $ adb shell cmd fingerprint sync
|
||||
```shell
|
||||
$ adb shell setprop vendor.fingerprint.virtual.next_enrollment 1:100,100,100:true
|
||||
```
|
||||
|
||||
3. Navigate to `Settings -> Security -> Fingerprint Unlock` and follow the
|
||||
prompts.
|
||||
4. Verify the enrollments in the UI:
|
||||
@@ -119,6 +120,38 @@ $ adb shell setprop vendor.fingerprint.virtual.operation_authenticate_error 8
|
||||
```
|
||||
For vendor specific error, errorCode = 1000 + vendorErrorCode
|
||||
|
||||
## Latency Insertion
|
||||
Three HAL operations (authenticate, enrollment and detect interaction) latency can be optionally specified in multiple ways
|
||||
1. default latency is fixed at 400 ms if not specified via sysprop
|
||||
2. specify authenticate operation latency to 900 ms
|
||||
```shell adb shell setprop vendor.fingerprint.virtual.operation_authenticate_latency 900```
|
||||
3. specify authenticate operation latency between 600 to 1200 ms in unifrom distribution
|
||||
```shelladb shell setprop vendor.fingerprint.virtual.operation_authenticate_latency 600,1200```
|
||||
|
||||
## Lockout
|
||||
To force the device into lockout state
|
||||
```shell
|
||||
$ adb shell setprop persist.vendor.fingerprint.virtual.lockout true
|
||||
```
|
||||
To test permanent lockout based on the failed authentication attempts (e.g. 7)
|
||||
```shell
|
||||
$ adb shell setprop persist.vendor.fingerprint.virtual.lockout_permanent_threshold 7
|
||||
$ adb shell setprop persist.vendor.fingerprint.virtual.lockout_enable true
|
||||
```
|
||||
To test timed lockout based on the failed authentication attempts (e.g. 8 seconds on 5 attempts)
|
||||
```shell
|
||||
$ adb shell setprop persist.vendor.fingerprint.virtual.lockout_timed_duration 8000
|
||||
$ adb shell setprop persist.vendor.fingerprint.virtual.lockout_timed_threshold 5
|
||||
$ adb shell setprop persist.vendor.fingerprint.virtual.lockout_enable true
|
||||
```
|
||||
|
||||
## Reset all configurations to default
|
||||
The following command will reset virtual configurations (related system properties) to default value.
|
||||
```shell
|
||||
$ adb shell cmd android.hardware.biometrics.fingerprint.IFingerprint/virtual resetconfig
|
||||
$ adb reboot
|
||||
```
|
||||
|
||||
## View HAL State
|
||||
|
||||
To view all the properties of the HAL (see `fingerprint.sysprop` file for the API):
|
||||
@@ -126,3 +159,7 @@ To view all the properties of the HAL (see `fingerprint.sysprop` file for the AP
|
||||
```shell
|
||||
$ adb shell getprop | grep vendor.fingerprint.virtual
|
||||
```
|
||||
To dump virtual HAL internal data
|
||||
```shell
|
||||
adb shell dumpsys android.hardware.biometrics.fingerprint.IFingerprint/virtual
|
||||
```
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
|
||||
#include "util/CancellationSignal.h"
|
||||
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "FingerprintVirtualHalSession"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
Session::Session(int sensorId, int userId, std::shared_ptr<ISessionCallback> cb,
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
props {
|
||||
owner: Vendor
|
||||
module: "android.fingerprint.virt.FingerprintHalProperties"
|
||||
prop {
|
||||
api_name: "authenticator_id"
|
||||
type: Long
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.authenticator_id"
|
||||
}
|
||||
prop {
|
||||
api_name: "challenge"
|
||||
type: Long
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.challenge"
|
||||
}
|
||||
prop {
|
||||
api_name: "control_illumination"
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.udfps.control_illumination"
|
||||
}
|
||||
prop {
|
||||
api_name: "detect_interaction"
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.detect_interaction"
|
||||
}
|
||||
prop {
|
||||
api_name: "display_touch"
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.udfps.display_touch"
|
||||
}
|
||||
prop {
|
||||
api_name: "enrollment_hit"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.enrollment_hit"
|
||||
}
|
||||
prop {
|
||||
api_name: "enrollments"
|
||||
type: IntegerList
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.enrollments"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout"
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout"
|
||||
}
|
||||
prop {
|
||||
api_name: "max_enrollments"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.max_enrollments"
|
||||
}
|
||||
prop {
|
||||
api_name: "navigation_guesture"
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.navigation_guesture"
|
||||
}
|
||||
prop {
|
||||
api_name: "next_enrollment"
|
||||
type: String
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.next_enrollment"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_acquired"
|
||||
type: String
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_acquired"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_duration"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_duration"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_error"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_error"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_fails"
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_fails"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_latency"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_latency"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_detect_interaction_acquired"
|
||||
type: String
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_acquired"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_detect_interaction_duration"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_duration"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_detect_interaction_error"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_error"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_detect_interaction_latency"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_latency"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_enroll_error"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.operation_enroll_error"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_enroll_latency"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.fingerprint.virtual.operation_enroll_latency"
|
||||
}
|
||||
prop {
|
||||
api_name: "sensor_id"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.sensor_id"
|
||||
}
|
||||
prop {
|
||||
api_name: "sensor_location"
|
||||
type: String
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.sensor_location"
|
||||
}
|
||||
prop {
|
||||
api_name: "sensor_strength"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.sensor_strength"
|
||||
}
|
||||
prop {
|
||||
api_name: "type"
|
||||
type: String
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.type"
|
||||
enum_values: "default|rear|udfps|side"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ owner: Vendor
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.type"
|
||||
type: String
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
enum_values: "default|rear|udfps|side"
|
||||
api_name: "type"
|
||||
@@ -17,7 +17,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.enrollments"
|
||||
type: IntegerList
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "enrollments"
|
||||
}
|
||||
@@ -27,7 +27,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.enrollment_hit"
|
||||
type: Integer
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "enrollment_hit"
|
||||
}
|
||||
@@ -42,7 +42,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.next_enrollment"
|
||||
type: String
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "next_enrollment"
|
||||
}
|
||||
@@ -51,7 +51,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.authenticator_id"
|
||||
type: Long
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "authenticator_id"
|
||||
}
|
||||
@@ -60,25 +60,16 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.challenge"
|
||||
type: Long
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "challenge"
|
||||
}
|
||||
|
||||
# if locked out
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout"
|
||||
type: Boolean
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout"
|
||||
}
|
||||
|
||||
# force all authenticate operations to fail
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_fails"
|
||||
type: Boolean
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_fails"
|
||||
}
|
||||
@@ -91,7 +82,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_error"
|
||||
type: Integer
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "operation_detect_interaction_error"
|
||||
}
|
||||
@@ -100,34 +91,40 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_enroll_error"
|
||||
type: Integer
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "operation_enroll_error"
|
||||
}
|
||||
|
||||
# add a latency to authentication operations
|
||||
# default to 400ms
|
||||
# [x] = x ms
|
||||
# [x,y] = randomly between x and y ms
|
||||
# others = invalid
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_latency"
|
||||
type: Integer
|
||||
scope: Public
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_latency"
|
||||
}
|
||||
|
||||
# add a latency to detectInteraction operations
|
||||
# refer to `operation_authenticate_latency` above for usage
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_latency"
|
||||
type: Integer
|
||||
scope: Public
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "operation_detect_interaction_latency"
|
||||
}
|
||||
|
||||
# add a latency to enroll operations
|
||||
# refer to `operation_authenticate_latency` above for usage
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_enroll_latency"
|
||||
type: Integer
|
||||
scope: Public
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "operation_enroll_latency"
|
||||
}
|
||||
@@ -137,7 +134,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_duration"
|
||||
type: Integer
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_duration"
|
||||
}
|
||||
@@ -146,7 +143,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_error"
|
||||
type: Integer
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_error"
|
||||
}
|
||||
@@ -156,7 +153,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.sensor_location"
|
||||
type: String
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "sensor_location"
|
||||
}
|
||||
@@ -165,7 +162,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_acquired"
|
||||
type: String
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_acquired"
|
||||
}
|
||||
@@ -175,7 +172,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_duration"
|
||||
type: Integer
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "operation_detect_interaction_duration"
|
||||
}
|
||||
@@ -187,7 +184,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_acquired"
|
||||
type: String
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "operation_detect_interaction_acquired"
|
||||
}
|
||||
@@ -196,7 +193,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.sensor_id"
|
||||
type: Integer
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "sensor_id"
|
||||
}
|
||||
@@ -206,7 +203,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.sensor_strength"
|
||||
type: Integer
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "sensor_strength"
|
||||
}
|
||||
@@ -216,7 +213,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.max_enrollments"
|
||||
type: Integer
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "max_enrollments"
|
||||
}
|
||||
@@ -225,7 +222,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.navigation_guesture"
|
||||
type: Boolean
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "navigation_guesture"
|
||||
}
|
||||
@@ -234,7 +231,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.detect_interaction"
|
||||
type: Boolean
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "detect_interaction"
|
||||
}
|
||||
@@ -243,7 +240,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.udfps.display_touch"
|
||||
type: Boolean
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "display_touch"
|
||||
}
|
||||
@@ -252,7 +249,52 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.udfps.control_illumination"
|
||||
type: Boolean
|
||||
scope: Public
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "control_illumination"
|
||||
}
|
||||
|
||||
# force to be locked out (default: false)
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "lockout"
|
||||
}
|
||||
|
||||
# whether support lockout based on the failed auth attempts (default: false)
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout_enable"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "lockout_enable"
|
||||
}
|
||||
|
||||
# temporarily lockout threshold in number of consecutive failed auth attempts (default: 5)
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout_timed_threshold"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "lockout_timed_threshold"
|
||||
}
|
||||
|
||||
# temporary lockout duration in ms (default: 10000ms)
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout_timed_duration"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "lockout_timed_duration"
|
||||
}
|
||||
|
||||
# permanently lockout threshold in number of consecutive failed auth attempts (default: 20)
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout_permanent_threshold"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "lockout_permanent_threshold"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,8 +15,13 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define LOG_TAG "FingerprintVirtualHal"
|
||||
|
||||
#include <aidl/android/hardware/biometrics/common/SensorStrength.h>
|
||||
#include <aidl/android/hardware/biometrics/fingerprint/ISessionCallback.h>
|
||||
#include <android/binder_to_string.h>
|
||||
#include <string>
|
||||
|
||||
#include <random>
|
||||
|
||||
@@ -24,6 +29,8 @@
|
||||
#include <future>
|
||||
#include <vector>
|
||||
|
||||
#include "FakeLockoutTracker.h"
|
||||
|
||||
using namespace ::aidl::android::hardware::biometrics::common;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
@@ -36,11 +43,11 @@ class FakeFingerprintEngine {
|
||||
|
||||
void generateChallengeImpl(ISessionCallback* cb);
|
||||
void revokeChallengeImpl(ISessionCallback* cb, int64_t challenge);
|
||||
void enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat,
|
||||
const std::future<void>& cancel);
|
||||
void authenticateImpl(ISessionCallback* cb, int64_t operationId,
|
||||
const std::future<void>& cancel);
|
||||
void detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel);
|
||||
virtual void enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat,
|
||||
const std::future<void>& cancel);
|
||||
virtual void authenticateImpl(ISessionCallback* cb, int64_t operationId,
|
||||
const std::future<void>& cancel);
|
||||
virtual void detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel);
|
||||
void enumerateEnrollmentsImpl(ISessionCallback* cb);
|
||||
void removeEnrollmentsImpl(ISessionCallback* cb, const std::vector<int32_t>& enrollmentIds);
|
||||
void getAuthenticatorIdImpl(ISessionCallback* cb);
|
||||
@@ -63,13 +70,29 @@ class FakeFingerprintEngine {
|
||||
|
||||
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;
|
||||
|
||||
virtual std::string toString() const {
|
||||
std::ostringstream os;
|
||||
os << "----- FakeFingerprintEngine:: -----" << std::endl;
|
||||
os << "acquiredVendorInfoBase:" << FINGERPRINT_ACQUIRED_VENDOR_BASE;
|
||||
os << ", errorVendorBase:" << FINGERPRINT_ERROR_VENDOR_BASE << std::endl;
|
||||
os << mLockoutTracker.toString();
|
||||
return os.str();
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr int32_t FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
|
||||
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);
|
||||
|
||||
FakeLockoutTracker mLockoutTracker;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -28,17 +28,55 @@ class FakeFingerprintEngineUdfps : public FakeFingerprintEngine {
|
||||
static constexpr int32_t defaultSensorLocationY = 1600;
|
||||
static constexpr int32_t defaultSensorRadius = 150;
|
||||
|
||||
FakeFingerprintEngineUdfps() : FakeFingerprintEngine() {}
|
||||
static constexpr int32_t uiReadyTimeoutInMs = 5000;
|
||||
|
||||
FakeFingerprintEngineUdfps();
|
||||
~FakeFingerprintEngineUdfps() {}
|
||||
|
||||
virtual ndk::ScopedAStatus onPointerDownImpl(int32_t pointerId, int32_t x, int32_t y,
|
||||
float minor, float major) override;
|
||||
ndk::ScopedAStatus onPointerDownImpl(int32_t pointerId, int32_t x, int32_t y, float minor,
|
||||
float major) override;
|
||||
|
||||
virtual ndk::ScopedAStatus onPointerUpImpl(int32_t pointerId) override;
|
||||
ndk::ScopedAStatus onPointerUpImpl(int32_t pointerId) override;
|
||||
|
||||
virtual ndk::ScopedAStatus onUiReadyImpl() override;
|
||||
ndk::ScopedAStatus onUiReadyImpl() override;
|
||||
|
||||
virtual SensorLocation defaultSensorLocation() override;
|
||||
SensorLocation defaultSensorLocation() override;
|
||||
|
||||
void enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat,
|
||||
const std::future<void>& cancel);
|
||||
void authenticateImpl(ISessionCallback* cb, int64_t operationId,
|
||||
const std::future<void>& cancel);
|
||||
void detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel);
|
||||
|
||||
enum class WorkMode : int8_t { kIdle = 0, kAuthenticate, kEnroll, kDetectInteract };
|
||||
|
||||
WorkMode getWorkMode() { return mWorkMode; }
|
||||
|
||||
std::string toString() const {
|
||||
std::ostringstream os;
|
||||
os << FakeFingerprintEngine::toString();
|
||||
os << "----- FakeFingerprintEngineUdfps -----" << std::endl;
|
||||
os << "mWorkMode:" << (int)mWorkMode;
|
||||
os << ", mUiReadyTime:" << mUiReadyTime;
|
||||
os << ", mPointerDownTime:" << mPointerDownTime << std::endl;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
private:
|
||||
void onAuthenticateFingerDown();
|
||||
void onEnrollFingerDown();
|
||||
void onDetectInteractFingerDown();
|
||||
void fingerDownAction();
|
||||
void updateContext(WorkMode mode, ISessionCallback* cb, std::future<void>& cancel,
|
||||
int64_t operationId, const keymaster::HardwareAuthToken& hat);
|
||||
|
||||
WorkMode mWorkMode;
|
||||
ISessionCallback* mCb;
|
||||
keymaster::HardwareAuthToken mHat;
|
||||
std::vector<std::future<void>> mCancelVec;
|
||||
int64_t mOperationId;
|
||||
int64_t mPointerDownTime;
|
||||
int64_t mUiReadyTime;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <android/binder_to_string.h>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
class FakeLockoutTracker {
|
||||
public:
|
||||
FakeLockoutTracker() : mFailedCount(0) {}
|
||||
~FakeLockoutTracker() {}
|
||||
|
||||
enum class LockoutMode : int8_t { kNone = 0, kTimed, kPermanent };
|
||||
|
||||
void reset();
|
||||
LockoutMode getMode();
|
||||
void addFailedAttempt();
|
||||
int64_t getLockoutTimeLeft();
|
||||
inline std::string toString() const {
|
||||
std::ostringstream os;
|
||||
os << "----- FakeLockoutTracker:: -----" << std::endl;
|
||||
os << "FakeLockoutTracker::mFailedCount:" << mFailedCount;
|
||||
os << ", FakeLockoutTracker::mCurrentMode:" << (int)mCurrentMode;
|
||||
os << std::endl;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
private:
|
||||
int32_t mFailedCount;
|
||||
int64_t mLockoutTimedStart;
|
||||
LockoutMode mCurrentMode;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define LOG_TAG "FingerprintVirtualHal"
|
||||
|
||||
#include <aidl/android/hardware/biometrics/fingerprint/BnFingerprint.h>
|
||||
|
||||
#include "FakeFingerprintEngine.h"
|
||||
@@ -39,8 +37,13 @@ class Fingerprint : public BnFingerprint {
|
||||
ndk::ScopedAStatus createSession(int32_t sensorId, int32_t userId,
|
||||
const std::shared_ptr<ISessionCallback>& cb,
|
||||
std::shared_ptr<ISession>* out) override;
|
||||
binder_status_t dump(int fd, const char** args, uint32_t numArgs);
|
||||
binder_status_t handleShellCommand(int in, int out, int err, const char** argv, uint32_t argc);
|
||||
|
||||
private:
|
||||
void resetConfigToDefault();
|
||||
void onHelp(int);
|
||||
|
||||
std::unique_ptr<FakeFingerprintEngine> mEngine;
|
||||
WorkerThread mWorker;
|
||||
std::shared_ptr<Session> mSession;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <aidl/android/hardware/biometrics/fingerprint/BnSessionCallback.h>
|
||||
|
||||
#include "FakeFingerprintEngine.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
using namespace ::android::fingerprint::virt;
|
||||
using namespace ::aidl::android::hardware::biometrics::fingerprint;
|
||||
@@ -118,9 +119,9 @@ class TestSessionCallback : public BnSessionCallback {
|
||||
class FakeFingerprintEngineTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
FingerprintHalProperties::operation_enroll_latency(0);
|
||||
FingerprintHalProperties::operation_authenticate_latency(0);
|
||||
FingerprintHalProperties::operation_detect_interaction_latency(0);
|
||||
FingerprintHalProperties::operation_enroll_latency({0});
|
||||
FingerprintHalProperties::operation_authenticate_latency({0});
|
||||
FingerprintHalProperties::operation_detect_interaction_latency({0});
|
||||
mCallback = ndk::SharedRefBase::make<TestSessionCallback>();
|
||||
}
|
||||
|
||||
@@ -128,6 +129,9 @@ class FakeFingerprintEngineTest : public ::testing::Test {
|
||||
FingerprintHalProperties::operation_authenticate_error(0);
|
||||
FingerprintHalProperties::operation_detect_interaction_error(0);
|
||||
FingerprintHalProperties::operation_authenticate_acquired("");
|
||||
FingerprintHalProperties::operation_enroll_latency({});
|
||||
FingerprintHalProperties::operation_authenticate_latency({});
|
||||
FingerprintHalProperties::operation_detect_interaction_latency({});
|
||||
}
|
||||
|
||||
FakeFingerprintEngine mEngine;
|
||||
@@ -291,6 +295,7 @@ TEST_F(FakeFingerprintEngineTest, AuthenticateAcquired) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFingerprintEngineTest, InteractionDetect) {
|
||||
FingerprintHalProperties::detect_interaction(true);
|
||||
FingerprintHalProperties::enrollments({1, 2});
|
||||
FingerprintHalProperties::enrollment_hit(2);
|
||||
FingerprintHalProperties::operation_detect_interaction_acquired("");
|
||||
@@ -300,6 +305,7 @@ TEST_F(FakeFingerprintEngineTest, InteractionDetect) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFingerprintEngineTest, InteractionDetectCancel) {
|
||||
FingerprintHalProperties::detect_interaction(true);
|
||||
FingerprintHalProperties::enrollments({1, 2});
|
||||
FingerprintHalProperties::enrollment_hit(2);
|
||||
mCancel.set_value();
|
||||
@@ -309,6 +315,7 @@ TEST_F(FakeFingerprintEngineTest, InteractionDetectCancel) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFingerprintEngineTest, InteractionDetectNotSet) {
|
||||
FingerprintHalProperties::detect_interaction(true);
|
||||
FingerprintHalProperties::enrollments({1, 2});
|
||||
FingerprintHalProperties::enrollment_hit({});
|
||||
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
|
||||
@@ -323,6 +330,7 @@ TEST_F(FakeFingerprintEngineTest, InteractionDetectNotEnrolled) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFingerprintEngineTest, InteractionDetectError) {
|
||||
FingerprintHalProperties::detect_interaction(true);
|
||||
FingerprintHalProperties::operation_detect_interaction_error(8);
|
||||
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
|
||||
ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
|
||||
@@ -331,6 +339,7 @@ TEST_F(FakeFingerprintEngineTest, InteractionDetectError) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFingerprintEngineTest, InteractionDetectAcquired) {
|
||||
FingerprintHalProperties::detect_interaction(true);
|
||||
FingerprintHalProperties::enrollments({1, 2});
|
||||
FingerprintHalProperties::enrollment_hit(2);
|
||||
FingerprintHalProperties::operation_detect_interaction_acquired("4,1013");
|
||||
@@ -435,12 +444,29 @@ TEST_F(FakeFingerprintEngineTest, parseEnrollmentCaptureFail) {
|
||||
std::vector<std::string> badStr{"10c", "100-5", "100-[5,6,7", "100-5,6,7]",
|
||||
"100,2x0,300", "200-[f]", "a,b"};
|
||||
std::vector<std::vector<int32_t>> ecV;
|
||||
for (const auto s : badStr) {
|
||||
for (const auto& s : badStr) {
|
||||
ecV = mEngine.parseEnrollmentCapture(s);
|
||||
ASSERT_EQ(ecV.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(FakeFingerprintEngineTest, randomLatency) {
|
||||
FingerprintHalProperties::operation_detect_interaction_latency({});
|
||||
ASSERT_EQ(DEFAULT_LATENCY,
|
||||
mEngine.getLatency(FingerprintHalProperties::operation_detect_interaction_latency()));
|
||||
FingerprintHalProperties::operation_detect_interaction_latency({10});
|
||||
ASSERT_EQ(10,
|
||||
mEngine.getLatency(FingerprintHalProperties::operation_detect_interaction_latency()));
|
||||
FingerprintHalProperties::operation_detect_interaction_latency({1, 1000});
|
||||
std::set<int32_t> latencySet;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
latencySet.insert(mEngine.getLatency(
|
||||
FingerprintHalProperties::operation_detect_interaction_latency()));
|
||||
}
|
||||
ASSERT_TRUE(latencySet.size() > 95);
|
||||
FingerprintHalProperties::operation_detect_interaction_latency({});
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <aidl/android/hardware/biometrics/fingerprint/BnSessionCallback.h>
|
||||
#include <android/binder_process.h>
|
||||
#include <fingerprint.sysprop.h>
|
||||
#include <gtest/gtest.h>
|
||||
@@ -29,6 +30,69 @@ using namespace ::aidl::android::hardware::keymaster;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
class TestSessionCallback : public BnSessionCallback {
|
||||
public:
|
||||
ndk::ScopedAStatus onChallengeGenerated(int64_t /*challenge*/) override {
|
||||
return ndk::ScopedAStatus::ok();
|
||||
};
|
||||
::ndk::ScopedAStatus onChallengeRevoked(int64_t /*challenge*/) override {
|
||||
return ndk::ScopedAStatus::ok();
|
||||
};
|
||||
::ndk::ScopedAStatus onError(fingerprint::Error /*error*/, int32_t /*vendorCode*/) override {
|
||||
return ndk::ScopedAStatus::ok();
|
||||
};
|
||||
::ndk::ScopedAStatus onEnrollmentProgress(int32_t /*enrollmentId*/,
|
||||
int32_t /*remaining*/) override {
|
||||
mEnrollmentProgress++;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
};
|
||||
|
||||
::ndk::ScopedAStatus onAuthenticationSucceeded(int32_t /*enrollmentId*/,
|
||||
const keymaster::HardwareAuthToken&) override {
|
||||
mAuthenticationSuccess++;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
};
|
||||
::ndk::ScopedAStatus onAuthenticationFailed() override {
|
||||
mAuthenticationFailure++;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
};
|
||||
::ndk::ScopedAStatus onInteractionDetected() override {
|
||||
mDetectInteraction++;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
};
|
||||
ndk::ScopedAStatus onAcquired(AcquiredInfo /*info*/, int32_t /*vendorCode*/) override {
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
::ndk::ScopedAStatus onEnrollmentsEnumerated(
|
||||
const std::vector<int32_t>& /*enrollmentIds*/) override {
|
||||
return ndk::ScopedAStatus::ok();
|
||||
};
|
||||
::ndk::ScopedAStatus onEnrollmentsRemoved(
|
||||
const std::vector<int32_t>& /*enrollmentIds*/) override {
|
||||
return ndk::ScopedAStatus::ok();
|
||||
};
|
||||
::ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t /*authenticatorId*/) override {
|
||||
return ndk::ScopedAStatus::ok();
|
||||
};
|
||||
::ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t /*authenticatorId*/) override {
|
||||
return ndk::ScopedAStatus::ok();
|
||||
};
|
||||
::ndk::ScopedAStatus onLockoutPermanent() override { return ndk::ScopedAStatus::ok(); };
|
||||
ndk::ScopedAStatus onLockoutTimed(int64_t /* timeout */) override {
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); }
|
||||
ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
|
||||
|
||||
int32_t getAuthenticationCount() { return mAuthenticationSuccess + mAuthenticationFailure; }
|
||||
int32_t getDetectInteractionCount() { return mDetectInteraction; }
|
||||
|
||||
int32_t mAuthenticationSuccess = 0;
|
||||
int32_t mAuthenticationFailure = 0;
|
||||
int32_t mEnrollmentProgress = 0;
|
||||
int32_t mDetectInteraction = 0;
|
||||
};
|
||||
|
||||
class FakeFingerprintEngineUdfpsTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {}
|
||||
@@ -65,30 +129,56 @@ TEST_F(FakeFingerprintEngineUdfpsTest, getSensorLocationOk) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFingerprintEngineUdfpsTest, getSensorLocationBad) {
|
||||
FingerprintHalProperties::sensor_location("");
|
||||
SensorLocation sc = mEngine.getSensorLocation();
|
||||
ASSERT_TRUE(isDefaultLocation(sc));
|
||||
|
||||
auto loc = "100";
|
||||
FingerprintHalProperties::sensor_location(loc);
|
||||
sc = mEngine.getSensorLocation();
|
||||
ASSERT_TRUE(isDefaultLocation(sc));
|
||||
|
||||
loc = "10:20";
|
||||
FingerprintHalProperties::sensor_location(loc);
|
||||
sc = mEngine.getSensorLocation();
|
||||
ASSERT_TRUE(isDefaultLocation(sc));
|
||||
|
||||
loc = "10,20,5";
|
||||
FingerprintHalProperties::sensor_location(loc);
|
||||
sc = mEngine.getSensorLocation();
|
||||
ASSERT_TRUE(isDefaultLocation(sc));
|
||||
|
||||
loc = "a:b:c";
|
||||
FingerprintHalProperties::sensor_location(loc);
|
||||
sc = mEngine.getSensorLocation();
|
||||
ASSERT_TRUE(isDefaultLocation(sc));
|
||||
const std::vector<std::string> badStr{"", "100", "10:20", "10,20,5", "a:b:c"};
|
||||
SensorLocation sc;
|
||||
for (const auto& s : badStr) {
|
||||
FingerprintHalProperties::sensor_location(s);
|
||||
sc = mEngine.getSensorLocation();
|
||||
ASSERT_TRUE(isDefaultLocation(sc));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(FakeFingerprintEngineUdfpsTest, initialization) {
|
||||
ASSERT_TRUE(mEngine.getWorkMode() == FakeFingerprintEngineUdfps::WorkMode::kIdle);
|
||||
}
|
||||
|
||||
TEST_F(FakeFingerprintEngineUdfpsTest, authenticate) {
|
||||
std::shared_ptr<TestSessionCallback> cb = ndk::SharedRefBase::make<TestSessionCallback>();
|
||||
std::promise<void> cancel;
|
||||
mEngine.authenticateImpl(cb.get(), 1, cancel.get_future());
|
||||
ASSERT_TRUE(mEngine.getWorkMode() == FakeFingerprintEngineUdfps::WorkMode::kAuthenticate);
|
||||
mEngine.onPointerDownImpl(1, 2, 3, 4.0, 5.0);
|
||||
ASSERT_EQ(cb->getAuthenticationCount(), 0);
|
||||
mEngine.onUiReadyImpl();
|
||||
ASSERT_EQ(cb->getAuthenticationCount(), 1);
|
||||
}
|
||||
|
||||
TEST_F(FakeFingerprintEngineUdfpsTest, enroll) {
|
||||
std::shared_ptr<TestSessionCallback> cb = ndk::SharedRefBase::make<TestSessionCallback>();
|
||||
std::promise<void> cancel;
|
||||
keymaster::HardwareAuthToken hat{.mac = {5, 6}};
|
||||
FingerprintHalProperties::next_enrollment("5:0,0:true");
|
||||
mEngine.enrollImpl(cb.get(), hat, cancel.get_future());
|
||||
ASSERT_TRUE(mEngine.getWorkMode() == FakeFingerprintEngineUdfps::WorkMode::kEnroll);
|
||||
mEngine.onPointerDownImpl(1, 2, 3, 4.0, 5.0);
|
||||
ASSERT_EQ(cb->mEnrollmentProgress, 0);
|
||||
mEngine.onUiReadyImpl();
|
||||
ASSERT_TRUE(cb->mEnrollmentProgress > 0);
|
||||
}
|
||||
|
||||
TEST_F(FakeFingerprintEngineUdfpsTest, detectInteraction) {
|
||||
FingerprintHalProperties::detect_interaction(true);
|
||||
FingerprintHalProperties::enrollments({1, 2});
|
||||
FingerprintHalProperties::enrollment_hit(2);
|
||||
FingerprintHalProperties::operation_detect_interaction_acquired("");
|
||||
std::shared_ptr<TestSessionCallback> cb = ndk::SharedRefBase::make<TestSessionCallback>();
|
||||
std::promise<void> cancel;
|
||||
mEngine.detectInteractionImpl(cb.get(), cancel.get_future());
|
||||
ASSERT_TRUE(mEngine.getWorkMode() == FakeFingerprintEngineUdfps::WorkMode::kDetectInteract);
|
||||
mEngine.onPointerDownImpl(1, 2, 3, 4.0, 5.0);
|
||||
ASSERT_EQ(cb->getDetectInteractionCount(), 0);
|
||||
mEngine.onUiReadyImpl();
|
||||
ASSERT_EQ(cb->getDetectInteractionCount(), 1);
|
||||
}
|
||||
// More
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <android/binder_process.h>
|
||||
#include <fingerprint.sysprop.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "FakeLockoutTracker.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
using namespace ::android::fingerprint::virt;
|
||||
using namespace ::aidl::android::hardware::biometrics::fingerprint;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
class FakeLockoutTrackerTest : public ::testing::Test {
|
||||
protected:
|
||||
static constexpr int32_t LOCKOUT_TIMED_THRESHOLD = 3;
|
||||
static constexpr int32_t LOCKOUT_PERMANENT_THRESHOLD = 5;
|
||||
static constexpr int32_t LOCKOUT_TIMED_DURATION = 100;
|
||||
|
||||
void SetUp() override {
|
||||
FingerprintHalProperties::lockout_timed_threshold(LOCKOUT_TIMED_THRESHOLD);
|
||||
FingerprintHalProperties::lockout_timed_duration(LOCKOUT_TIMED_DURATION);
|
||||
FingerprintHalProperties::lockout_permanent_threshold(LOCKOUT_PERMANENT_THRESHOLD);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// reset to default
|
||||
FingerprintHalProperties::lockout_timed_threshold(5);
|
||||
FingerprintHalProperties::lockout_timed_duration(20);
|
||||
FingerprintHalProperties::lockout_permanent_threshold(10000);
|
||||
FingerprintHalProperties::lockout_enable(false);
|
||||
FingerprintHalProperties::lockout(false);
|
||||
}
|
||||
|
||||
FakeLockoutTracker mLockoutTracker;
|
||||
};
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptDisable) {
|
||||
FingerprintHalProperties::lockout_enable(false);
|
||||
for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD + 1; i++) mLockoutTracker.addFailedAttempt();
|
||||
ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
|
||||
mLockoutTracker.reset();
|
||||
}
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimed) {
|
||||
FingerprintHalProperties::lockout_enable(true);
|
||||
for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++) mLockoutTracker.addFailedAttempt();
|
||||
ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kTimed);
|
||||
// time left
|
||||
int N = 5;
|
||||
int64_t prevTimeLeft = INT_MIN;
|
||||
for (int i = 0; i < N; i++) {
|
||||
SLEEP_MS(LOCKOUT_TIMED_DURATION / N + 1);
|
||||
int64_t currTimeLeft = mLockoutTracker.getLockoutTimeLeft();
|
||||
ASSERT_TRUE(currTimeLeft > prevTimeLeft);
|
||||
prevTimeLeft = currTimeLeft;
|
||||
}
|
||||
ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
|
||||
mLockoutTracker.reset();
|
||||
}
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptPermanent) {
|
||||
FingerprintHalProperties::lockout_enable(true);
|
||||
for (int i = 0; i < LOCKOUT_PERMANENT_THRESHOLD - 1; i++) mLockoutTracker.addFailedAttempt();
|
||||
ASSERT_NE(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kPermanent);
|
||||
mLockoutTracker.addFailedAttempt();
|
||||
ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kPermanent);
|
||||
ASSERT_TRUE(FingerprintHalProperties::lockout());
|
||||
mLockoutTracker.reset();
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
ABinderProcess_startThreadPool();
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
Reference in New Issue
Block a user