Merge "Support Face Virtual HAL operation latency randomization" into main

This commit is contained in:
Jeff Pu 2024-01-08 22:18:08 +00:00 committed by Android (Google) Code Review
commit b515d81fb7
6 changed files with 89 additions and 127 deletions

View file

@ -70,7 +70,7 @@ void FakeFaceEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareA
EnrollmentType /*enrollmentType*/,
const std::vector<Feature>& /*features*/,
const std::future<void>& cancel) {
BEGIN_OP(FaceHalProperties::operation_start_enroll_latency().value_or(0));
BEGIN_OP(getLatency(FaceHalProperties::operation_enroll_latency()));
// Do proper HAT verification in the real implementation.
if (hat.mac.empty()) {
@ -158,7 +158,7 @@ void FakeFaceEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareA
void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationId*/,
const std::future<void>& cancel) {
BEGIN_OP(FaceHalProperties::operation_authenticate_latency().value_or(0));
BEGIN_OP(getLatency(FaceHalProperties::operation_authenticate_latency()));
auto id = FaceHalProperties::enrollment_hit().value_or(0);
auto enrolls = FaceHalProperties::enrollments();
@ -291,7 +291,7 @@ std::pair<Error, int32_t> FakeFaceEngine::convertError(int32_t code) {
}
void FakeFaceEngine::detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel) {
BEGIN_OP(FaceHalProperties::operation_detect_interaction_latency().value_or(0));
BEGIN_OP(getLatency(FaceHalProperties::operation_detect_interaction_latency()));
if (FaceHalProperties::operation_detect_interaction_fails().value_or(false)) {
LOG(ERROR) << "Fail: operation_detect_interaction_fails";
@ -418,4 +418,33 @@ void FakeFaceEngine::resetLockoutImpl(ISessionCallback* cb,
cb->onLockoutCleared();
}
int32_t FakeFaceEngine::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);
}
int32_t FakeFaceEngine::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;
}
} // namespace aidl::android::hardware::biometrics::face

View file

@ -60,6 +60,7 @@ class FakeFaceEngine {
void getAuthenticatorIdImpl(ISessionCallback* cb);
void invalidateAuthenticatorIdImpl(ISessionCallback* cb);
void resetLockoutImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& /*hat*/);
int32_t getLatency(const std::vector<std::optional<std::int32_t>>& latencyVec);
virtual std::string toString() const {
std::ostringstream os;
@ -71,6 +72,7 @@ class FakeFaceEngine {
std::mt19937 mRandom;
private:
int32_t getRandomInRange(int32_t bound1, int32_t bound2);
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);

View file

@ -28,7 +28,9 @@ class FakeLockoutTracker {
public:
FakeLockoutTracker()
: mFailedCount(0),
mTimedFailedCount(0),
mLastFailedTime(0),
mCurrentMode(LockoutMode::kNone),
mIsLockoutTimerStarted(false),
mIsLockoutTimerAborted(false) {}
~FakeLockoutTracker() {}

View file

@ -1,98 +0,0 @@
props {
owner: Vendor
module: "android.face.virt.FaceHalProperties"
prop {
api_name: "authenticator_id"
type: Long
access: ReadWrite
prop_name: "vendor.face.virtual.authenticator_id"
}
prop {
api_name: "challenge"
type: Long
access: ReadWrite
prop_name: "vendor.face.virtual.challenge"
}
prop {
api_name: "enrollment_hit"
type: Integer
access: ReadWrite
prop_name: "vendor.face.virtual.enrollment_hit"
}
prop {
api_name: "enrollments"
type: IntegerList
access: ReadWrite
prop_name: "persist.vendor.face.virtual.enrollments"
}
prop {
api_name: "features"
type: IntegerList
access: ReadWrite
prop_name: "persist.vendor.face.virtual.features"
}
prop {
api_name: "lockout"
access: ReadWrite
prop_name: "vendor.face.virtual.lockout"
}
prop {
api_name: "next_enrollment"
type: String
access: ReadWrite
prop_name: "vendor.face.virtual.next_enrollment"
}
prop {
api_name: "operation_authenticate_duration"
type: Integer
access: ReadWrite
prop_name: "vendor.face.virtual.operation_authenticate_duration"
}
prop {
api_name: "operation_authenticate_fails"
access: ReadWrite
prop_name: "vendor.face.virtual.operation_authenticate_fails"
}
prop {
api_name: "operation_authenticate_latency"
type: Integer
access: ReadWrite
prop_name: "vendor.face.virtual.operation_authenticate_latency"
}
prop {
api_name: "operation_detect_interaction_fails"
access: ReadWrite
prop_name: "vendor.face.virtual.operation_detect_interaction_fails"
}
prop {
api_name: "operation_detect_interaction_latency"
type: Integer
access: ReadWrite
prop_name: "vendor.face.virtual.operation_detect_interaction_latency"
}
prop {
api_name: "operation_enroll_fails"
access: ReadWrite
prop_name: "vendor.face.virtual.operation_enroll_fails"
}
prop {
api_name: "operation_start_enroll_latency"
type: Integer
access: ReadWrite
prop_name: "vendor.face.virtual.operation_start_enroll_latency"
}
prop {
api_name: "strength"
type: String
access: ReadWrite
prop_name: "persist.vendor.face.virtual.strength"
enum_values: "convenience|weak|strong"
}
prop {
api_name: "type"
type: String
access: ReadWrite
prop_name: "persist.vendor.face.virtual.type"
enum_values: "IR|RGB"
}
}

View file

@ -7,7 +7,7 @@ owner: Vendor
prop {
prop_name: "persist.vendor.face.virtual.type"
type: String
scope: Public
scope: Internal
access: ReadWrite
enum_values: "IR|RGB"
api_name: "type"
@ -17,7 +17,7 @@ prop {
prop {
prop_name: "persist.vendor.face.virtual.strength"
type: String
scope: Public
scope: Internal
access: ReadWrite
enum_values: "convenience|weak|strong"
api_name: "strength"
@ -27,7 +27,7 @@ prop {
prop {
prop_name: "persist.vendor.face.virtual.enrollments"
type: IntegerList
scope: Public
scope: Internal
access: ReadWrite
api_name: "enrollments"
}
@ -36,7 +36,7 @@ prop {
prop {
prop_name: "persist.vendor.face.virtual.features"
type: IntegerList
scope: Public
scope: Internal
access: ReadWrite
api_name: "features"
}
@ -46,20 +46,11 @@ prop {
prop {
prop_name: "vendor.face.virtual.enrollment_hit"
type: Integer
scope: Public
scope: Internal
access: ReadWrite
api_name: "enrollment_hit"
}
# The initial latency for enrollment
prop {
prop_name: "vendor.face.virtual.operation_start_enroll_latency"
type: Integer
scope: Public
access: ReadWrite
api_name: "operation_start_enroll_latency"
}
# the next enrollment in the format:
# "<id>,<bucket_id>:<delay>:<succeeds>,<bucket_id>..."
# for example: "0:1,0:100:1,1:200:1" indicating that bucket 0 took
@ -69,7 +60,7 @@ prop {
prop {
prop_name: "vendor.face.virtual.next_enrollment"
type: String
scope: Public
scope: Internal
access: ReadWrite
api_name: "next_enrollment"
}
@ -78,7 +69,7 @@ prop {
prop {
prop_name: "vendor.face.virtual.authenticator_id"
type: Long
scope: Public
scope: Internal
access: ReadWrite
api_name: "authenticator_id"
}
@ -87,7 +78,7 @@ prop {
prop {
prop_name: "vendor.face.virtual.challenge"
type: Long
scope: Public
scope: Internal
access: ReadWrite
api_name: "challenge"
}
@ -96,7 +87,7 @@ prop {
prop {
prop_name: "vendor.face.virtual.lockout"
type: Boolean
scope: Public
scope: Internal
access: ReadWrite
api_name: "lockout"
}
@ -105,7 +96,7 @@ prop {
prop {
prop_name: "vendor.face.virtual.operation_authenticate_fails"
type: Boolean
scope: Public
scope: Internal
access: ReadWrite
api_name: "operation_authenticate_fails"
}
@ -114,7 +105,7 @@ prop {
prop {
prop_name: "vendor.face.virtual.operation_detect_interaction_fails"
type: Boolean
scope: Public
scope: Internal
access: ReadWrite
api_name: "operation_detect_interaction_fails"
}
@ -123,7 +114,7 @@ prop {
prop {
prop_name: "vendor.face.virtual.operation_enroll_fails"
type: Boolean
scope: Public
scope: Internal
access: ReadWrite
api_name: "operation_enroll_fails"
}
@ -133,8 +124,8 @@ prop {
# the HAL will send AcquiredInfo::START and AcquiredInfo::FIRST_FRAME_RECEIVED
prop {
prop_name: "vendor.face.virtual.operation_authenticate_latency"
type: Integer
scope: Public
type: IntegerList
scope: Internal
access: ReadWrite
api_name: "operation_authenticate_latency"
}
@ -142,18 +133,27 @@ prop {
# add a latency to detectInteraction operations
prop {
prop_name: "vendor.face.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
prop {
prop_name: "vendor.face.virtual.operation_enroll_latency"
type: IntegerList
scope: Internal
access: ReadWrite
api_name: "operation_enroll_latency"
}
# millisecond duration for authenticate operations
# (waits for changes to enrollment_hit)
prop {
prop_name: "vendor.face.virtual.operation_authenticate_duration"
type: Integer
scope: Public
scope: Internal
access: ReadWrite
api_name: "operation_authenticate_duration"
}

View file

@ -22,6 +22,7 @@
#include <android-base/logging.h>
#include "FakeFaceEngine.h"
#include "util/Util.h"
using namespace ::android::face::virt;
using namespace ::aidl::android::hardware::biometrics::face;
@ -137,11 +138,15 @@ class FakeFaceEngineTest : public ::testing::Test {
void SetUp() override {
LOG(ERROR) << "JRM SETUP";
mCallback = ndk::SharedRefBase::make<TestSessionCallback>();
}
void TearDown() override {
FaceHalProperties::enrollments({});
FaceHalProperties::challenge({});
FaceHalProperties::features({});
FaceHalProperties::authenticator_id({});
FaceHalProperties::strength("");
FaceHalProperties::operation_detect_interaction_latency({});
}
FakeFaceEngine mEngine;
@ -383,4 +388,26 @@ TEST_F(FakeFaceEngineTest, ResetLockoutWithAuth) {
ASSERT_FALSE(mCallback->mAuthenticateFailed);
}
TEST_F(FakeFaceEngineTest, LatencyDefault) {
FaceHalProperties::operation_detect_interaction_latency({});
ASSERT_EQ(DEFAULT_LATENCY,
mEngine.getLatency(FaceHalProperties::operation_detect_interaction_latency()));
}
TEST_F(FakeFaceEngineTest, LatencyFixed) {
FaceHalProperties::operation_detect_interaction_latency({10});
ASSERT_EQ(10, mEngine.getLatency(FaceHalProperties::operation_detect_interaction_latency()));
}
TEST_F(FakeFaceEngineTest, LatencyRandom) {
FaceHalProperties::operation_detect_interaction_latency({1, 1000});
std::set<int32_t> latencySet;
for (int i = 0; i < 100; i++) {
auto x = mEngine.getLatency(FaceHalProperties::operation_detect_interaction_latency());
ASSERT_TRUE(x >= 1 && x <= 1000);
latencySet.insert(x);
}
ASSERT_TRUE(latencySet.size() > 95); // unique values
}
} // namespace aidl::android::hardware::biometrics::face