mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Merge 24Q4 (ab/12406339) into aosp-main-future
Bug: 370570306 Merged-In: I30915c907c06f577d6428af8aa745dd94c674dc1 Change-Id: Ib0409a7c7113802cdb08693b81a4e9618071f8cc
This commit is contained in:
@@ -55,6 +55,9 @@ union HapticGenerator {
|
||||
parcelable HapticScale {
|
||||
int id;
|
||||
android.hardware.audio.effect.HapticGenerator.VibratorScale scale = android.hardware.audio.effect.HapticGenerator.VibratorScale.MUTE;
|
||||
float scaleFactor = (-1.0f) /* -1.000000f */;
|
||||
float adaptiveScaleFactor = (-1.0f) /* -1.000000f */;
|
||||
const float UNDEFINED_SCALE_FACTOR = (-1.0f) /* -1.000000f */;
|
||||
}
|
||||
@VintfStability
|
||||
parcelable VibratorInformation {
|
||||
|
||||
@@ -55,14 +55,52 @@ union HapticGenerator {
|
||||
|
||||
@VintfStability
|
||||
parcelable HapticScale {
|
||||
/**
|
||||
* Representation of undefined scale factor, applied by default for backwards compatibility.
|
||||
*/
|
||||
const float UNDEFINED_SCALE_FACTOR = -1.0f;
|
||||
|
||||
/**
|
||||
* Audio track ID.
|
||||
*/
|
||||
int id;
|
||||
|
||||
/**
|
||||
* Haptic intensity.
|
||||
*
|
||||
* This represents haptics scale as fixed levels defined by VibrationScale. If the field
|
||||
* scaleFactor is defined then this will be ignored in favor of scaleFactor, otherwise this
|
||||
* will be used to define the intensity for the haptics.
|
||||
*/
|
||||
VibratorScale scale = VibratorScale.MUTE;
|
||||
|
||||
/**
|
||||
* Haptic scale factor.
|
||||
*
|
||||
* This is a continuous scale representation of VibratorScale, allowing flexible number of
|
||||
* scale levels. If this field is defined then it will be used to define the intensity of
|
||||
* the haptics, instead of the old VibratorScale field. If this field is undefined then the
|
||||
* old VibratorScale field will be used.
|
||||
*
|
||||
* The value zero represents the same as VibratorScale.MUTE and the value one represents
|
||||
* VibratorScale.NONE. Values in (0,1) should scale down, and values > 1 should scale up
|
||||
* within hardware bounds. Negative values will be ignored.
|
||||
*/
|
||||
float scaleFactor = -1.0f; // UNDEFINED_SCALE_FACTOR
|
||||
|
||||
/**
|
||||
* Haptic adaptive scale factor.
|
||||
*
|
||||
* This is an additional scale value that should be applied on top of the vibrator scale to
|
||||
* adapt to the device current state. This should be applied to linearly scale the haptic
|
||||
* data after scale/scaleFactor is applied.
|
||||
*
|
||||
* The value zero mutes the haptics, even if the scale/scaleFactor are not set to MUTE/zero.
|
||||
* The value one will not scale the haptics, and can be used as a constant for no-op.
|
||||
* Values in (0,1) should scale down. Values > 1 should scale up within hardware bounds.
|
||||
* Negative values will be ignored.
|
||||
*/
|
||||
float adaptiveScaleFactor = -1.0f; // UNDEFINED_SCALE_FACTOR
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -136,6 +136,9 @@ cc_test {
|
||||
name: "VtsHalHapticGeneratorTargetTest",
|
||||
defaults: ["VtsHalAudioEffectTargetTestDefaults"],
|
||||
srcs: ["VtsHalHapticGeneratorTargetTest.cpp"],
|
||||
shared_libs: [
|
||||
"libaudioutils",
|
||||
],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
|
||||
@@ -479,6 +479,17 @@ class EffectHelper {
|
||||
mOutputSamples = common.output.frameCount * mOutputFrameSize / sizeof(float);
|
||||
}
|
||||
|
||||
void generateInput(std::vector<float>& input, float inputFrequency, float samplingFrequency,
|
||||
size_t inputSize = 0) {
|
||||
if (inputSize == 0 || inputSize > input.size()) {
|
||||
inputSize = input.size();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < inputSize; i++) {
|
||||
input[i] = sin(2 * M_PI * inputFrequency * i / samplingFrequency);
|
||||
}
|
||||
}
|
||||
|
||||
bool mIsSpatializer;
|
||||
Descriptor mDescriptor;
|
||||
size_t mInputFrameSize, mOutputFrameSize;
|
||||
|
||||
@@ -21,11 +21,13 @@
|
||||
#define LOG_TAG "VtsHalHapticGeneratorTargetTest"
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_enums.h>
|
||||
#include <audio_utils/power.h>
|
||||
|
||||
#include "EffectHelper.h"
|
||||
|
||||
using namespace android;
|
||||
|
||||
using aidl::android::hardware::audio::common::getChannelCount;
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator;
|
||||
using aidl::android::hardware::audio::effect::HapticGenerator;
|
||||
@@ -34,406 +36,412 @@ using aidl::android::hardware::audio::effect::IFactory;
|
||||
using aidl::android::hardware::audio::effect::Parameter;
|
||||
using android::hardware::audio::common::testing::detail::TestExecutionTracer;
|
||||
|
||||
/**
|
||||
* Here we focus on specific parameter checking, general IEffect interfaces testing performed in
|
||||
* VtsAudioEffectTargetTest.
|
||||
*/
|
||||
enum ParamName {
|
||||
PARAM_INSTANCE_NAME,
|
||||
PARAM_HAPTIC_SCALE_ID,
|
||||
PARAM_HAPTIC_SCALE_VIBRATOR_SCALE,
|
||||
PARAM_VIBRATION_INFORMATION_RESONANT_FREQUENCY,
|
||||
PARAM_VIBRATION_INFORMATION_Q_FACTOR,
|
||||
PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE,
|
||||
};
|
||||
using HapticGeneratorParamTestParam =
|
||||
std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int,
|
||||
HapticGenerator::VibratorScale, float, float, float>;
|
||||
|
||||
/*
|
||||
* Testing parameter range, assuming the parameter supported by effect is in this range.
|
||||
* Parameter should be within the valid range defined in the documentation,
|
||||
* for any supported value test expects EX_NONE from IEffect.setParameter(),
|
||||
* otherwise expect EX_ILLEGAL_ARGUMENT.
|
||||
*/
|
||||
|
||||
// TODO : Update the test values once range/capability is updated by implementation
|
||||
const int MIN_ID = std::numeric_limits<int>::min();
|
||||
const int MAX_ID = std::numeric_limits<int>::max();
|
||||
const float MIN_FLOAT = std::numeric_limits<float>::min();
|
||||
const float MAX_FLOAT = std::numeric_limits<float>::max();
|
||||
|
||||
const std::vector<int> kHapticScaleIdValues = {MIN_ID, 0, MAX_ID};
|
||||
const std::vector<HapticGenerator::VibratorScale> kVibratorScaleValues = {
|
||||
std::vector<HapticGenerator::VibratorScale> kScaleValues = {
|
||||
ndk::enum_range<HapticGenerator::VibratorScale>().begin(),
|
||||
ndk::enum_range<HapticGenerator::VibratorScale>().end()};
|
||||
|
||||
const std::vector<float> kScaleFactorValues = {HapticGenerator::HapticScale::UNDEFINED_SCALE_FACTOR,
|
||||
0.0f, 0.5f, 1.0f, MAX_FLOAT};
|
||||
const std::vector<float> kAdaptiveScaleFactorValues = {
|
||||
HapticGenerator::HapticScale::UNDEFINED_SCALE_FACTOR, 0.0f, 0.5f, 1.0f, MAX_FLOAT};
|
||||
|
||||
const std::vector<float> kResonantFrequencyValues = {MIN_FLOAT, 100, MAX_FLOAT};
|
||||
const std::vector<float> kQFactorValues = {MIN_FLOAT, 100, MAX_FLOAT};
|
||||
const std::vector<float> kMaxAmplitude = {MIN_FLOAT, 100, MAX_FLOAT};
|
||||
|
||||
class HapticGeneratorParamTest : public ::testing::TestWithParam<HapticGeneratorParamTestParam>,
|
||||
public EffectHelper {
|
||||
constexpr int HAPTIC_SCALE_FACTORS_EFFECT_MIN_VERSION = 3;
|
||||
|
||||
static const std::vector<int32_t> kHapticOutputLayouts = {
|
||||
AudioChannelLayout::LAYOUT_MONO_HAPTIC_A, AudioChannelLayout::LAYOUT_MONO_HAPTIC_AB,
|
||||
AudioChannelLayout::LAYOUT_STEREO_HAPTIC_A, AudioChannelLayout::LAYOUT_STEREO_HAPTIC_AB};
|
||||
|
||||
class HapticGeneratorHelper : public EffectHelper {
|
||||
public:
|
||||
HapticGeneratorParamTest()
|
||||
: mParamHapticScaleId(std::get<PARAM_HAPTIC_SCALE_ID>(GetParam())),
|
||||
mParamVibratorScale(std::get<PARAM_HAPTIC_SCALE_VIBRATOR_SCALE>(GetParam())),
|
||||
mParamResonantFrequency(
|
||||
std::get<PARAM_VIBRATION_INFORMATION_RESONANT_FREQUENCY>(GetParam())),
|
||||
mParamQFactor(std::get<PARAM_VIBRATION_INFORMATION_Q_FACTOR>(GetParam())),
|
||||
mParamMaxAmplitude(std::get<PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE>(GetParam())) {
|
||||
std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
|
||||
}
|
||||
void SetUp() override {
|
||||
void SetUpHapticGenerator(int32_t chMask = AudioChannelLayout::CHANNEL_HAPTIC_A) {
|
||||
ASSERT_NE(nullptr, mFactory);
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
|
||||
EXPECT_STATUS(EX_NONE, mEffect->getInterfaceVersion(&mEffectInterfaceVersion));
|
||||
|
||||
AudioChannelLayout layout =
|
||||
AudioChannelLayout::make<AudioChannelLayout::layoutMask>(chMask);
|
||||
|
||||
Parameter::Common common = createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
|
||||
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
|
||||
IEffect::OpenEffectReturn ret;
|
||||
0 /* session */, 1 /* ioHandle */, kSamplingFrequency /* iSampleRate */,
|
||||
kSamplingFrequency /* oSampleRate */, kFrameCount /* iFrameCount */,
|
||||
kFrameCount /* oFrameCount */, layout, layout);
|
||||
ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt, &ret, EX_NONE));
|
||||
ASSERT_NE(nullptr, mEffect);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
void TearDownHapticGenerator() {
|
||||
ASSERT_NO_FATAL_FAILURE(close(mEffect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
|
||||
ret = IEffect::OpenEffectReturn{};
|
||||
}
|
||||
|
||||
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
|
||||
Parameter createScaleParam(const std::vector<HapticGenerator::HapticScale>& hapticScales) {
|
||||
return Parameter::make<Parameter::specific>(
|
||||
Parameter::Specific::make<Parameter::Specific::hapticGenerator>(
|
||||
HapticGenerator::make<HapticGenerator::hapticScales>(hapticScales)));
|
||||
}
|
||||
|
||||
Parameter createVibratorParam(HapticGenerator::VibratorInformation vibrationInfo) {
|
||||
return Parameter::make<Parameter::specific>(
|
||||
Parameter::Specific::make<Parameter::Specific::hapticGenerator>(
|
||||
HapticGenerator::make<HapticGenerator::vibratorInfo>(vibrationInfo)));
|
||||
}
|
||||
|
||||
void setAndVerifyParameter(Parameter hapticParameter, HapticGenerator::Tag tag,
|
||||
binder_exception_t expected = EX_NONE) {
|
||||
EXPECT_STATUS(expected, mEffect->setParameter(hapticParameter))
|
||||
<< hapticParameter.toString();
|
||||
if (expected == EX_NONE) {
|
||||
// get parameter
|
||||
Parameter getParam;
|
||||
auto second = Parameter::Id::make<Parameter::Id::hapticGeneratorTag>(
|
||||
HapticGenerator::Id::make<HapticGenerator::Id::commonTag>(
|
||||
HapticGenerator::Tag(tag)));
|
||||
// If the set is successful, get param should match
|
||||
EXPECT_STATUS(expected, mEffect->getParameter(second, &getParam));
|
||||
EXPECT_EQ(hapticParameter, getParam) << "\nexpectedParam:" << hapticParameter.toString()
|
||||
<< "\ngetParam:" << getParam.toString();
|
||||
}
|
||||
}
|
||||
|
||||
HapticGenerator::VibratorInformation createVibratorInfo(float resonantFrequency, float qFactor,
|
||||
float amplitude) {
|
||||
return HapticGenerator::VibratorInformation(resonantFrequency, qFactor, amplitude);
|
||||
}
|
||||
|
||||
static const long kFrameCount = 10000;
|
||||
static constexpr int kSamplingFrequency = 44100;
|
||||
static constexpr int kDefaultScaleID = 0;
|
||||
static constexpr float kDefaultMaxAmp = 1;
|
||||
static constexpr float kDefaultResonantFrequency = 150;
|
||||
static constexpr float kDefaultQfactor = 8;
|
||||
static constexpr HapticGenerator::VibratorScale kDefaultScale =
|
||||
HapticGenerator::VibratorScale::NONE;
|
||||
std::shared_ptr<IFactory> mFactory;
|
||||
std::shared_ptr<IEffect> mEffect;
|
||||
Descriptor mDescriptor;
|
||||
int mParamHapticScaleId = 0;
|
||||
HapticGenerator::VibratorScale mParamVibratorScale = HapticGenerator::VibratorScale::MUTE;
|
||||
float mParamResonantFrequency = 0;
|
||||
float mParamQFactor = 0;
|
||||
float mParamMaxAmplitude = 0;
|
||||
IEffect::OpenEffectReturn ret;
|
||||
Parameter mHapticSpecificParameter;
|
||||
Parameter::Id mHapticIdParameter;
|
||||
int mEffectInterfaceVersion;
|
||||
};
|
||||
|
||||
void SetAndGetHapticGeneratorParameters() {
|
||||
for (auto& it : mTags) {
|
||||
auto& tag = std::get<ParamTestEnum::PARAM_TEST_TAG>(it);
|
||||
auto& setHg = std::get<ParamTestEnum::PARAM_TEST_TARGET>(it);
|
||||
/**
|
||||
*Tests do the following:
|
||||
* -Testing parameter range supported by the effect.
|
||||
* -For any supported value test expects EX_NONE from IEffect.setParameter(),
|
||||
* otherwise expect EX_ILLEGAL_ARGUMENT.
|
||||
* -Validating the effect by comparing the output energies of the supported parameters.
|
||||
**/
|
||||
|
||||
// set parameter
|
||||
Parameter expectParam;
|
||||
Parameter::Specific specific;
|
||||
specific.set<Parameter::Specific::hapticGenerator>(setHg);
|
||||
expectParam.set<Parameter::specific>(specific);
|
||||
using EffectInstance = std::pair<std::shared_ptr<IFactory>, Descriptor>;
|
||||
|
||||
const bool valid =
|
||||
isParameterValid<HapticGenerator, Range::hapticGenerator>(setHg, mDescriptor);
|
||||
const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
|
||||
EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString();
|
||||
class HapticGeneratorScaleParamTest : public ::testing::TestWithParam<EffectInstance>,
|
||||
public HapticGeneratorHelper {
|
||||
public:
|
||||
HapticGeneratorScaleParamTest() { std::tie(mFactory, mDescriptor) = GetParam(); }
|
||||
void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpHapticGenerator()); }
|
||||
void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownHapticGenerator()); }
|
||||
};
|
||||
|
||||
// only get if parameter in range and set success
|
||||
if (expected == EX_NONE) {
|
||||
Parameter getParam;
|
||||
Parameter::Id id;
|
||||
HapticGenerator::Id hgId;
|
||||
hgId.set<HapticGenerator::Id::commonTag>(tag);
|
||||
id.set<Parameter::Id::hapticGeneratorTag>(hgId);
|
||||
EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
|
||||
EXPECT_EQ(expectParam, getParam) << expectParam.toString() << "\n"
|
||||
<< getParam.toString();
|
||||
TEST_P(HapticGeneratorScaleParamTest, SetAndGetScales) {
|
||||
std::vector<HapticGenerator::HapticScale> hapticScales;
|
||||
for (int i = 0; i < static_cast<int>(kScaleValues.size()); i++) {
|
||||
hapticScales.push_back({.id = i, .scale = kScaleValues[i]});
|
||||
}
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
setAndVerifyParameter(createScaleParam(hapticScales), HapticGenerator::hapticScales));
|
||||
}
|
||||
|
||||
TEST_P(HapticGeneratorScaleParamTest, SetAndGetScaleFactors) {
|
||||
if (mEffectInterfaceVersion < HAPTIC_SCALE_FACTORS_EFFECT_MIN_VERSION) {
|
||||
GTEST_SKIP() << "Skipping HapticGenerator ScaleFactors test for effect version "
|
||||
<< std::to_string(mEffectInterfaceVersion);
|
||||
}
|
||||
|
||||
std::vector<HapticGenerator::HapticScale> hapticScales;
|
||||
for (int i = 0; i < static_cast<int>(kScaleFactorValues.size()); i++) {
|
||||
hapticScales.push_back(
|
||||
{.id = i, .scale = kScaleValues[0], .scaleFactor = kScaleFactorValues[i]});
|
||||
}
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
setAndVerifyParameter(createScaleParam(hapticScales), HapticGenerator::hapticScales));
|
||||
}
|
||||
|
||||
TEST_P(HapticGeneratorScaleParamTest, SetAndGetAdaptiveScaleFactors) {
|
||||
if (mEffectInterfaceVersion < HAPTIC_SCALE_FACTORS_EFFECT_MIN_VERSION) {
|
||||
GTEST_SKIP() << "Skipping HapticGenerator AdaptiveScaleFactors test for effect version "
|
||||
<< std::to_string(mEffectInterfaceVersion);
|
||||
}
|
||||
|
||||
std::vector<HapticGenerator::HapticScale> hapticScales;
|
||||
for (int i = 0; i < static_cast<int>(kAdaptiveScaleFactorValues.size()); i++) {
|
||||
hapticScales.push_back({.id = i,
|
||||
.scale = kScaleValues[0],
|
||||
.scaleFactor = kScaleFactorValues[3],
|
||||
.adaptiveScaleFactor = kAdaptiveScaleFactorValues[i]});
|
||||
}
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
setAndVerifyParameter(createScaleParam(hapticScales), HapticGenerator::hapticScales));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
HapticGeneratorValidTest, HapticGeneratorScaleParamTest,
|
||||
testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
|
||||
IFactory::descriptor, getEffectTypeUuidHapticGenerator())),
|
||||
[](const testing::TestParamInfo<HapticGeneratorScaleParamTest::ParamType>& info) {
|
||||
auto descriptor = info.param;
|
||||
return getPrefix(descriptor.second);
|
||||
});
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HapticGeneratorScaleParamTest);
|
||||
|
||||
enum VibratorParamName {
|
||||
VIBRATOR_PARAM_INSTANCE,
|
||||
VIBRATOR_PARAM_RESONANT_FREQUENCY,
|
||||
VIBRATOR_PARAM_Q_FACTOR,
|
||||
VIBRATOR_PARAM_MAX_AMPLITUDE,
|
||||
};
|
||||
|
||||
using HapticGeneratorVibratorInfoTestParam = std::tuple<EffectInstance, float, float, float>;
|
||||
|
||||
class HapticGeneratorVibratorInfoParamTest
|
||||
: public ::testing::TestWithParam<HapticGeneratorVibratorInfoTestParam>,
|
||||
public HapticGeneratorHelper {
|
||||
public:
|
||||
HapticGeneratorVibratorInfoParamTest()
|
||||
: mParamResonantFrequency(std::get<VIBRATOR_PARAM_RESONANT_FREQUENCY>(GetParam())),
|
||||
mParamQFactor(std::get<VIBRATOR_PARAM_Q_FACTOR>(GetParam())),
|
||||
mParamMaxAmplitude(std::get<VIBRATOR_PARAM_MAX_AMPLITUDE>(GetParam())) {
|
||||
std::tie(mFactory, mDescriptor) = std::get<VIBRATOR_PARAM_INSTANCE>(GetParam());
|
||||
}
|
||||
void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpHapticGenerator()); }
|
||||
void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownHapticGenerator()); }
|
||||
|
||||
float mParamResonantFrequency = kDefaultResonantFrequency;
|
||||
float mParamQFactor = kDefaultQfactor;
|
||||
float mParamMaxAmplitude = kDefaultMaxAmp;
|
||||
};
|
||||
|
||||
TEST_P(HapticGeneratorVibratorInfoParamTest, SetAndGetVibratorInformation) {
|
||||
auto vibratorInfo =
|
||||
createVibratorInfo(mParamResonantFrequency, mParamQFactor, mParamMaxAmplitude);
|
||||
if (isParameterValid<HapticGenerator, Range::hapticGenerator>(vibratorInfo, mDescriptor)) {
|
||||
ASSERT_NO_FATAL_FAILURE(setAndVerifyParameter(createVibratorParam(vibratorInfo),
|
||||
HapticGenerator::vibratorInfo));
|
||||
} else {
|
||||
ASSERT_NO_FATAL_FAILURE(setAndVerifyParameter(createVibratorParam(vibratorInfo),
|
||||
HapticGenerator::vibratorInfo,
|
||||
EX_ILLEGAL_ARGUMENT));
|
||||
}
|
||||
}
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HapticGeneratorVibratorInfoParamTest);
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
HapticGeneratorValidTest, HapticGeneratorVibratorInfoParamTest,
|
||||
::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
|
||||
IFactory::descriptor, getEffectTypeUuidHapticGenerator())),
|
||||
testing::ValuesIn(kResonantFrequencyValues),
|
||||
testing::ValuesIn(kQFactorValues), testing::ValuesIn(kMaxAmplitude)),
|
||||
[](const testing::TestParamInfo<HapticGeneratorVibratorInfoParamTest::ParamType>& info) {
|
||||
auto descriptor = std::get<VIBRATOR_PARAM_INSTANCE>(info.param).second;
|
||||
std::string resonantFrequency =
|
||||
std::to_string(std::get<VIBRATOR_PARAM_RESONANT_FREQUENCY>(info.param));
|
||||
std::string qFactor = std::to_string(std::get<VIBRATOR_PARAM_Q_FACTOR>(info.param));
|
||||
std::string maxAmplitude =
|
||||
std::to_string(std::get<VIBRATOR_PARAM_MAX_AMPLITUDE>(info.param));
|
||||
std::string name = getPrefix(descriptor) + "_resonantFrequency" + resonantFrequency +
|
||||
"_qFactor" + qFactor + "_maxAmplitude" + maxAmplitude;
|
||||
std::replace_if(
|
||||
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
|
||||
return name;
|
||||
});
|
||||
|
||||
/**
|
||||
* The data tests do the following
|
||||
* -Generate test input.
|
||||
* -Check if the parameters are supported. Skip the unsupported parameter values.
|
||||
* -Validate increase in haptic output energy energy.
|
||||
**/
|
||||
|
||||
enum DataTestParam { EFFECT_INSTANCE, LAYOUT };
|
||||
using HapticGeneratorDataTestParam = std::tuple<EffectInstance, int32_t>;
|
||||
|
||||
class HapticGeneratorDataTest : public ::testing::TestWithParam<HapticGeneratorDataTestParam>,
|
||||
public HapticGeneratorHelper {
|
||||
public:
|
||||
HapticGeneratorDataTest() : mChMask(std::get<LAYOUT>(GetParam())) {
|
||||
std::tie(mFactory, mDescriptor) = std::get<EFFECT_INSTANCE>(GetParam());
|
||||
mAudioChannelCount =
|
||||
getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChMask),
|
||||
~AudioChannelLayout::LAYOUT_HAPTIC_AB);
|
||||
mHapticChannelCount =
|
||||
getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChMask),
|
||||
AudioChannelLayout::LAYOUT_HAPTIC_AB);
|
||||
|
||||
mAudioSamples = kFrameCount * mAudioChannelCount;
|
||||
mHapticSamples = kFrameCount * mHapticChannelCount;
|
||||
mInput.resize(mHapticSamples + mAudioSamples, 0);
|
||||
mOutput.resize(mHapticSamples + mAudioSamples, 0);
|
||||
}
|
||||
|
||||
void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpHapticGenerator(mChMask)); }
|
||||
void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownHapticGenerator()); }
|
||||
|
||||
void generateSinePeriod() {
|
||||
size_t cycleSize = kSamplingFrequency / kInputFrequency;
|
||||
size_t startSize = 0;
|
||||
while (startSize < mAudioSamples) {
|
||||
for (size_t i = 0; i < cycleSize; i++) {
|
||||
mInput[i + startSize] = sin(2 * M_PI * kInputFrequency * i / kSamplingFrequency);
|
||||
}
|
||||
startSize += mAudioSamples / 4;
|
||||
}
|
||||
}
|
||||
|
||||
void setBaseVibratorParam() {
|
||||
auto vibratorInfo =
|
||||
createVibratorInfo(kDefaultResonantFrequency, kDefaultQfactor, kDefaultMaxAmp);
|
||||
if (isParameterValid<HapticGenerator, Range::hapticGenerator>(vibratorInfo, mDescriptor)) {
|
||||
ASSERT_NO_FATAL_FAILURE(setAndVerifyParameter(createVibratorParam(vibratorInfo),
|
||||
HapticGenerator::vibratorInfo));
|
||||
} else {
|
||||
GTEST_SKIP() << "Invalid base vibrator values, skipping the test\n";
|
||||
}
|
||||
}
|
||||
|
||||
void setBaseScaleParam() {
|
||||
ASSERT_NO_FATAL_FAILURE(setAndVerifyParameter(
|
||||
createScaleParam({HapticGenerator::HapticScale(kDefaultScaleID, kDefaultScale)}),
|
||||
HapticGenerator::hapticScales));
|
||||
}
|
||||
|
||||
void validateIncreasingEnergy(HapticGenerator::Tag tag) {
|
||||
float baseEnergy = -1;
|
||||
for (auto param : mHapticParam) {
|
||||
ASSERT_NO_FATAL_FAILURE(setAndVerifyParameter(param, tag));
|
||||
SCOPED_TRACE("Param: " + param.toString());
|
||||
ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput(mInput, mOutput, mEffect, &ret));
|
||||
float hapticOutputEnergy = audio_utils_compute_energy_mono(
|
||||
mOutput.data() + mAudioSamples, AUDIO_FORMAT_PCM_FLOAT, mHapticSamples);
|
||||
EXPECT_GT(hapticOutputEnergy, baseEnergy);
|
||||
baseEnergy = hapticOutputEnergy;
|
||||
}
|
||||
}
|
||||
|
||||
float findAbsMax(auto begin, auto end) {
|
||||
return *std::max_element(begin, end,
|
||||
[](float a, float b) { return std::abs(a) < std::abs(b); });
|
||||
}
|
||||
|
||||
void findMaxAmplitude() {
|
||||
for (float amp = 0.1; amp <= 1; amp += 0.1) {
|
||||
auto vibratorInfo = createVibratorInfo(kDefaultResonantFrequency, kDefaultQfactor, amp);
|
||||
if (!isParameterValid<HapticGenerator, Range::hapticGenerator>(vibratorInfo,
|
||||
mDescriptor)) {
|
||||
continue;
|
||||
}
|
||||
ASSERT_NO_FATAL_FAILURE(setAndVerifyParameter(createVibratorParam(vibratorInfo),
|
||||
HapticGenerator::vibratorInfo));
|
||||
ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput(mInput, mOutput, mEffect, &ret));
|
||||
float outAmplitude = findAbsMax(mOutput.begin() + mAudioSamples, mOutput.end());
|
||||
if (outAmplitude > mMaxAmplitude) {
|
||||
mMaxAmplitude = outAmplitude;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addHapticScaleParam(int id, HapticGenerator::VibratorScale scale) {
|
||||
HapticGenerator setHg;
|
||||
std::vector<HapticGenerator::HapticScale> hapticScales = {{.id = id, .scale = scale}};
|
||||
setHg.set<HapticGenerator::hapticScales>(hapticScales);
|
||||
mTags.push_back({HapticGenerator::hapticScales, setHg});
|
||||
}
|
||||
|
||||
void addVibratorInformationParam(float resonantFrequencyHz, float qFactor, float maxAmplitude) {
|
||||
HapticGenerator hg;
|
||||
HapticGenerator::VibratorInformation vibrationInfo = {
|
||||
.resonantFrequencyHz = resonantFrequencyHz,
|
||||
.qFactor = qFactor,
|
||||
.maxAmplitude = maxAmplitude};
|
||||
hg.set<HapticGenerator::vibratorInfo>(vibrationInfo);
|
||||
mTags.push_back({HapticGenerator::vibratorInfo, hg});
|
||||
}
|
||||
|
||||
private:
|
||||
enum ParamTestEnum { PARAM_TEST_TAG, PARAM_TEST_TARGET };
|
||||
std::vector<std::tuple<HapticGenerator::Tag, HapticGenerator>> mTags;
|
||||
|
||||
void CleanUp() { mTags.clear(); }
|
||||
const int kInputFrequency = 1000;
|
||||
float mMaxAmplitude = 0;
|
||||
size_t mHapticSamples;
|
||||
int32_t mChMask;
|
||||
int32_t mAudioChannelCount;
|
||||
int32_t mHapticChannelCount;
|
||||
size_t mAudioSamples;
|
||||
float mBaseHapticOutputEnergy;
|
||||
std::vector<Parameter> mHapticParam;
|
||||
// both input and output buffer includes audio and haptic samples
|
||||
std::vector<float> mInput;
|
||||
std::vector<float> mOutput;
|
||||
};
|
||||
|
||||
TEST_P(HapticGeneratorParamTest, SetAndGetHapticScale) {
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(mParamHapticScaleId, mParamVibratorScale));
|
||||
SetAndGetHapticGeneratorParameters();
|
||||
TEST_P(HapticGeneratorDataTest, IncreasingVibratorScaleTest) {
|
||||
generateInput(mInput, kInputFrequency, kSamplingFrequency, mAudioSamples);
|
||||
ASSERT_NO_FATAL_FAILURE(setBaseVibratorParam());
|
||||
for (HapticGenerator::VibratorScale scale : kScaleValues) {
|
||||
mHapticParam.push_back(
|
||||
createScaleParam({HapticGenerator::HapticScale(kDefaultScaleID, scale)}));
|
||||
}
|
||||
ASSERT_NO_FATAL_FAILURE(validateIncreasingEnergy(HapticGenerator::hapticScales));
|
||||
}
|
||||
|
||||
TEST_P(HapticGeneratorParamTest, SetAndGetMultipleHapticScales) {
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(mParamHapticScaleId, mParamVibratorScale));
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(mParamHapticScaleId, mParamVibratorScale));
|
||||
SetAndGetHapticGeneratorParameters();
|
||||
TEST_P(HapticGeneratorDataTest, IncreasingMaxAmplitudeTest) {
|
||||
generateInput(mInput, kInputFrequency, kSamplingFrequency, mAudioSamples);
|
||||
ASSERT_NO_FATAL_FAILURE(setBaseScaleParam());
|
||||
findMaxAmplitude();
|
||||
std::vector<float> increasingAmplitudeValues = {0.25f * mMaxAmplitude, 0.5f * mMaxAmplitude,
|
||||
0.75f * mMaxAmplitude, mMaxAmplitude};
|
||||
for (float amplitude : increasingAmplitudeValues) {
|
||||
auto vibratorInfo =
|
||||
createVibratorInfo(kDefaultResonantFrequency, kDefaultQfactor, amplitude);
|
||||
if (!isParameterValid<HapticGenerator, Range::hapticGenerator>(vibratorInfo, mDescriptor)) {
|
||||
continue;
|
||||
}
|
||||
mHapticParam.push_back(createVibratorParam(vibratorInfo));
|
||||
}
|
||||
ASSERT_NO_FATAL_FAILURE(validateIncreasingEnergy(HapticGenerator::vibratorInfo));
|
||||
}
|
||||
|
||||
TEST_P(HapticGeneratorParamTest, SetAndGetVibratorInformation) {
|
||||
EXPECT_NO_FATAL_FAILURE(addVibratorInformationParam(mParamResonantFrequency, mParamQFactor,
|
||||
mParamMaxAmplitude));
|
||||
SetAndGetHapticGeneratorParameters();
|
||||
TEST_P(HapticGeneratorDataTest, DescreasingResonantFrequencyTest) {
|
||||
std::vector<float> descreasingResonantFrequency = {800, 600, 400, 200};
|
||||
generateInput(mInput, kInputFrequency, kSamplingFrequency, mAudioSamples);
|
||||
ASSERT_NO_FATAL_FAILURE(setBaseScaleParam());
|
||||
for (float resonantFrequency : descreasingResonantFrequency) {
|
||||
auto vibratorInfo = createVibratorInfo(resonantFrequency, kDefaultQfactor, kDefaultMaxAmp);
|
||||
if (!isParameterValid<HapticGenerator, Range::hapticGenerator>(vibratorInfo, mDescriptor)) {
|
||||
continue;
|
||||
}
|
||||
mHapticParam.push_back(createVibratorParam(vibratorInfo));
|
||||
}
|
||||
ASSERT_NO_FATAL_FAILURE(validateIncreasingEnergy(HapticGenerator::vibratorInfo));
|
||||
}
|
||||
|
||||
TEST_P(HapticGeneratorDataTest, IncreasingQfactorTest) {
|
||||
std::vector<float> increasingQfactor = {16, 24, 32, 40};
|
||||
generateSinePeriod();
|
||||
ASSERT_NO_FATAL_FAILURE(setBaseScaleParam());
|
||||
for (float qFactor : increasingQfactor) {
|
||||
auto vibratorInfo = createVibratorInfo(kDefaultResonantFrequency, qFactor, kDefaultMaxAmp);
|
||||
if (!isParameterValid<HapticGenerator, Range::hapticGenerator>(vibratorInfo, mDescriptor)) {
|
||||
continue;
|
||||
}
|
||||
mHapticParam.push_back(createVibratorParam(vibratorInfo));
|
||||
}
|
||||
ASSERT_NO_FATAL_FAILURE(validateIncreasingEnergy(HapticGenerator::vibratorInfo));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
HapticGeneratorValidTest, HapticGeneratorParamTest,
|
||||
DataTest, HapticGeneratorDataTest,
|
||||
::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
|
||||
IFactory::descriptor, getEffectTypeUuidHapticGenerator())),
|
||||
testing::ValuesIn(kHapticScaleIdValues),
|
||||
testing::ValuesIn(kVibratorScaleValues),
|
||||
testing::ValuesIn(kResonantFrequencyValues),
|
||||
testing::ValuesIn(kQFactorValues), testing::ValuesIn(kMaxAmplitude)),
|
||||
[](const testing::TestParamInfo<HapticGeneratorParamTest::ParamType>& info) {
|
||||
auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
|
||||
std::string hapticScaleID = std::to_string(std::get<PARAM_HAPTIC_SCALE_ID>(info.param));
|
||||
std::string hapticScaleVibScale = std::to_string(
|
||||
static_cast<int>(std::get<PARAM_HAPTIC_SCALE_VIBRATOR_SCALE>(info.param)));
|
||||
std::string resonantFrequency = std::to_string(
|
||||
std::get<PARAM_VIBRATION_INFORMATION_RESONANT_FREQUENCY>(info.param));
|
||||
std::string qFactor =
|
||||
std::to_string(std::get<PARAM_VIBRATION_INFORMATION_Q_FACTOR>(info.param));
|
||||
std::string maxAmplitude =
|
||||
std::to_string(std::get<PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE>(info.param));
|
||||
std::string name = getPrefix(descriptor) + "_hapticScaleId" + hapticScaleID +
|
||||
"_hapticScaleVibScale" + hapticScaleVibScale + "_resonantFrequency" +
|
||||
resonantFrequency + "_qFactor" + qFactor + "_maxAmplitude" +
|
||||
maxAmplitude;
|
||||
std::replace_if(
|
||||
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
|
||||
testing::ValuesIn(kHapticOutputLayouts)),
|
||||
[](const testing::TestParamInfo<HapticGeneratorDataTest::ParamType>& info) {
|
||||
auto descriptor = std::get<EFFECT_INSTANCE>(info.param).second;
|
||||
std::string layout = "0x" + std::format("{:x}", std::get<LAYOUT>(info.param));
|
||||
std::string name = getPrefix(descriptor) + "_layout_" + layout;
|
||||
return name;
|
||||
});
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
HapticGeneratorInvalidTest, HapticGeneratorParamTest,
|
||||
::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
|
||||
IFactory::descriptor, getEffectTypeUuidHapticGenerator())),
|
||||
testing::Values(MIN_ID),
|
||||
testing::Values(HapticGenerator::VibratorScale::NONE),
|
||||
testing::Values(MIN_FLOAT), testing::Values(MIN_FLOAT),
|
||||
testing::Values(MIN_FLOAT)),
|
||||
[](const testing::TestParamInfo<HapticGeneratorParamTest::ParamType>& info) {
|
||||
auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
|
||||
std::string hapticScaleID = std::to_string(std::get<PARAM_HAPTIC_SCALE_ID>(info.param));
|
||||
std::string hapticScaleVibScale = std::to_string(
|
||||
static_cast<int>(std::get<PARAM_HAPTIC_SCALE_VIBRATOR_SCALE>(info.param)));
|
||||
std::string resonantFrequency = std::to_string(
|
||||
std::get<PARAM_VIBRATION_INFORMATION_RESONANT_FREQUENCY>(info.param));
|
||||
std::string qFactor =
|
||||
std::to_string(std::get<PARAM_VIBRATION_INFORMATION_Q_FACTOR>(info.param));
|
||||
std::string maxAmplitude =
|
||||
std::to_string(std::get<PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE>(info.param));
|
||||
std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
|
||||
descriptor.common.name + "_UUID_" +
|
||||
toString(descriptor.common.id.uuid) + "_hapticScaleId" +
|
||||
hapticScaleID + "_hapticScaleVibScale" + hapticScaleVibScale +
|
||||
"_resonantFrequency" + resonantFrequency + "_qFactor" + qFactor +
|
||||
"_maxAmplitude" + maxAmplitude;
|
||||
std::replace_if(
|
||||
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
|
||||
return name;
|
||||
});
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HapticGeneratorParamTest);
|
||||
|
||||
// Test HapticScale[] hapticScales parameter
|
||||
using HapticGeneratorScalesTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>>;
|
||||
class HapticGeneratorScalesTest : public ::testing::TestWithParam<HapticGeneratorScalesTestParam>,
|
||||
public EffectHelper {
|
||||
public:
|
||||
HapticGeneratorScalesTest() {
|
||||
std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
ASSERT_NE(nullptr, mFactory);
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
|
||||
|
||||
Parameter::Common common = createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
|
||||
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
|
||||
IEffect::OpenEffectReturn ret;
|
||||
ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt, &ret, EX_NONE));
|
||||
ASSERT_NE(nullptr, mEffect);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
ASSERT_NO_FATAL_FAILURE(close(mEffect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
|
||||
std::shared_ptr<IFactory> mFactory;
|
||||
std::shared_ptr<IEffect> mEffect;
|
||||
Descriptor mDescriptor;
|
||||
|
||||
void addHapticScaleParam(std::vector<HapticGenerator::HapticScale> scales) {
|
||||
mHapticScales.push_back(HapticGenerator::make<HapticGenerator::hapticScales>(scales));
|
||||
for (const auto& scale : scales) {
|
||||
expectMap.insert_or_assign(scale.id, scale.scale);
|
||||
}
|
||||
}
|
||||
|
||||
void SetHapticScaleParameters() {
|
||||
// std::unordered_set<HapticGenerator::HapticScale> target;
|
||||
for (auto& it : mHapticScales) {
|
||||
Parameter::Specific specific =
|
||||
Parameter::Specific::make<Parameter::Specific::hapticGenerator>(it);
|
||||
Parameter param = Parameter::make<Parameter::specific>(specific);
|
||||
EXPECT_STATUS(EX_NONE, mEffect->setParameter(param)) << param.toString();
|
||||
}
|
||||
}
|
||||
|
||||
void checkHapticScaleParameter() {
|
||||
// get parameter
|
||||
Parameter targetParam;
|
||||
HapticGenerator::Id hgId = HapticGenerator::Id::make<HapticGenerator::Id::commonTag>(
|
||||
HapticGenerator::hapticScales);
|
||||
Parameter::Id id = Parameter::Id::make<Parameter::Id::hapticGeneratorTag>(hgId);
|
||||
EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &targetParam));
|
||||
ASSERT_EQ(Parameter::specific, targetParam.getTag());
|
||||
Parameter::Specific specific = targetParam.get<Parameter::specific>();
|
||||
ASSERT_EQ(Parameter::Specific::hapticGenerator, specific.getTag());
|
||||
HapticGenerator hg = specific.get<Parameter::Specific::hapticGenerator>();
|
||||
ASSERT_EQ(HapticGenerator::hapticScales, hg.getTag());
|
||||
std::vector<HapticGenerator::HapticScale> scales = hg.get<HapticGenerator::hapticScales>();
|
||||
ASSERT_EQ(scales.size(), expectMap.size());
|
||||
for (const auto& scale : scales) {
|
||||
auto itor = expectMap.find(scale.id);
|
||||
ASSERT_NE(expectMap.end(), itor);
|
||||
ASSERT_EQ(scale.scale, itor->second);
|
||||
expectMap.erase(scale.id);
|
||||
}
|
||||
ASSERT_EQ(0ul, expectMap.size());
|
||||
}
|
||||
|
||||
const static HapticGenerator::HapticScale kHapticScaleWithMinId;
|
||||
const static HapticGenerator::HapticScale kHapticScaleWithMinIdNew;
|
||||
const static HapticGenerator::HapticScale kHapticScale;
|
||||
const static HapticGenerator::HapticScale kHapticScaleNew;
|
||||
const static HapticGenerator::HapticScale kHapticScaleWithMaxId;
|
||||
const static HapticGenerator::HapticScale kHapticScaleWithMaxIdNew;
|
||||
|
||||
std::vector<HapticGenerator> mHapticScales;
|
||||
|
||||
void CleanUp() {
|
||||
mHapticScales.clear();
|
||||
expectMap.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<int /* trackID */, HapticGenerator::VibratorScale> expectMap;
|
||||
};
|
||||
|
||||
const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleWithMinId = {
|
||||
.id = MIN_ID, .scale = HapticGenerator::VibratorScale::MUTE};
|
||||
const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleWithMinIdNew = {
|
||||
.id = MIN_ID, .scale = HapticGenerator::VibratorScale::VERY_LOW};
|
||||
const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScale = {
|
||||
.id = 1, .scale = HapticGenerator::VibratorScale::LOW};
|
||||
const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleNew = {
|
||||
.id = 1, .scale = HapticGenerator::VibratorScale::NONE};
|
||||
const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleWithMaxId = {
|
||||
.id = MAX_ID, .scale = HapticGenerator::VibratorScale::VERY_HIGH};
|
||||
const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleWithMaxIdNew = {
|
||||
.id = MAX_ID, .scale = HapticGenerator::VibratorScale::MUTE};
|
||||
|
||||
TEST_P(HapticGeneratorScalesTest, SetAndUpdateOne) {
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScale}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleNew}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMinId}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMinIdNew}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMaxId}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMaxIdNew}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
|
||||
}
|
||||
|
||||
TEST_P(HapticGeneratorScalesTest, SetAndUpdateVector) {
|
||||
EXPECT_NO_FATAL_FAILURE(
|
||||
addHapticScaleParam({kHapticScale, kHapticScaleWithMaxId, kHapticScaleWithMinId}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(
|
||||
{kHapticScaleNew, kHapticScaleWithMaxIdNew, kHapticScaleWithMinIdNew}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
|
||||
}
|
||||
|
||||
TEST_P(HapticGeneratorScalesTest, SetAndUpdateMultipleVector) {
|
||||
EXPECT_NO_FATAL_FAILURE(
|
||||
addHapticScaleParam({kHapticScale, kHapticScaleWithMaxId, kHapticScaleWithMinId}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(
|
||||
{kHapticScaleNew, kHapticScaleWithMaxIdNew, kHapticScaleWithMinIdNew}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
EXPECT_NO_FATAL_FAILURE(
|
||||
addHapticScaleParam({kHapticScale, kHapticScaleWithMaxId, kHapticScaleWithMinId}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
|
||||
}
|
||||
|
||||
TEST_P(HapticGeneratorScalesTest, SetOneAndAddMoreVector) {
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScale}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMaxId, kHapticScaleWithMinId}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
|
||||
}
|
||||
|
||||
TEST_P(HapticGeneratorScalesTest, SetMultipleAndAddOneVector) {
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMaxId, kHapticScaleWithMinId}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScale}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
|
||||
}
|
||||
|
||||
TEST_P(HapticGeneratorScalesTest, SetMultipleVectorRepeat) {
|
||||
EXPECT_NO_FATAL_FAILURE(
|
||||
addHapticScaleParam({kHapticScaleWithMaxId, kHapticScale, kHapticScaleWithMinId}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
EXPECT_NO_FATAL_FAILURE(
|
||||
addHapticScaleParam({kHapticScaleWithMaxId, kHapticScale, kHapticScaleWithMinId}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
EXPECT_NO_FATAL_FAILURE(
|
||||
addHapticScaleParam({kHapticScaleWithMaxId, kHapticScale, kHapticScaleWithMinId}));
|
||||
EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
HapticGeneratorScalesTest, HapticGeneratorScalesTest,
|
||||
::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
|
||||
IFactory::descriptor, getEffectTypeUuidHapticGenerator()))),
|
||||
[](const testing::TestParamInfo<HapticGeneratorScalesTest::ParamType>& info) {
|
||||
auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
|
||||
std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
|
||||
descriptor.common.name + "_UUID_" +
|
||||
toString(descriptor.common.id.uuid);
|
||||
std::replace_if(
|
||||
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
|
||||
return name;
|
||||
});
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HapticGeneratorScalesTest);
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HapticGeneratorDataTest);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
@@ -19,10 +19,58 @@
|
||||
"name": "CtsCarBuiltinApiHostTestCases"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceTest"
|
||||
"name": "CarServiceAudioTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceCarTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceClusterTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceDiagnosticTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceDrivingStateTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceEvsTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceGarageModeTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceInputTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceOsTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServicePmTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServicePowerTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServicePropertyTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceRemoteAccessTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceStorageMonitoringTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceTelemetryTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceUnitTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceVmsTest"
|
||||
},
|
||||
{
|
||||
"name": "CarServiceWatchdogTest"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -46,6 +46,9 @@ aidl_interface {
|
||||
ndk: {
|
||||
min_sdk_version: "29",
|
||||
},
|
||||
rust: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
versions_with_info: [
|
||||
{
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.automotive.evs</name>
|
||||
<fqname>IEvsEnumerator/hw/0</fqname>
|
||||
<version>1</version>
|
||||
<version>2</version>
|
||||
</hal>
|
||||
</manifest>
|
||||
|
||||
30
automotive/evs/aidl/rust_impl/Android.bp
Normal file
30
automotive/evs/aidl/rust_impl/Android.bp
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
rust_binary {
|
||||
name: "android.hardware.automotive.evs-aidl-rust-service",
|
||||
relative_install_path: "hw",
|
||||
vendor: true,
|
||||
srcs: ["src/*.rs"],
|
||||
crate_root: "src/main.rs",
|
||||
vintf_fragments: ["manifest_evs-rust-service.xml"],
|
||||
init_rc: ["evs-rust-service.rc"],
|
||||
rustlibs: [
|
||||
"android.hardware.automotive.evs-V2-rust",
|
||||
"libbinder_rs",
|
||||
"liblog_rust",
|
||||
],
|
||||
}
|
||||
21
automotive/evs/aidl/rust_impl/README.md
Normal file
21
automotive/evs/aidl/rust_impl/README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Rust Skeleton EVS HAL implementation.
|
||||
|
||||
WARNING: This is not a reference EVS HAL implementation and therefore does not
|
||||
provide any actual functionality.
|
||||
|
||||
This folder contains a skeleton EVS HAL implementation in Rust to demonstrate
|
||||
how vendors could implement their EVS HAL in Rust. To compile and run this
|
||||
implementation, please include below package to the device build script:
|
||||
|
||||
* `android.hardware.automotive.evs-aidl-rust-service`
|
||||
|
||||
Please note that this service will attempt to register the service as
|
||||
`IEvsEnumerator/rust/0` and therefore is also required to be declared in the
|
||||
service context by adding below line to a proper `service_contexts` file:
|
||||
|
||||
> android.hardware.automotive.evs.IEvsEnumerator/rust/0 u:object_r:hal_evs_service:s0
|
||||
|
||||
This implementation intentionally returns `binder::StatusCode::UNKNOWN_ERROR`
|
||||
for any API call except deprecated API for ultrasonics; the process will be
|
||||
panicked on these methods instead. Hence, this implementation does not comply
|
||||
with VTS tests and vendors must replace each method with actual implementation.
|
||||
8
automotive/evs/aidl/rust_impl/evs-rust-service.rc
Normal file
8
automotive/evs/aidl/rust_impl/evs-rust-service.rc
Normal file
@@ -0,0 +1,8 @@
|
||||
service vendor.evs-hal-rust-default /vendor/bin/hw/android.hardware.automotive.evs-aidl-rust-service
|
||||
class early_hal
|
||||
priority -20
|
||||
user graphics
|
||||
group automotive_evs camera
|
||||
onrestart restart cardisplayproxyd
|
||||
onrestart restart evsmanagerd
|
||||
disabled
|
||||
@@ -0,0 +1,7 @@
|
||||
<manifest version="2.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.automotive.evs</name>
|
||||
<version>2</version>
|
||||
<fqname>IEvsEnumerator/rust/0</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
113
automotive/evs/aidl/rust_impl/src/default_evs_hal.rs
Normal file
113
automotive/evs/aidl/rust_impl/src/default_evs_hal.rs
Normal file
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Copyright (C) 2024 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.
|
||||
//
|
||||
|
||||
use android_hardware_automotive_evs::aidl::android::hardware::automotive::evs::{
|
||||
CameraDesc::CameraDesc, DisplayState::DisplayState, IEvsCamera::IEvsCamera,
|
||||
IEvsDisplay::IEvsDisplay, IEvsEnumerator::IEvsEnumerator,
|
||||
IEvsEnumeratorStatusCallback::IEvsEnumeratorStatusCallback,
|
||||
IEvsUltrasonicsArray::IEvsUltrasonicsArray, Stream::Stream,
|
||||
UltrasonicsArrayDesc::UltrasonicsArrayDesc,
|
||||
};
|
||||
|
||||
pub struct DefaultEvsHal {}
|
||||
|
||||
impl binder::Interface for DefaultEvsHal {}
|
||||
|
||||
impl IEvsEnumerator for DefaultEvsHal {
|
||||
fn closeCamera(
|
||||
&self,
|
||||
_: &binder::Strong<(dyn IEvsCamera + 'static)>,
|
||||
) -> std::result::Result<(), binder::Status> {
|
||||
Err(binder::StatusCode::UNKNOWN_ERROR.into())
|
||||
}
|
||||
|
||||
fn closeDisplay(
|
||||
&self,
|
||||
_: &binder::Strong<(dyn IEvsDisplay + 'static)>,
|
||||
) -> std::result::Result<(), binder::Status> {
|
||||
Err(binder::StatusCode::UNKNOWN_ERROR.into())
|
||||
}
|
||||
|
||||
fn closeUltrasonicsArray(
|
||||
&self,
|
||||
_: &binder::Strong<(dyn IEvsUltrasonicsArray + 'static)>,
|
||||
) -> std::result::Result<(), binder::Status> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn getCameraList(&self) -> std::result::Result<std::vec::Vec<CameraDesc>, binder::Status> {
|
||||
Err(binder::StatusCode::UNKNOWN_ERROR.into())
|
||||
}
|
||||
|
||||
fn getDisplayIdList(&self) -> std::result::Result<std::vec::Vec<u8>, binder::Status> {
|
||||
Err(binder::StatusCode::UNKNOWN_ERROR.into())
|
||||
}
|
||||
|
||||
fn getDisplayState(&self) -> std::result::Result<DisplayState, binder::Status> {
|
||||
Err(binder::StatusCode::UNKNOWN_ERROR.into())
|
||||
}
|
||||
|
||||
fn getStreamList(
|
||||
&self,
|
||||
_: &CameraDesc,
|
||||
) -> std::result::Result<std::vec::Vec<Stream>, binder::Status> {
|
||||
Err(binder::StatusCode::UNKNOWN_ERROR.into())
|
||||
}
|
||||
|
||||
fn getUltrasonicsArrayList(
|
||||
&self,
|
||||
) -> std::result::Result<std::vec::Vec<UltrasonicsArrayDesc>, binder::Status> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn isHardware(&self) -> std::result::Result<bool, binder::Status> {
|
||||
Err(binder::StatusCode::UNKNOWN_ERROR.into())
|
||||
}
|
||||
|
||||
fn openCamera(
|
||||
&self,
|
||||
_: &str,
|
||||
_: &Stream,
|
||||
) -> std::result::Result<binder::Strong<(dyn IEvsCamera + 'static)>, binder::Status> {
|
||||
Err(binder::StatusCode::UNKNOWN_ERROR.into())
|
||||
}
|
||||
|
||||
fn openDisplay(
|
||||
&self,
|
||||
_: i32,
|
||||
) -> std::result::Result<binder::Strong<(dyn IEvsDisplay + 'static)>, binder::Status> {
|
||||
Err(binder::StatusCode::UNKNOWN_ERROR.into())
|
||||
}
|
||||
|
||||
fn openUltrasonicsArray(
|
||||
&self,
|
||||
_: &str,
|
||||
) -> std::result::Result<binder::Strong<(dyn IEvsUltrasonicsArray + 'static)>, binder::Status>
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn registerStatusCallback(
|
||||
&self,
|
||||
_: &binder::Strong<(dyn IEvsEnumeratorStatusCallback + 'static)>,
|
||||
) -> std::result::Result<(), binder::Status> {
|
||||
Err(binder::StatusCode::UNKNOWN_ERROR.into())
|
||||
}
|
||||
|
||||
fn getDisplayStateById(&self, _: i32) -> std::result::Result<DisplayState, binder::Status> {
|
||||
Err(binder::StatusCode::UNKNOWN_ERROR.into())
|
||||
}
|
||||
}
|
||||
42
automotive/evs/aidl/rust_impl/src/main.rs
Normal file
42
automotive/evs/aidl/rust_impl/src/main.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Copyright (C) 2024 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.
|
||||
//
|
||||
|
||||
mod default_evs_hal;
|
||||
|
||||
use crate::default_evs_hal::DefaultEvsHal;
|
||||
|
||||
use android_hardware_automotive_evs::aidl::android::hardware::automotive::evs::IEvsEnumerator::BnEvsEnumerator;
|
||||
|
||||
use log::info;
|
||||
|
||||
fn main() {
|
||||
binder::ProcessState::start_thread_pool();
|
||||
|
||||
let service = DefaultEvsHal {};
|
||||
|
||||
// Register HAL implementation as rust/0 instance.
|
||||
let service_name = "android.hardware.automotive.evs.IEvsEnumerator/rust/0";
|
||||
let service_binder = BnEvsEnumerator::new_binder(service, binder::BinderFeatures::default());
|
||||
|
||||
binder::add_service(service_name, service_binder.as_binder())
|
||||
.expect(format!("Failed to register {}.", service_name).as_str());
|
||||
info!("EVS Hardware Enumerator is ready");
|
||||
|
||||
binder::ProcessState::join_thread_pool();
|
||||
|
||||
// In normal operation, we don't expect the thread pool to exit.
|
||||
info!("EVS Hardware Enumerator is shutting down");
|
||||
}
|
||||
@@ -22,7 +22,7 @@ cc_defaults {
|
||||
name: "VehicleHalInterfaceDefaults",
|
||||
static_libs: [
|
||||
"android.hardware.automotive.vehicle-V3-ndk",
|
||||
"android.hardware.automotive.vehicle.property-V3-ndk",
|
||||
"android.hardware.automotive.vehicle.property-V4-ndk",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -30,6 +30,14 @@ rust_defaults {
|
||||
name: "VehicleHalInterfaceRustDefaults",
|
||||
rustlibs: [
|
||||
"android.hardware.automotive.vehicle-V3-rust",
|
||||
"android.hardware.automotive.vehicle.property-V3-rust",
|
||||
"android.hardware.automotive.vehicle.property-V4-rust",
|
||||
],
|
||||
}
|
||||
|
||||
aidl_interface_defaults {
|
||||
name: "android.hardware.automotive.vehicle-latest-defaults",
|
||||
imports: [
|
||||
"android.hardware.automotive.vehicle-V3",
|
||||
"android.hardware.automotive.vehicle.property-V4",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ cc_test {
|
||||
cc_test {
|
||||
name: "VehiclePropertyAnnotationCppTest",
|
||||
srcs: ["VehiclePropertyAnnotationCppTest.cpp"],
|
||||
header_libs: ["IVehicleGeneratedHeaders-V3"],
|
||||
header_libs: ["IVehicleGeneratedHeaders-V4"],
|
||||
defaults: ["VehicleHalInterfaceDefaults"],
|
||||
test_suites: ["general-tests"],
|
||||
}
|
||||
@@ -49,11 +49,11 @@ android_test {
|
||||
name: "VehiclePropertyAnnotationJavaTest",
|
||||
srcs: [
|
||||
"VehiclePropertyAnnotationJavaTest.java",
|
||||
":IVehicleGeneratedJavaFiles-V3",
|
||||
":IVehicleGeneratedJavaFiles-V4",
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.automotive.vehicle-V3-java",
|
||||
"android.hardware.automotive.vehicle.property-V3-java",
|
||||
"android.hardware.automotive.vehicle.property-V4-java",
|
||||
"androidx.test.runner",
|
||||
"truth",
|
||||
],
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyAccess.h>
|
||||
|
||||
// Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
#include <PerDisplayMaxBrightness.h>
|
||||
// End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace aidl {
|
||||
@@ -302,6 +306,9 @@ std::unordered_map<VehicleProperty, VehiclePropertyAccess> AccessForVehiclePrope
|
||||
{VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE, VehiclePropertyAccess::READ},
|
||||
{VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyAccess::READ_WRITE},
|
||||
{VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyAccess::READ},
|
||||
// Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
{PER_DISPLAY_MAX_BRIGHTNESS, VehiclePropertyAccess::READ},
|
||||
// End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
};
|
||||
|
||||
} // namespace vehicle
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
|
||||
#include <aidl/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.h>
|
||||
|
||||
// Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
#include <PerDisplayMaxBrightness.h>
|
||||
// End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace aidl {
|
||||
@@ -302,6 +306,9 @@ std::unordered_map<VehicleProperty, VehiclePropertyChangeMode> ChangeModeForVehi
|
||||
{VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE, VehiclePropertyChangeMode::ON_CHANGE},
|
||||
{VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
|
||||
{VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyChangeMode::ON_CHANGE},
|
||||
// Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
{PER_DISPLAY_MAX_BRIGHTNESS, VehiclePropertyChangeMode::STATIC},
|
||||
// End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
};
|
||||
|
||||
} // namespace vehicle
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
|
||||
|
||||
namespace aidl::android::hardware::automotive::vehicle {
|
||||
|
||||
// Same as VehicleProperty::PER_DISPLAY_MAX_BRIGHTNESS as defined in v4.
|
||||
static constexpr VehicleProperty PER_DISPLAY_MAX_BRIGHTNESS = (VehicleProperty)0x11410F4E;
|
||||
|
||||
} // namespace aidl::android::hardware::automotive::vehicle
|
||||
@@ -26,6 +26,10 @@
|
||||
|
||||
#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
|
||||
|
||||
// Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
#include <PerDisplayMaxBrightness.h>
|
||||
// End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace aidl {
|
||||
@@ -301,6 +305,9 @@ std::unordered_map<VehicleProperty, int32_t> VersionForVehicleProperty = {
|
||||
{VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE, 3},
|
||||
{VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, 3},
|
||||
{VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, 3},
|
||||
// Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
{PER_DISPLAY_MAX_BRIGHTNESS, 2},
|
||||
// End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
};
|
||||
|
||||
} // namespace vehicle
|
||||
|
||||
@@ -28,6 +28,10 @@ import java.util.Map;
|
||||
|
||||
public final class AccessForVehicleProperty {
|
||||
|
||||
// Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
private static final int PER_DISPLAY_MAX_BRIGHTNESS = 0x11410F4E;
|
||||
// End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
|
||||
public static final Map<Integer, Integer> values = Map.ofEntries(
|
||||
Map.entry(VehicleProperty.INFO_VIN, VehiclePropertyAccess.READ),
|
||||
Map.entry(VehicleProperty.INFO_MAKE, VehiclePropertyAccess.READ),
|
||||
@@ -294,7 +298,10 @@ public final class AccessForVehicleProperty {
|
||||
Map.entry(VehicleProperty.CROSS_TRAFFIC_MONITORING_ENABLED, VehiclePropertyAccess.READ_WRITE),
|
||||
Map.entry(VehicleProperty.CROSS_TRAFFIC_MONITORING_WARNING_STATE, VehiclePropertyAccess.READ),
|
||||
Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyAccess.READ_WRITE),
|
||||
Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyAccess.READ)
|
||||
Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyAccess.READ),
|
||||
// Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
Map.entry(PER_DISPLAY_MAX_BRIGHTNESS, VehiclePropertyAccess.READ)
|
||||
// End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@ import java.util.Map;
|
||||
|
||||
public final class ChangeModeForVehicleProperty {
|
||||
|
||||
// Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
private static final int PER_DISPLAY_MAX_BRIGHTNESS = 0x11410F4E;
|
||||
// End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
|
||||
public static final Map<Integer, Integer> values = Map.ofEntries(
|
||||
Map.entry(VehicleProperty.INFO_VIN, VehiclePropertyChangeMode.STATIC),
|
||||
Map.entry(VehicleProperty.INFO_MAKE, VehiclePropertyChangeMode.STATIC),
|
||||
@@ -294,7 +298,10 @@ public final class ChangeModeForVehicleProperty {
|
||||
Map.entry(VehicleProperty.CROSS_TRAFFIC_MONITORING_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
|
||||
Map.entry(VehicleProperty.CROSS_TRAFFIC_MONITORING_WARNING_STATE, VehiclePropertyChangeMode.ON_CHANGE),
|
||||
Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
|
||||
Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyChangeMode.ON_CHANGE)
|
||||
Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyChangeMode.ON_CHANGE),
|
||||
// Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
Map.entry(PER_DISPLAY_MAX_BRIGHTNESS, VehiclePropertyChangeMode.STATIC)
|
||||
// End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ cc_library {
|
||||
defaults: ["VehicleHalDefaults"],
|
||||
static_libs: ["VehicleHalUtils"],
|
||||
header_libs: [
|
||||
"IVehicleGeneratedHeaders-V3",
|
||||
"IVehicleGeneratedHeaders-V4",
|
||||
],
|
||||
shared_libs: ["libjsoncpp"],
|
||||
}
|
||||
@@ -44,7 +44,7 @@ cc_library {
|
||||
defaults: ["VehicleHalDefaults"],
|
||||
static_libs: ["VehicleHalUtils"],
|
||||
header_libs: [
|
||||
"IVehicleGeneratedHeaders-V3",
|
||||
"IVehicleGeneratedHeaders-V4",
|
||||
"libbinder_headers",
|
||||
],
|
||||
cflags: ["-DENABLE_VEHICLE_HAL_TEST_PROPERTIES"],
|
||||
@@ -60,7 +60,7 @@ cc_library_headers {
|
||||
defaults: ["VehicleHalDefaults"],
|
||||
static_libs: ["VehicleHalUtils"],
|
||||
header_libs: [
|
||||
"IVehicleGeneratedHeaders-V3",
|
||||
"IVehicleGeneratedHeaders-V4",
|
||||
],
|
||||
shared_libs: ["libjsoncpp"],
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@ cc_test {
|
||||
"VehicleHalJsonConfigLoader",
|
||||
"VehicleHalUtils",
|
||||
"libgtest",
|
||||
],
|
||||
shared_libs: [
|
||||
"libjsoncpp",
|
||||
],
|
||||
defaults: ["VehicleHalDefaults"],
|
||||
@@ -43,8 +41,6 @@ cc_test {
|
||||
"VehicleHalJsonConfigLoaderEnableTestProperties",
|
||||
"VehicleHalUtils",
|
||||
"libgtest",
|
||||
],
|
||||
shared_libs: [
|
||||
"libjsoncpp",
|
||||
],
|
||||
defaults: ["VehicleHalDefaults"],
|
||||
|
||||
8
automotive/vehicle/aidl/impl/default_config/TEST_MAPPING
Normal file
8
automotive/vehicle/aidl/impl/default_config/TEST_MAPPING
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"ravenwood-presubmit": [
|
||||
{
|
||||
"name": "CarServiceHostUnitTest",
|
||||
"host": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3195,19 +3195,22 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"property": "VehicleProperty::DISPLAY_BRIGHTNESS",
|
||||
"property": "VehicleProperty::PER_DISPLAY_BRIGHTNESS"
|
||||
},
|
||||
{
|
||||
"property": "VehicleProperty::PER_DISPLAY_MAX_BRIGHTNESS",
|
||||
"defaultValue": {
|
||||
"int32Values": [
|
||||
0,
|
||||
100,
|
||||
1,
|
||||
100,
|
||||
2,
|
||||
100,
|
||||
3,
|
||||
100
|
||||
]
|
||||
},
|
||||
"areas": [
|
||||
{
|
||||
"areaId": 0,
|
||||
"minInt32Value": 0,
|
||||
"maxInt32Value": 100
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"property": "VehicleProperty::VALET_MODE_ENABLED",
|
||||
|
||||
@@ -29,12 +29,10 @@ cc_test {
|
||||
"VehicleHalUtils",
|
||||
"libgmock",
|
||||
"libgtest",
|
||||
"libjsoncpp",
|
||||
],
|
||||
header_libs: [
|
||||
"IVehicleGeneratedHeaders-V3",
|
||||
],
|
||||
shared_libs: [
|
||||
"libjsoncpp",
|
||||
"IVehicleGeneratedHeaders-V4",
|
||||
],
|
||||
data: [
|
||||
":VehicleHalDefaultProperties_JSON",
|
||||
@@ -52,15 +50,13 @@ cc_test {
|
||||
"VehicleHalUtils",
|
||||
"libgmock",
|
||||
"libgtest",
|
||||
"libjsoncpp",
|
||||
],
|
||||
cflags: [
|
||||
"-DENABLE_VEHICLE_HAL_TEST_PROPERTIES",
|
||||
],
|
||||
header_libs: [
|
||||
"IVehicleGeneratedHeaders-V3",
|
||||
],
|
||||
shared_libs: [
|
||||
"libjsoncpp",
|
||||
"IVehicleGeneratedHeaders-V4",
|
||||
],
|
||||
data: [
|
||||
":VehicleHalDefaultProperties_JSON",
|
||||
|
||||
@@ -28,8 +28,6 @@ cc_test {
|
||||
"VehicleHalUtils",
|
||||
"FakeVehicleHalValueGenerators",
|
||||
"FakeObd2Frame",
|
||||
],
|
||||
shared_libs: [
|
||||
"libjsoncpp",
|
||||
],
|
||||
data: [
|
||||
|
||||
@@ -1056,6 +1056,10 @@ VhalResult<void> FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValu
|
||||
VhalResult<void> isAdasPropertyAvailableResult;
|
||||
VhalResult<bool> isCruiseControlTypeStandardResult;
|
||||
switch (propId) {
|
||||
case toInt(VehicleProperty::DISPLAY_BRIGHTNESS):
|
||||
case toInt(VehicleProperty::PER_DISPLAY_BRIGHTNESS):
|
||||
ALOGD("DISPLAY_BRIGHTNESS: %s", value.toString().c_str());
|
||||
return {};
|
||||
case toInt(VehicleProperty::AP_POWER_STATE_REPORT):
|
||||
*isSpecialValue = true;
|
||||
return setApPowerStateReport(value);
|
||||
|
||||
@@ -40,10 +40,10 @@ cc_test {
|
||||
"FakeUserHal",
|
||||
"libgtest",
|
||||
"libgmock",
|
||||
"libjsoncpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libgrpc++",
|
||||
"libjsoncpp",
|
||||
"libprotobuf-cpp-full",
|
||||
],
|
||||
data: [
|
||||
|
||||
@@ -83,6 +83,17 @@ std::vector<aidlvhal::VehiclePropConfig> GRPCVehicleHardware::getAllPropertyConf
|
||||
return configs;
|
||||
}
|
||||
|
||||
std::optional<aidlvhal::VehiclePropConfig> GRPCVehicleHardware::getPropertyConfig(
|
||||
int32_t propId) const {
|
||||
// TODO(b/354055835): Use GRPC call to get one config instead of getting all the configs.
|
||||
for (const auto& config : getAllPropertyConfigs()) {
|
||||
if (config.prop == propId) {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
aidlvhal::StatusCode GRPCVehicleHardware::setValues(
|
||||
std::shared_ptr<const SetValuesCallback> callback,
|
||||
const std::vector<aidlvhal::SetValueRequest>& requests) {
|
||||
@@ -265,6 +276,7 @@ DumpResult GRPCVehicleHardware::dump(const std::vector<std::string>& options) {
|
||||
return {
|
||||
.callerShouldDumpState = protoDumpResult.caller_should_dump_state(),
|
||||
.buffer = protoDumpResult.buffer(),
|
||||
.refreshPropertyConfigs = protoDumpResult.refresh_property_configs(),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,10 @@ class GRPCVehicleHardware : public IVehicleHardware {
|
||||
// Get all the property configs.
|
||||
std::vector<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const override;
|
||||
|
||||
// Get the config for the specified propId.
|
||||
std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
|
||||
getPropertyConfig(int32_t propId) const override;
|
||||
|
||||
// Set property values asynchronously. Server could return before the property set requests
|
||||
// are sent to vehicle bus or before property set confirmation is received. The callback is
|
||||
// safe to be called after the function returns and is safe to be called in a different thread.
|
||||
|
||||
@@ -226,6 +226,7 @@ GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::vector<std::string> serverAd
|
||||
auto dumpResult = mHardware->dump(dumpOptionStrings);
|
||||
result->set_caller_should_dump_state(dumpResult.callerShouldDumpState);
|
||||
result->set_buffer(dumpResult.buffer);
|
||||
result->set_refresh_property_configs(dumpResult.refreshPropertyConfigs);
|
||||
return ::grpc::Status::OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <VehicleHalTypes.h>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
@@ -46,33 +47,53 @@ struct SetValueErrorEvent {
|
||||
int32_t areaId;
|
||||
};
|
||||
|
||||
namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle;
|
||||
|
||||
// An abstract interface to access vehicle hardware.
|
||||
// For virtualized VHAL, GrpcVehicleHardware would communicate with a VehicleHardware
|
||||
// implementation in another VM through GRPC. For non-virtualzied VHAL, VHAL directly communicates
|
||||
// with a VehicleHardware through this interface.
|
||||
class IVehicleHardware {
|
||||
public:
|
||||
using SetValuesCallback = std::function<void(
|
||||
std::vector<aidl::android::hardware::automotive::vehicle::SetValueResult>)>;
|
||||
using GetValuesCallback = std::function<void(
|
||||
std::vector<aidl::android::hardware::automotive::vehicle::GetValueResult>)>;
|
||||
using PropertyChangeCallback = std::function<void(
|
||||
std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>)>;
|
||||
using SetValuesCallback = std::function<void(std::vector<aidlvhal::SetValueResult>)>;
|
||||
using GetValuesCallback = std::function<void(std::vector<aidlvhal::GetValueResult>)>;
|
||||
using PropertyChangeCallback = std::function<void(std::vector<aidlvhal::VehiclePropValue>)>;
|
||||
using PropertySetErrorCallback = std::function<void(std::vector<SetValueErrorEvent>)>;
|
||||
|
||||
virtual ~IVehicleHardware() = default;
|
||||
|
||||
// Get all the property configs.
|
||||
virtual std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
|
||||
getAllPropertyConfigs() const = 0;
|
||||
virtual std::vector<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const = 0;
|
||||
|
||||
// Get the property configs for the specified propId. This is used for early-boot
|
||||
// native VHAL clients to access certain property configs when not all property configs are
|
||||
// available. For example, a config discovery process might be required to determine the
|
||||
// property config for HVAC. However, for early boot properties, e.g. VHAL_HEARTBEAT, it
|
||||
// could return before the config discovery process.
|
||||
//
|
||||
// Currently Android system may try to access the following properties during early boot:
|
||||
// STORAGE_ENCRYPTION_BINDING_SEED, WATCHDOG_ALIVE, WATCHDOG_TERMINATE_PROCESS, VHAL_HEARTBEAT,
|
||||
// CURRENT_POWER_POLICY, POWER_POLICY_REQ, POWER_POLICY_GROUP_REQ. They should return
|
||||
// quickly otherwise the whole bootup process might be blocked.
|
||||
virtual std::optional<aidlvhal::VehiclePropConfig> getPropertyConfig(int32_t propId) const {
|
||||
// The default implementation is to use getAllPropertyConfigs(). This should be
|
||||
// overridden if getAllPropertyConfigs() takes a while to return for initial boot or
|
||||
// relies on ethernet or other communication channel that is not available during early
|
||||
// boot.
|
||||
for (const auto& config : getAllPropertyConfigs()) {
|
||||
if (config.prop == propId) {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Set property values asynchronously. Server could return before the property set requests
|
||||
// are sent to vehicle bus or before property set confirmation is received. The callback is
|
||||
// safe to be called after the function returns and is safe to be called in a different thread.
|
||||
virtual aidl::android::hardware::automotive::vehicle::StatusCode setValues(
|
||||
virtual aidlvhal::StatusCode setValues(
|
||||
std::shared_ptr<const SetValuesCallback> callback,
|
||||
const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
|
||||
requests) = 0;
|
||||
const std::vector<aidlvhal::SetValueRequest>& requests) = 0;
|
||||
|
||||
// Get property values asynchronously. Server could return before the property values are ready.
|
||||
// The callback is safe to be called after the function returns and is safe to be called in a
|
||||
@@ -86,7 +107,7 @@ class IVehicleHardware {
|
||||
virtual DumpResult dump(const std::vector<std::string>& options) = 0;
|
||||
|
||||
// Check whether the system is healthy, return {@code StatusCode::OK} for healthy.
|
||||
virtual aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() = 0;
|
||||
virtual aidlvhal::StatusCode checkHealth() = 0;
|
||||
|
||||
// Register a callback that would be called when there is a property change event from vehicle.
|
||||
// This function must only be called once during initialization.
|
||||
@@ -179,16 +200,14 @@ class IVehicleHardware {
|
||||
// 5. The second subscriber is removed, 'unsubscribe' is called.
|
||||
// The impl can optionally disable the polling for vehicle speed.
|
||||
//
|
||||
virtual aidl::android::hardware::automotive::vehicle::StatusCode subscribe(
|
||||
[[maybe_unused]] aidl::android::hardware::automotive::vehicle::SubscribeOptions
|
||||
options) {
|
||||
return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
|
||||
virtual aidlvhal::StatusCode subscribe([[maybe_unused]] aidlvhal::SubscribeOptions options) {
|
||||
return aidlvhal::StatusCode::OK;
|
||||
}
|
||||
|
||||
// A [propId, areaId] is unsubscribed. This applies for both continuous or on-change property.
|
||||
virtual aidl::android::hardware::automotive::vehicle::StatusCode unsubscribe(
|
||||
[[maybe_unused]] int32_t propId, [[maybe_unused]] int32_t areaId) {
|
||||
return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
|
||||
virtual aidlvhal::StatusCode unsubscribe([[maybe_unused]] int32_t propId,
|
||||
[[maybe_unused]] int32_t areaId) {
|
||||
return aidlvhal::StatusCode::OK;
|
||||
}
|
||||
|
||||
// This function is deprecated, subscribe/unsubscribe should be used instead.
|
||||
@@ -216,10 +235,10 @@ class IVehicleHardware {
|
||||
//
|
||||
// If the impl is always polling at {@code maxSampleRate} as specified in config, then this
|
||||
// function can be a no-op.
|
||||
virtual aidl::android::hardware::automotive::vehicle::StatusCode updateSampleRate(
|
||||
[[maybe_unused]] int32_t propId, [[maybe_unused]] int32_t areaId,
|
||||
[[maybe_unused]] float sampleRate) {
|
||||
return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
|
||||
virtual aidlvhal::StatusCode updateSampleRate([[maybe_unused]] int32_t propId,
|
||||
[[maybe_unused]] int32_t areaId,
|
||||
[[maybe_unused]] float sampleRate) {
|
||||
return aidlvhal::StatusCode::OK;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -106,3 +106,21 @@ cc_library_static {
|
||||
"-Wno-unused-parameter",
|
||||
],
|
||||
}
|
||||
|
||||
rust_protobuf {
|
||||
name: "libvehicle_hal_property_protos",
|
||||
crate_name: "vehicle_hal_property_protos",
|
||||
protos: [":VehicleHalProtoFiles"],
|
||||
source_stem: "vehicle_hal_property_protos",
|
||||
host_supported: true,
|
||||
vendor_available: true,
|
||||
product_available: true,
|
||||
apex_available: [
|
||||
"//apex_available:platform",
|
||||
"//apex_available:anyapex",
|
||||
],
|
||||
exported_include_dirs: ["."],
|
||||
proto_flags: [
|
||||
"-I external/protobuf/src",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -25,4 +25,6 @@ message DumpResult {
|
||||
bool caller_should_dump_state = 1;
|
||||
/* The dumped information for the caller to print. */
|
||||
string buffer = 2;
|
||||
/* To pass if DefaultVehicleHal should refresh the property configs. */
|
||||
bool refresh_property_configs = 3;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ cc_library {
|
||||
],
|
||||
header_libs: [
|
||||
"IVehicleHardware",
|
||||
"IVehicleGeneratedHeaders-V3",
|
||||
"IVehicleGeneratedHeaders-V4",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbinder_ndk",
|
||||
|
||||
@@ -199,6 +199,8 @@ class DefaultVehicleHal final : public aidlvhal::BnVehicle {
|
||||
|
||||
bool checkDumpPermission();
|
||||
|
||||
bool isConfigSupportedForCurrentVhalVersion(const aidlvhal::VehiclePropConfig& config) const;
|
||||
|
||||
bool getAllPropConfigsFromHardwareLocked() const EXCLUDES(mConfigLock);
|
||||
|
||||
// The looping handler function to process all onBinderDied or onBinderUnlinked events in
|
||||
|
||||
@@ -340,32 +340,37 @@ int32_t DefaultVehicleHal::getVhalInterfaceVersion() const {
|
||||
return myVersion;
|
||||
}
|
||||
|
||||
bool DefaultVehicleHal::isConfigSupportedForCurrentVhalVersion(
|
||||
const VehiclePropConfig& config) const {
|
||||
int32_t myVersion = getVhalInterfaceVersion();
|
||||
if (!isSystemProp(config.prop)) {
|
||||
return true;
|
||||
}
|
||||
VehicleProperty property = static_cast<VehicleProperty>(config.prop);
|
||||
std::string propertyName = aidl::android::hardware::automotive::vehicle::toString(property);
|
||||
auto it = VersionForVehicleProperty.find(property);
|
||||
if (it == VersionForVehicleProperty.end()) {
|
||||
ALOGE("The property: %s is not a supported system property, ignore", propertyName.c_str());
|
||||
return false;
|
||||
}
|
||||
int requiredVersion = it->second;
|
||||
if (myVersion < requiredVersion) {
|
||||
ALOGE("The property: %s is not supported for current client VHAL version, "
|
||||
"require %d, current version: %d, ignore",
|
||||
propertyName.c_str(), requiredVersion, myVersion);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DefaultVehicleHal::getAllPropConfigsFromHardwareLocked() const {
|
||||
ALOGD("Get all property configs from hardware");
|
||||
auto configs = mVehicleHardware->getAllPropertyConfigs();
|
||||
std::vector<VehiclePropConfig> filteredConfigs;
|
||||
int32_t myVersion = getVhalInterfaceVersion();
|
||||
for (auto& config : configs) {
|
||||
if (!isSystemProp(config.prop)) {
|
||||
for (const auto& config : configs) {
|
||||
if (isConfigSupportedForCurrentVhalVersion(config)) {
|
||||
filteredConfigs.push_back(std::move(config));
|
||||
continue;
|
||||
}
|
||||
VehicleProperty property = static_cast<VehicleProperty>(config.prop);
|
||||
std::string propertyName = aidl::android::hardware::automotive::vehicle::toString(property);
|
||||
auto it = VersionForVehicleProperty.find(property);
|
||||
if (it == VersionForVehicleProperty.end()) {
|
||||
ALOGE("The property: %s is not a supported system property, ignore",
|
||||
propertyName.c_str());
|
||||
continue;
|
||||
}
|
||||
int requiredVersion = it->second;
|
||||
if (myVersion < requiredVersion) {
|
||||
ALOGE("The property: %s is not supported for current client VHAL version, "
|
||||
"require %d, current version: %d, ignore",
|
||||
propertyName.c_str(), requiredVersion, myVersion);
|
||||
continue;
|
||||
}
|
||||
filteredConfigs.push_back(std::move(config));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -431,6 +436,19 @@ ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
|
||||
|
||||
Result<VehiclePropConfig> DefaultVehicleHal::getConfig(int32_t propId) const {
|
||||
Result<VehiclePropConfig> result;
|
||||
|
||||
if (!mConfigInit) {
|
||||
std::optional<VehiclePropConfig> config = mVehicleHardware->getPropertyConfig(propId);
|
||||
if (!config.has_value()) {
|
||||
return Error() << "no config for property, ID: " << propId;
|
||||
}
|
||||
if (!isConfigSupportedForCurrentVhalVersion(config.value())) {
|
||||
return Error() << "property not supported for current VHAL interface, ID: " << propId;
|
||||
}
|
||||
|
||||
return config.value();
|
||||
}
|
||||
|
||||
getConfigsByPropId([this, &result, propId](const auto& configsByPropId) {
|
||||
SharedScopedLockAssertion lockAssertion(mConfigLock);
|
||||
|
||||
@@ -685,6 +703,22 @@ ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback,
|
||||
ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
|
||||
VehiclePropConfigs* output) {
|
||||
std::vector<VehiclePropConfig> configs;
|
||||
|
||||
if (!mConfigInit) {
|
||||
for (int32_t prop : props) {
|
||||
auto maybeConfig = mVehicleHardware->getPropertyConfig(prop);
|
||||
if (!maybeConfig.has_value() ||
|
||||
!isConfigSupportedForCurrentVhalVersion(maybeConfig.value())) {
|
||||
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
|
||||
toInt(StatusCode::INVALID_ARG),
|
||||
StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
|
||||
}
|
||||
configs.push_back(maybeConfig.value());
|
||||
}
|
||||
|
||||
return vectorToStableLargeParcelable(std::move(configs), output);
|
||||
}
|
||||
|
||||
ScopedAStatus status = ScopedAStatus::ok();
|
||||
getConfigsByPropId([this, &configs, &status, &props](const auto& configsByPropId) {
|
||||
SharedScopedLockAssertion lockAssertion(mConfigLock);
|
||||
|
||||
@@ -650,6 +650,8 @@ TEST_F(DefaultVehicleHalTest, testGetPropConfigs) {
|
||||
|
||||
auto hardware = std::make_unique<MockVehicleHardware>();
|
||||
hardware->setPropertyConfigs(testConfigs);
|
||||
// Store the pointer for testing. We are sure it is valid.
|
||||
MockVehicleHardware* hardwarePtr = hardware.get();
|
||||
auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
|
||||
std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
|
||||
|
||||
@@ -658,6 +660,7 @@ TEST_F(DefaultVehicleHalTest, testGetPropConfigs) {
|
||||
|
||||
ASSERT_TRUE(status.isOk()) << "getPropConfigs failed: " << status.getMessage();
|
||||
ASSERT_EQ(output.payloads, testConfigs);
|
||||
ASSERT_FALSE(hardwarePtr->getAllPropertyConfigsCalled());
|
||||
}
|
||||
|
||||
TEST_F(DefaultVehicleHalTest, testGetPropConfigsInvalidArg) {
|
||||
@@ -704,6 +707,34 @@ TEST_F(DefaultVehicleHalTest, testGetValuesSmall) {
|
||||
ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
|
||||
EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch";
|
||||
EXPECT_EQ(countClients(), static_cast<size_t>(1));
|
||||
ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled());
|
||||
}
|
||||
|
||||
TEST_F(DefaultVehicleHalTest, testGetValuesSmall_AfterGetAllPropConfigs) {
|
||||
GetValueRequests requests;
|
||||
std::vector<GetValueResult> expectedResults;
|
||||
std::vector<GetValueRequest> expectedHardwareRequests;
|
||||
|
||||
// If we already called getAllPropConfigs, the configs will be cached.
|
||||
VehiclePropConfigs output;
|
||||
getClient()->getAllPropConfigs(&output);
|
||||
|
||||
ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
|
||||
|
||||
getHardware()->addGetValueResponses(expectedResults);
|
||||
|
||||
auto status = getClient()->getValues(getCallbackClient(), requests);
|
||||
|
||||
ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
|
||||
|
||||
EXPECT_EQ(getHardware()->nextGetValueRequests(), expectedHardwareRequests)
|
||||
<< "requests to hardware mismatch";
|
||||
|
||||
auto maybeGetValueResults = getCallback()->nextGetValueResults();
|
||||
ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
|
||||
EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch";
|
||||
EXPECT_EQ(countClients(), static_cast<size_t>(1));
|
||||
ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled());
|
||||
}
|
||||
|
||||
TEST_F(DefaultVehicleHalTest, testGetValuesLarge) {
|
||||
@@ -1016,6 +1047,34 @@ TEST_F(DefaultVehicleHalTest, testSetValuesSmall) {
|
||||
ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
|
||||
ASSERT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch";
|
||||
EXPECT_EQ(countClients(), static_cast<size_t>(1));
|
||||
ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled());
|
||||
}
|
||||
|
||||
TEST_F(DefaultVehicleHalTest, testSetValuesSmall_AfterGetAllPropConfigs) {
|
||||
SetValueRequests requests;
|
||||
std::vector<SetValueResult> expectedResults;
|
||||
std::vector<SetValueRequest> expectedHardwareRequests;
|
||||
|
||||
// If we already called getAllPropConfigs, the configs will be cached.
|
||||
VehiclePropConfigs output;
|
||||
getClient()->getAllPropConfigs(&output);
|
||||
|
||||
ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
|
||||
|
||||
getHardware()->addSetValueResponses(expectedResults);
|
||||
|
||||
auto status = getClient()->setValues(getCallbackClient(), requests);
|
||||
|
||||
ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
|
||||
|
||||
EXPECT_EQ(getHardware()->nextSetValueRequests(), expectedHardwareRequests)
|
||||
<< "requests to hardware mismatch";
|
||||
|
||||
auto maybeSetValueResults = getCallback()->nextSetValueResults();
|
||||
ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
|
||||
ASSERT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch";
|
||||
EXPECT_EQ(countClients(), static_cast<size_t>(1));
|
||||
ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled());
|
||||
}
|
||||
|
||||
TEST_F(DefaultVehicleHalTest, testSetValuesLarge) {
|
||||
|
||||
@@ -45,9 +45,20 @@ MockVehicleHardware::~MockVehicleHardware() {
|
||||
|
||||
std::vector<VehiclePropConfig> MockVehicleHardware::getAllPropertyConfigs() const {
|
||||
std::scoped_lock<std::mutex> lockGuard(mLock);
|
||||
mGetAllPropertyConfigsCalled = true;
|
||||
return mPropertyConfigs;
|
||||
}
|
||||
|
||||
std::optional<VehiclePropConfig> MockVehicleHardware::getPropertyConfig(int32_t propId) const {
|
||||
std::scoped_lock<std::mutex> lockGuard(mLock);
|
||||
for (const auto& config : mPropertyConfigs) {
|
||||
if (config.prop == propId) {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
StatusCode MockVehicleHardware::setValues(std::shared_ptr<const SetValuesCallback> callback,
|
||||
const std::vector<SetValueRequest>& requests) {
|
||||
std::scoped_lock<std::mutex> lockGuard(mLock);
|
||||
@@ -336,6 +347,11 @@ void MockVehicleHardware::sendOnPropertySetErrorEvent(
|
||||
(*mPropertySetErrorCallback)(errorEvents);
|
||||
}
|
||||
|
||||
bool MockVehicleHardware::getAllPropertyConfigsCalled() {
|
||||
std::scoped_lock<std::mutex> lockGuard(mLock);
|
||||
return mGetAllPropertyConfigsCalled;
|
||||
}
|
||||
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
|
||||
@@ -47,6 +47,8 @@ class MockVehicleHardware final : public IVehicleHardware {
|
||||
|
||||
std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
|
||||
getAllPropertyConfigs() const override;
|
||||
std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
|
||||
getPropertyConfig(int32_t propId) const override;
|
||||
aidl::android::hardware::automotive::vehicle::StatusCode setValues(
|
||||
std::shared_ptr<const SetValuesCallback> callback,
|
||||
const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
|
||||
@@ -98,6 +100,9 @@ class MockVehicleHardware final : public IVehicleHardware {
|
||||
std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>
|
||||
getSubscribeOptions();
|
||||
void clearSubscribeOptions();
|
||||
// Whether getAllPropertyConfigs() has been called, which blocks all all property configs
|
||||
// being ready.
|
||||
bool getAllPropertyConfigsCalled();
|
||||
|
||||
private:
|
||||
mutable std::mutex mLock;
|
||||
@@ -143,6 +148,8 @@ class MockVehicleHardware final : public IVehicleHardware {
|
||||
|
||||
DumpResult mDumpResult;
|
||||
|
||||
mutable bool mGetAllPropertyConfigsCalled GUARDED_BY(mLock) = false;
|
||||
|
||||
// RecurrentTimer is thread-safe.
|
||||
std::shared_ptr<RecurrentTimer> mRecurrentTimer;
|
||||
std::unordered_map<int32_t, std::unordered_map<int32_t, std::shared_ptr<std::function<void()>>>>
|
||||
|
||||
@@ -79,17 +79,18 @@ public final class EmuMetadataGenerator {
|
||||
+ "either this or input_files must be specified\n" + INPUT_FILES_OPTION
|
||||
+ ": one or more Java files, this is used to decide the input "
|
||||
+ "directory\n" + PACKAGE_NAME_OPTION
|
||||
+ ": the optional package name for the interface, by default is " + DEFAULT_PACKAGE_NAME
|
||||
+ "\n" + OUTPUT_JSON_OPTION + ": The output JSON file\n" + OUTPUT_EMPTY_FILE_OPTION
|
||||
+ ": Only used for check_mode, this file will be created if "
|
||||
+ ": the optional package name for the interface, by default is "
|
||||
+ DEFAULT_PACKAGE_NAME + "\n" + OUTPUT_JSON_OPTION + ": The output JSON file\n"
|
||||
+ OUTPUT_EMPTY_FILE_OPTION + ": Only used for check_mode, this file will be created if "
|
||||
+ "check passed\n" + CHECK_AGAINST_OPTION
|
||||
+ ": An optional JSON file to check against. If specified, the "
|
||||
+ "generated output file will be checked against this file, if they are not the same, "
|
||||
+ ("generated output file will be checked against this file, if they are not the "
|
||||
+ "same, ")
|
||||
+ "the script will fail, otherwise, the output_empty_file will be created\n"
|
||||
+ "For example: \n"
|
||||
+ "EnumMetadataGenerator --input_dir out/soong/.intermediates/hardware/"
|
||||
+ "interfaces/automotive/vehicle/aidl_property/android.hardware.automotive.vehicle."
|
||||
+ "property-V3-java-source/gen/ --package_name android.hardware.automotive.vehicle "
|
||||
+ "property-V4-java-source/gen/ --package_name android.hardware.automotive.vehicle "
|
||||
+ "--output_json /tmp/android.hardware.automotive.vehicle-types-meta.json";
|
||||
private static final String VEHICLE_PROPERTY_FILE = "VehicleProperty.java";
|
||||
private static final String CHECK_FILE_PATH =
|
||||
|
||||
@@ -17,4 +17,4 @@
|
||||
|
||||
LOCAL_STATIC_LIBRARIES += \
|
||||
android.hardware.automotive.vehicle-V3-ndk \
|
||||
android.hardware.automotive.vehicle.property-V3-ndk
|
||||
android.hardware.automotive.vehicle.property-V4-ndk
|
||||
|
||||
@@ -44,7 +44,7 @@ cc_test {
|
||||
"vhalclient_defaults",
|
||||
],
|
||||
header_libs: [
|
||||
"IVehicleGeneratedHeaders-V3",
|
||||
"IVehicleGeneratedHeaders-V4",
|
||||
],
|
||||
test_suites: [
|
||||
"general-tests",
|
||||
|
||||
@@ -22,6 +22,12 @@ aidl_interface {
|
||||
cpp: {
|
||||
enabled: false,
|
||||
},
|
||||
ndk: {
|
||||
apex_available: [
|
||||
"//apex_available:anyapex",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
},
|
||||
rust: {
|
||||
enabled: true,
|
||||
},
|
||||
|
||||
@@ -22,7 +22,7 @@ cc_library {
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
name: "android.hardware.biometrics.common.config",
|
||||
export_include_dirs: ["include"],
|
||||
vendor: true,
|
||||
vendor_available: true,
|
||||
srcs: [
|
||||
"Config.cpp",
|
||||
],
|
||||
@@ -30,6 +30,10 @@ cc_library {
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
],
|
||||
apex_available: [
|
||||
"//apex_available:anyapex",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
}
|
||||
|
||||
cc_test_host {
|
||||
|
||||
@@ -100,7 +100,11 @@ class Config {
|
||||
} else if (std::holds_alternative<OptIntVec>(v)) {
|
||||
for (auto x : std::get<OptIntVec>(v))
|
||||
if (x.has_value()) os << x.value() << " ";
|
||||
} else if (std::holds_alternative<OptString>(v)) {
|
||||
OptString ov = std::get<OptString>(v);
|
||||
if (ov.has_value()) os << ov.value();
|
||||
}
|
||||
|
||||
return os.str();
|
||||
}
|
||||
std::string toString() const {
|
||||
|
||||
@@ -10,10 +10,14 @@ cc_library {
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
name: "android.hardware.biometrics.common.thread",
|
||||
export_include_dirs: ["include"],
|
||||
vendor: true,
|
||||
vendor_available: true,
|
||||
srcs: [
|
||||
"WorkerThread.cpp",
|
||||
],
|
||||
apex_available: [
|
||||
"//apex_available:anyapex",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
}
|
||||
|
||||
cc_test_host {
|
||||
|
||||
@@ -6,7 +6,7 @@ cc_library {
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
name: "android.hardware.biometrics.common.util",
|
||||
export_include_dirs: ["include"],
|
||||
vendor: true,
|
||||
vendor_available: true,
|
||||
srcs: [
|
||||
"CancellationSignal.cpp",
|
||||
],
|
||||
@@ -15,4 +15,8 @@ cc_library {
|
||||
"libbinder_ndk",
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
],
|
||||
apex_available: [
|
||||
"//apex_available:anyapex",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ aidl_interface {
|
||||
name: "android.hardware.biometrics.face",
|
||||
vendor_available: true,
|
||||
srcs: [
|
||||
"android/hardware/biometrics/face/**/*.aidl",
|
||||
"android/hardware/biometrics/face/*.aidl",
|
||||
],
|
||||
imports: [
|
||||
"android.hardware.biometrics.common-V4",
|
||||
@@ -36,6 +36,10 @@ aidl_interface {
|
||||
additional_shared_libraries: [
|
||||
"libnativewindow",
|
||||
],
|
||||
apex_available: [
|
||||
"//apex_available:platform",
|
||||
"com.android.hardware.biometrics.face.virtual",
|
||||
],
|
||||
},
|
||||
},
|
||||
versions_with_info: [
|
||||
@@ -74,5 +78,39 @@ aidl_interface {
|
||||
|
||||
],
|
||||
frozen: true,
|
||||
|
||||
}
|
||||
|
||||
aidl_interface {
|
||||
name: "android.hardware.biometrics.face.virtualhal",
|
||||
srcs: [
|
||||
"android/hardware/biometrics/face/virtualhal/*.aidl",
|
||||
],
|
||||
imports: [
|
||||
"android.hardware.biometrics.common-V4",
|
||||
"android.hardware.keymaster-V4",
|
||||
"android.hardware.biometrics.face-V4",
|
||||
],
|
||||
vendor_available: true,
|
||||
unstable: true,
|
||||
backend: {
|
||||
java: {
|
||||
platform_apis: true,
|
||||
},
|
||||
rust: {
|
||||
enabled: false,
|
||||
},
|
||||
cpp: {
|
||||
enabled: false,
|
||||
},
|
||||
ndk: {
|
||||
additional_shared_libraries: [
|
||||
"libnativewindow",
|
||||
],
|
||||
apex_available: [
|
||||
"com.android.hardware.biometrics.face.virtual",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
},
|
||||
},
|
||||
frozen: false,
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ interface ISession {
|
||||
* Note that this interface allows multiple in-flight challenges. Invoking generateChallenge
|
||||
* twice does not invalidate the first challenge. The challenge is invalidated only when:
|
||||
* 1) Its lifespan exceeds the challenge timeout defined in the TEE.
|
||||
* 2) IFingerprint#revokeChallenge is invoked
|
||||
* 2) IFace#revokeChallenge is invoked
|
||||
*
|
||||
* For example, the following is a possible table of valid challenges:
|
||||
* ----------------------------------------------
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
package android.hardware.biometrics.face.virtualhal;
|
||||
|
||||
import android.hardware.biometrics.face.AcquiredInfo;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
union AcquiredInfoAndVendorCode {
|
||||
/**
|
||||
* Acquired info as specified in AcqauiredInfo.aidl
|
||||
*/
|
||||
AcquiredInfo acquiredInfo = AcquiredInfo.UNKNOWN;
|
||||
|
||||
/**
|
||||
* Vendor specific code
|
||||
*/
|
||||
int vendorCode;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
package android.hardware.biometrics.face.virtualhal;
|
||||
|
||||
import android.hardware.biometrics.face.virtualhal.AcquiredInfoAndVendorCode;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
parcelable EnrollmentProgressStep {
|
||||
/**
|
||||
* The duration of the enrollment step in milli-seconds
|
||||
*/
|
||||
int durationMs;
|
||||
|
||||
/**
|
||||
* The sequence of acquired info and vendor code to be issued by HAL during the step.
|
||||
* The codes are evenly spread over the duration
|
||||
*/
|
||||
AcquiredInfoAndVendorCode[] acquiredInfoAndVendorCodes;
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
package android.hardware.biometrics.face.virtualhal;
|
||||
|
||||
import android.hardware.biometrics.common.SensorStrength;
|
||||
import android.hardware.biometrics.face.FaceSensorType;
|
||||
import android.hardware.biometrics.face.IFace;
|
||||
import android.hardware.biometrics.face.virtualhal.AcquiredInfoAndVendorCode;
|
||||
import android.hardware.biometrics.face.virtualhal.NextEnrollment;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
interface IVirtualHal {
|
||||
/**
|
||||
* The operation failed due to invalid input parameters, the error messages should
|
||||
* gives more details
|
||||
*/
|
||||
const int STATUS_INVALID_PARAMETER = 1;
|
||||
|
||||
/**
|
||||
* Set Face Virtual HAL behavior parameters
|
||||
*/
|
||||
|
||||
/**
|
||||
* setEnrollments
|
||||
*
|
||||
* Set the ids of the faces that were currently enrolled in the Virtual HAL,
|
||||
*
|
||||
* @param ids ids can contain 1 or more ids, each must be larger than 0
|
||||
*/
|
||||
void setEnrollments(in int[] id);
|
||||
|
||||
/**
|
||||
* setEnrollmentHit
|
||||
*
|
||||
* Set current face enrollment ids in Face Virtual HAL,
|
||||
*
|
||||
* @param ids ids can contain 1 or more ids, each must be larger than 0
|
||||
*/
|
||||
void setEnrollmentHit(in int hit_id);
|
||||
|
||||
/**
|
||||
* setNextEnrollment
|
||||
*
|
||||
* Set the next enrollment behavior
|
||||
*
|
||||
* @param next_enrollment specifies enrollment id, progress stages and final result
|
||||
*/
|
||||
void setNextEnrollment(in NextEnrollment next_enrollment);
|
||||
|
||||
/**
|
||||
* setAuthenticatorId
|
||||
*
|
||||
* Set authenticator id in virtual HAL, the id is returned in ISession#AuthenticatorId() call
|
||||
*
|
||||
* @param id authenticator id value, only applied to the sensor with SensorStrength::STRONG.
|
||||
*/
|
||||
void setAuthenticatorId(in long id);
|
||||
|
||||
/**
|
||||
* setChallenge
|
||||
*
|
||||
* Set the challenge generated by the virtual HAL, which is returned in
|
||||
* ISessionCallback#onChallengeGenerated()
|
||||
*
|
||||
* @param challenge
|
||||
*/
|
||||
void setChallenge(in long challenge);
|
||||
|
||||
/**
|
||||
* setOperationAuthenticateFails
|
||||
*
|
||||
* Set whether to force authentication to fail. If true, the virtual hal will report failure on
|
||||
* authentication attempt until it is set to false
|
||||
*
|
||||
* @param fail if true, then the next authentication will fail
|
||||
*/
|
||||
void setOperationAuthenticateFails(in boolean fail);
|
||||
|
||||
/**
|
||||
* setOperationAuthenticateLatency
|
||||
*
|
||||
* Set authentication latency in the virtual hal in a fixed value (single element) or random
|
||||
* values (two elements representing the bound values)
|
||||
* The latency simulates the delay from the time framework requesting HAL to authetication to
|
||||
* the time when HAL is ready to perform authentication operations.
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in array falls in any of
|
||||
* the following conditions
|
||||
* 1. the array contains no element
|
||||
* 2. the array contains more than two elements
|
||||
* 3. the array contains any negative value
|
||||
* The accompanying error message gives more detail
|
||||
*
|
||||
* @param latencyMs[] value(s) are in milli-seconds
|
||||
*/
|
||||
void setOperationAuthenticateLatency(in int[] latencyMs);
|
||||
|
||||
/**
|
||||
* setOperationAuthenticateDuration
|
||||
*
|
||||
* Set authentication duration covering the HAL authetication from start to end, including
|
||||
* face capturing, and matching, acquired info reporting. In case a sequence of acquired
|
||||
* info code are specified via setOperationAuthenticateAcquired(), the reporting is evenly
|
||||
* distributed over the duration.
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
|
||||
*
|
||||
* @param duration value is in milli-seconds
|
||||
*/
|
||||
void setOperationAuthenticateDuration(in int durationMs);
|
||||
|
||||
/**
|
||||
* setOperationAuthenticateError
|
||||
*
|
||||
* Force authentication to error out for non-zero error
|
||||
* Check
|
||||
* hardware/interfaces/biometrics/face/aidl/default/aidl/android/hardware/biometrics/face/Error.aidl
|
||||
* for valid error codes
|
||||
*
|
||||
* @param error if error < 1000
|
||||
* non-vendor error
|
||||
* else
|
||||
* vendor error
|
||||
*/
|
||||
void setOperationAuthenticateError(in int error);
|
||||
|
||||
/**
|
||||
* setOperationAuthenticateAcquired
|
||||
*
|
||||
* Set one of more acquired info codes for the virtual hal to report during authentication
|
||||
* Check
|
||||
* hardware/interfaces/biometrics/face/aidl/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
|
||||
* for valid acquired info codes
|
||||
*
|
||||
* @param acquired[], one or more acquired info codes
|
||||
*/
|
||||
void setOperationAuthenticateAcquired(in AcquiredInfoAndVendorCode[] acquired);
|
||||
|
||||
/**
|
||||
* setOperationEnrollLatency
|
||||
*
|
||||
* Set enrollment latency in the virtual hal in a fixed value (single element) or random
|
||||
* values (two elements representing the bound values)
|
||||
* The latency simulates the delay from the time framework requesting HAL to enroll to the
|
||||
* time when HAL is ready to perform enrollment operations.
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in array falls in any of
|
||||
* the following conditions
|
||||
* 1. the array contains no element
|
||||
* 2. the array contains more than two elements
|
||||
* 3. the array contains any negative value
|
||||
* The accompanying error message gives more detail
|
||||
*
|
||||
* @param latencyMs[] value(s) are in milli-seconds
|
||||
*/
|
||||
void setOperationEnrollLatency(in int[] latencyMs);
|
||||
|
||||
/**
|
||||
* setOperationDetectInteractionLatency
|
||||
*
|
||||
* Set detect interaction latency in the virtual hal in a fixed value (single element) or random
|
||||
* values (two elements representing the bound values)
|
||||
* The latency simulates the delay from the time framework requesting HAL to detect interaction
|
||||
* to the time when HAL is ready to perform detect interaction operations.
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in array falls in any of
|
||||
* the following conditions
|
||||
* 1. the array contains no element
|
||||
* 2. the array contains more than two elements
|
||||
* 3. the array contains any negative value
|
||||
* The accompanying error message gives more detail
|
||||
*
|
||||
* @param latencyMs[] value(s) are in milli-seconds
|
||||
*/
|
||||
void setOperationDetectInteractionLatency(in int[] latencyMs);
|
||||
|
||||
/**
|
||||
* setOperationDetectInteractionFails
|
||||
*
|
||||
* Force detect interaction operation to fail
|
||||
*/
|
||||
void setOperationDetectInteractionFails(in boolean error);
|
||||
|
||||
/**
|
||||
* setLockout
|
||||
*
|
||||
* Whether to force to lockout on authentcation operation. If true, the virtual hal will report
|
||||
* permanent lockout in processing authentication requrest, regardless of whether
|
||||
* setLockoutEnable(true) is called or not.
|
||||
*
|
||||
* @param lockout, set to true if lockout is desired
|
||||
*/
|
||||
void setLockout(in boolean lockout);
|
||||
|
||||
/**
|
||||
* setLockoutEnable
|
||||
*
|
||||
* Whether to enable authentication-fail-based lockout tracking or not. The lock tracking
|
||||
* includes both timed-based (aka temporary) lockout and permanent lockout.
|
||||
*
|
||||
* @param enable, set true to enable the lockout tracking
|
||||
*/
|
||||
void setLockoutEnable(in boolean enable);
|
||||
|
||||
/**
|
||||
* setLockoutTimedEnable
|
||||
*
|
||||
* Whether to enable authentication-fail-based time-based-lockout tracking or not.
|
||||
*
|
||||
* @param enable, set true to enable the time-basedlockout tracking
|
||||
*/
|
||||
void setLockoutTimedEnable(in boolean enable);
|
||||
|
||||
/**
|
||||
* setLockoutTimedThreshold
|
||||
*
|
||||
* Set the number of consecutive authentication failures that triggers the timed-based lock to
|
||||
* occur
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
|
||||
*
|
||||
* @param threshold, the number of consecutive failures
|
||||
*/
|
||||
void setLockoutTimedThreshold(in int threshold);
|
||||
|
||||
/**
|
||||
* setLockoutTimedDuration
|
||||
*
|
||||
* Set the duration to expire timed-based lock during which there is no authentication failure
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
|
||||
*
|
||||
* @param duration, in milli-seconds
|
||||
*/
|
||||
void setLockoutTimedDuration(in int durationMs);
|
||||
|
||||
/**
|
||||
* setLockoutPermanentThreshold
|
||||
*
|
||||
* Set the number of consecutive authentication failures that triggers the permanent lock to
|
||||
* occur
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
|
||||
*
|
||||
* @param threshold, the number of consecutive failures
|
||||
*/
|
||||
void setLockoutPermanentThreshold(in int threshold);
|
||||
|
||||
/**
|
||||
* resetConfigurations
|
||||
*
|
||||
* Reset all virtual hal configurations to default values
|
||||
*/
|
||||
void resetConfigurations();
|
||||
|
||||
/**
|
||||
* setType
|
||||
*
|
||||
* Configure virtual face sensor type
|
||||
*
|
||||
* @param type, sensor type as specified in FaceSensorType.aidl
|
||||
*
|
||||
*/
|
||||
void setType(in FaceSensorType type);
|
||||
|
||||
/**
|
||||
* setSensorStrength
|
||||
*
|
||||
* Configure virtual face sensor strength
|
||||
*
|
||||
* @param sensor strength as specified in common/SensorStrength.aidl
|
||||
*/
|
||||
void setSensorStrength(in SensorStrength strength);
|
||||
|
||||
/**
|
||||
* getFaceHal
|
||||
*
|
||||
* @return IFace interface associated with IVirtualHal instance
|
||||
*/
|
||||
IFace getFaceHal();
|
||||
}
|
||||
@@ -14,12 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.hardware.biometrics.fingerprint;
|
||||
package android.hardware.biometrics.face.virtualhal;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@VintfStability
|
||||
parcelable NextEnrollment {
|
||||
/**
|
||||
* Identifier of the next enrollment if successful
|
||||
@@ -31,7 +30,7 @@ parcelable NextEnrollment {
|
||||
* and sequence of acquired info codes to be generated by HAL.
|
||||
* See EnrollmentProgressStep.aidl for more details
|
||||
*/
|
||||
android.hardware.biometrics.fingerprint.EnrollmentProgressStep[] progressSteps;
|
||||
android.hardware.biometrics.face.virtualhal.EnrollmentProgressStep[] progressSteps;
|
||||
|
||||
/**
|
||||
* Success or failure of the next enrollment
|
||||
@@ -0,0 +1,3 @@
|
||||
The aidl files in this directory are used to control/configure face virtual hal
|
||||
via IVirtualHal interface
|
||||
|
||||
@@ -9,21 +9,13 @@ package {
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "face-example.rc",
|
||||
srcs: ["face-example.rc"],
|
||||
name: "face-virtual.rc",
|
||||
srcs: ["face-virtual.rc"],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "face-example.xml",
|
||||
srcs: ["face-example.xml"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.biometrics.face-service.example",
|
||||
relative_install_path: "hw",
|
||||
init_rc: [":face-example.rc"],
|
||||
vintf_fragments: [":face-example.xml"],
|
||||
vendor: true,
|
||||
cc_library_static {
|
||||
name: "android.hardware.biometrics.face-service.lib",
|
||||
vendor_available: true,
|
||||
|
||||
shared_libs: [
|
||||
"libbinder_ndk",
|
||||
@@ -32,32 +24,80 @@ cc_binary {
|
||||
],
|
||||
srcs: [
|
||||
"FakeLockoutTracker.cpp",
|
||||
"main.cpp",
|
||||
"Face.cpp",
|
||||
"FakeFaceEngine.cpp",
|
||||
"Session.cpp",
|
||||
"FaceConfig.cpp",
|
||||
"VirtualHal.cpp",
|
||||
"main.cpp",
|
||||
],
|
||||
include_dirs: [
|
||||
"frameworks/native/aidl/gui",
|
||||
],
|
||||
stl: "c++_static",
|
||||
static_libs: [
|
||||
whole_static_libs: [
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.biometrics.common.config",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
"android.hardware.biometrics.common.util",
|
||||
"android.hardware.biometrics.face.virtualhal-ndk",
|
||||
"android.hardware.biometrics.face-V4-ndk",
|
||||
"android.hardware.common-V2-ndk",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
"libandroid.hardware.biometrics.face.VirtualProps",
|
||||
"libbase",
|
||||
],
|
||||
apex_available: [
|
||||
"com.android.hardware.biometrics.face.virtual",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.biometrics.face-service.example",
|
||||
system_ext_specific: true,
|
||||
relative_install_path: "hw",
|
||||
|
||||
shared_libs: [
|
||||
"libbinder_ndk",
|
||||
"liblog",
|
||||
"libnativewindow",
|
||||
],
|
||||
whole_static_libs: [
|
||||
"android.hardware.biometrics.face-service.lib",
|
||||
],
|
||||
installable: false, // install APEX instead
|
||||
apex_available: [
|
||||
"com.android.hardware.biometrics.face.virtual",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.biometrics.face-service.default",
|
||||
vendor: true,
|
||||
relative_install_path: "hw",
|
||||
init_rc: ["face-default.rc"],
|
||||
vintf_fragments: ["face-default.xml"],
|
||||
shared_libs: [
|
||||
"libbinder_ndk",
|
||||
"liblog",
|
||||
"libnativewindow",
|
||||
],
|
||||
whole_static_libs: [
|
||||
"android.hardware.biometrics.face-service.lib",
|
||||
],
|
||||
}
|
||||
|
||||
sysprop_library {
|
||||
name: "android.hardware.biometrics.face.VirtualProps",
|
||||
srcs: ["face.sysprop"],
|
||||
property_owner: "Vendor",
|
||||
vendor: true,
|
||||
property_owner: "Platform",
|
||||
vendor_available: true,
|
||||
apex_available: [
|
||||
"//apex_available:platform",
|
||||
"com.android.hardware.biometrics.face.virtual",
|
||||
],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
@@ -66,6 +106,7 @@ cc_test {
|
||||
"tests/FakeFaceEngineTest.cpp",
|
||||
"FakeFaceEngine.cpp",
|
||||
"FakeLockoutTracker.cpp",
|
||||
"FaceConfig.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
@@ -81,6 +122,8 @@ cc_test {
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
"android.hardware.biometrics.common.util",
|
||||
"android.hardware.biometrics.common.config",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
],
|
||||
vendor: true,
|
||||
test_suites: ["general-tests"],
|
||||
@@ -92,6 +135,7 @@ cc_test {
|
||||
srcs: [
|
||||
"tests/FakeLockoutTrackerTest.cpp",
|
||||
"FakeLockoutTracker.cpp",
|
||||
"FaceConfig.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
@@ -107,8 +151,45 @@ cc_test {
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
"android.hardware.biometrics.common.util",
|
||||
"android.hardware.biometrics.common.config",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
],
|
||||
vendor: true,
|
||||
test_suites: ["general-tests"],
|
||||
require_root: true,
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "android.hardware.biometrics.face.VirtualHalTest",
|
||||
srcs: [
|
||||
"tests/VirtualHalTest.cpp",
|
||||
"FakeLockoutTracker.cpp",
|
||||
"Face.cpp",
|
||||
"FakeFaceEngine.cpp",
|
||||
"Session.cpp",
|
||||
"VirtualHal.cpp",
|
||||
"FaceConfig.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"libnativewindow",
|
||||
"liblog",
|
||||
],
|
||||
include_dirs: [
|
||||
"frameworks/native/aidl/gui",
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.biometrics.common.config",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
"android.hardware.biometrics.common.util",
|
||||
"android.hardware.biometrics.face-V4-ndk",
|
||||
"android.hardware.common-V2-ndk",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
"libandroid.hardware.biometrics.face.VirtualProps",
|
||||
"android.hardware.biometrics.face.virtualhal-ndk",
|
||||
],
|
||||
test_suites: ["general-tests"],
|
||||
require_root: true,
|
||||
}
|
||||
|
||||
@@ -34,9 +34,7 @@ using namespace ::android::face::virt;
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
|
||||
const int kSensorId = 4;
|
||||
const common::SensorStrength kSensorStrength = FakeFaceEngine::GetSensorStrength();
|
||||
const int kMaxEnrollmentsPerUser = 5;
|
||||
const FaceSensorType kSensorType = FakeFaceEngine::GetSensorType();
|
||||
const bool kHalControlsPreview = true;
|
||||
const std::string kHwComponentId = "faceSensor";
|
||||
const std::string kHardwareVersion = "vendor/model/revision";
|
||||
@@ -62,13 +60,13 @@ ndk::ScopedAStatus Face::getSensorProps(std::vector<SensorProps>* return_val) {
|
||||
|
||||
common::CommonProps commonProps;
|
||||
commonProps.sensorId = kSensorId;
|
||||
commonProps.sensorStrength = kSensorStrength;
|
||||
commonProps.sensorStrength = FakeFaceEngine::GetSensorStrength();
|
||||
commonProps.maxEnrollmentsPerUser = kMaxEnrollmentsPerUser;
|
||||
commonProps.componentInfo = {std::move(hw_component_info), std::move(sw_component_info)};
|
||||
|
||||
SensorProps props;
|
||||
props.commonProps = std::move(commonProps);
|
||||
props.sensorType = kSensorType;
|
||||
props.sensorType = FakeFaceEngine::GetSensorType();
|
||||
props.halControlsPreview = kHalControlsPreview;
|
||||
props.enrollPreviewWidth = 1080;
|
||||
props.enrollPreviewHeight = 1920;
|
||||
@@ -141,6 +139,30 @@ binder_status_t Face::handleShellCommand(int in, int out, int err, const char**
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
const char* Face::type2String(FaceSensorType type) {
|
||||
switch (type) {
|
||||
case FaceSensorType::RGB:
|
||||
return "rgb";
|
||||
case FaceSensorType::IR:
|
||||
return "ir";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char* Face::strength2String(common::SensorStrength strength) {
|
||||
switch (strength) {
|
||||
case common::SensorStrength::STRONG:
|
||||
return "STRONG";
|
||||
case common::SensorStrength::WEAK:
|
||||
return "WEAK";
|
||||
case common::SensorStrength::CONVENIENCE:
|
||||
return "CONVENIENCE";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void Face::onHelp(int fd) {
|
||||
dprintf(fd, "Virtual Face HAL commands:\n");
|
||||
dprintf(fd, " help: print this help\n");
|
||||
@@ -167,7 +189,6 @@ void Face::resetConfigToDefault() {
|
||||
RESET_CONFIG_O(lockout);
|
||||
RESET_CONFIG_O(operation_authenticate_fails);
|
||||
RESET_CONFIG_O(operation_detect_interaction_fails);
|
||||
RESET_CONFIG_O(operation_enroll_fails);
|
||||
RESET_CONFIG_V(operation_authenticate_latency);
|
||||
RESET_CONFIG_V(operation_detect_interaction_latency);
|
||||
RESET_CONFIG_V(operation_enroll_latency);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/biometrics/face/BnFace.h>
|
||||
#include "FaceConfig.h"
|
||||
#include "Session.h"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
@@ -33,9 +34,20 @@ class Face : public BnFace {
|
||||
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);
|
||||
|
||||
static FaceConfig& cfg() {
|
||||
static FaceConfig* cfg = nullptr;
|
||||
if (cfg == nullptr) {
|
||||
cfg = new FaceConfig();
|
||||
cfg->init();
|
||||
}
|
||||
return *cfg;
|
||||
}
|
||||
void resetConfigToDefault();
|
||||
static const char* type2String(FaceSensorType type);
|
||||
static const char* strength2String(common::SensorStrength strength);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Session> mSession;
|
||||
void resetConfigToDefault();
|
||||
void onHelp(int);
|
||||
};
|
||||
|
||||
|
||||
93
biometrics/face/aidl/default/FaceConfig.cpp
Normal file
93
biometrics/face/aidl/default/FaceConfig.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "FaceConfig"
|
||||
|
||||
#include "FaceConfig.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <face.sysprop.h>
|
||||
|
||||
using namespace ::android::face::virt;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
|
||||
// Wrapper to system property access functions
|
||||
#define CREATE_GETTER_SETTER_WRAPPER(_NAME_, _T_) \
|
||||
ConfigValue _NAME_##Getter() { \
|
||||
return FaceHalProperties::_NAME_(); \
|
||||
} \
|
||||
bool _NAME_##Setter(const ConfigValue& v) { \
|
||||
return FaceHalProperties::_NAME_(std::get<_T_>(v)); \
|
||||
}
|
||||
|
||||
CREATE_GETTER_SETTER_WRAPPER(type, OptString)
|
||||
CREATE_GETTER_SETTER_WRAPPER(enrollments, OptIntVec)
|
||||
CREATE_GETTER_SETTER_WRAPPER(enrollment_hit, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(next_enrollment, OptString)
|
||||
CREATE_GETTER_SETTER_WRAPPER(authenticator_id, OptInt64)
|
||||
CREATE_GETTER_SETTER_WRAPPER(challenge, OptInt64)
|
||||
CREATE_GETTER_SETTER_WRAPPER(strength, OptString)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_fails, OptBool)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_latency, OptIntVec)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_duration, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_error, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_acquired, OptString)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_enroll_latency, OptIntVec)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_detect_interaction_fails, OptBool)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_detect_interaction_latency, OptIntVec)
|
||||
CREATE_GETTER_SETTER_WRAPPER(lockout, OptBool)
|
||||
CREATE_GETTER_SETTER_WRAPPER(lockout_enable, OptBool)
|
||||
CREATE_GETTER_SETTER_WRAPPER(lockout_timed_enable, OptBool)
|
||||
CREATE_GETTER_SETTER_WRAPPER(lockout_timed_threshold, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(lockout_timed_duration, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(lockout_permanent_threshold, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(features, OptIntVec)
|
||||
|
||||
// Name, Getter, Setter, Parser and default value
|
||||
#define NGS(_NAME_) #_NAME_, _NAME_##Getter, _NAME_##Setter
|
||||
static Config::Data configData[] = {
|
||||
{NGS(type), &Config::parseString, "rgb"},
|
||||
{NGS(enrollments), &Config::parseIntVec, ""},
|
||||
{NGS(enrollment_hit), &Config::parseInt32, "0"},
|
||||
{NGS(next_enrollment), &Config::parseString,
|
||||
"1:1000-[21,7,1,1103],1500-[1108,1],2000-[1113,1],2500-[1118,1]:true"},
|
||||
{NGS(authenticator_id), &Config::parseInt64, "0"},
|
||||
{NGS(challenge), &Config::parseInt64, ""},
|
||||
{NGS(strength), &Config::parseString, "strong"},
|
||||
{NGS(operation_authenticate_fails), &Config::parseBool, "false"},
|
||||
{NGS(operation_authenticate_latency), &Config::parseIntVec, ""},
|
||||
{NGS(operation_authenticate_duration), &Config::parseInt32, "500"},
|
||||
{NGS(operation_authenticate_error), &Config::parseInt32, "0"},
|
||||
{NGS(operation_authenticate_acquired), &Config::parseString, ""},
|
||||
{NGS(operation_enroll_latency), &Config::parseIntVec, ""},
|
||||
{NGS(operation_detect_interaction_latency), &Config::parseIntVec, ""},
|
||||
{NGS(operation_detect_interaction_fails), &Config::parseBool, "false"},
|
||||
{NGS(lockout), &Config::parseBool, "false"},
|
||||
{NGS(lockout_enable), &Config::parseBool, "false"},
|
||||
{NGS(lockout_timed_enable), &Config::parseBool, "false"},
|
||||
{NGS(lockout_timed_threshold), &Config::parseInt32, "3"},
|
||||
{NGS(lockout_timed_duration), &Config::parseInt32, "10000"},
|
||||
{NGS(lockout_permanent_threshold), &Config::parseInt32, "5"},
|
||||
{NGS(features), &Config::parseIntVec, ""}};
|
||||
|
||||
Config::Data* FaceConfig::getConfigData(int* size) {
|
||||
*size = sizeof(configData) / sizeof(configData[0]);
|
||||
return configData;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::face
|
||||
27
biometrics/face/aidl/default/FaceConfig.h
Normal file
27
biometrics/face/aidl/default/FaceConfig.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 "config/Config.h"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
|
||||
class FaceConfig : public Config {
|
||||
Config::Data* getConfigData(int* size) override;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::face
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <face.sysprop.h>
|
||||
|
||||
#include "Face.h"
|
||||
#include "util/CancellationSignal.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
@@ -31,23 +32,23 @@ using namespace ::android::face::virt;
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
|
||||
FaceSensorType FakeFaceEngine::GetSensorType() {
|
||||
std::string type = FaceHalProperties::type().value_or("");
|
||||
std::string type = Face::cfg().get<std::string>("type");
|
||||
if (type == "IR") {
|
||||
return FaceSensorType::IR;
|
||||
} else {
|
||||
FaceHalProperties::type("RGB");
|
||||
Face::cfg().set<std::string>("type", "RGB");
|
||||
return FaceSensorType::RGB;
|
||||
}
|
||||
}
|
||||
|
||||
common::SensorStrength FakeFaceEngine::GetSensorStrength() {
|
||||
std::string strength = FaceHalProperties::strength().value_or("");
|
||||
std::string strength = Face::cfg().get<std::string>("strength");
|
||||
if (strength == "convenience") {
|
||||
return common::SensorStrength::CONVENIENCE;
|
||||
} else if (strength == "weak") {
|
||||
return common::SensorStrength::WEAK;
|
||||
} else {
|
||||
FaceHalProperties::strength("strong");
|
||||
// Face::cfg().set<std::string>("strength", "strong");
|
||||
return common::SensorStrength::STRONG;
|
||||
}
|
||||
}
|
||||
@@ -56,13 +57,13 @@ void FakeFaceEngine::generateChallengeImpl(ISessionCallback* cb) {
|
||||
BEGIN_OP(0);
|
||||
std::uniform_int_distribution<int64_t> dist;
|
||||
auto challenge = dist(mRandom);
|
||||
FaceHalProperties::challenge(challenge);
|
||||
Face::cfg().set<int64_t>("challenge", challenge);
|
||||
cb->onChallengeGenerated(challenge);
|
||||
}
|
||||
|
||||
void FakeFaceEngine::revokeChallengeImpl(ISessionCallback* cb, int64_t challenge) {
|
||||
BEGIN_OP(0);
|
||||
FaceHalProperties::challenge({});
|
||||
Face::cfg().set<int64_t>("challenge", 0);
|
||||
cb->onChallengeRevoked(challenge);
|
||||
}
|
||||
void FakeFaceEngine::getEnrollmentConfigImpl(ISessionCallback* /*cb*/,
|
||||
@@ -71,7 +72,7 @@ void FakeFaceEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareA
|
||||
EnrollmentType /*enrollmentType*/,
|
||||
const std::vector<Feature>& /*features*/,
|
||||
const std::future<void>& cancel) {
|
||||
BEGIN_OP(getLatency(FaceHalProperties::operation_enroll_latency()));
|
||||
BEGIN_OP(getLatency(Face::cfg().getopt<OptIntVec>("operation_enroll_latency")));
|
||||
|
||||
// Do proper HAT verification in the real implementation.
|
||||
if (hat.mac.empty()) {
|
||||
@@ -80,18 +81,19 @@ void FakeFaceEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareA
|
||||
return;
|
||||
}
|
||||
|
||||
// Format: <id>:<progress_ms-[acquiredInfo,...],...:<success>
|
||||
// ------:-----------------------------------------:--------------
|
||||
// | | |--->enrollment success (true/false)
|
||||
// | |--> progress_steps
|
||||
// Format:
|
||||
// <id>:<progress_ms-[acquiredInfo,...],...:<success>
|
||||
// -------:--------------------------------------------------:--------------
|
||||
// | | |--->enrollment
|
||||
// success (true/false) | |--> progress_steps
|
||||
// |
|
||||
// |-->enrollment id
|
||||
//
|
||||
//
|
||||
// progress_steps
|
||||
// progress_steps:
|
||||
// <progress_duration>-[acquiredInfo,...]+
|
||||
// ---------------------------- ---------------------
|
||||
// | |-> sequence of acquiredInfo code
|
||||
// | |-> sequence of acquiredInfo code
|
||||
// | --> time duration of the step in ms
|
||||
//
|
||||
// E.g. 1:2000-[21,1108,5,6,1],1000-[1113,4,1]:true
|
||||
@@ -101,7 +103,7 @@ void FakeFaceEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareA
|
||||
//
|
||||
std::string defaultNextEnrollment =
|
||||
"1:1000-[21,7,1,1103],1500-[1108,1],2000-[1113,1],2500-[1118,1]:true";
|
||||
auto nextEnroll = FaceHalProperties::next_enrollment().value_or(defaultNextEnrollment);
|
||||
auto nextEnroll = Face::cfg().get<std::string>("next_enrollment");
|
||||
auto parts = Util::split(nextEnroll, ":");
|
||||
if (parts.size() != 3) {
|
||||
LOG(ERROR) << "Fail: invalid next_enrollment:" << nextEnroll;
|
||||
@@ -137,19 +139,19 @@ void FakeFaceEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareA
|
||||
|
||||
if (left == 0 && !IS_TRUE(parts[2])) { // end and failed
|
||||
LOG(ERROR) << "Fail: requested by caller: " << nextEnroll;
|
||||
FaceHalProperties::next_enrollment({});
|
||||
Face::cfg().setopt<OptString>("next_enrollment", std::nullopt);
|
||||
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
|
||||
} else { // progress and update props if last time
|
||||
LOG(INFO) << "onEnroll: " << enrollmentId << " left: " << left;
|
||||
if (left == 0) {
|
||||
auto enrollments = FaceHalProperties::enrollments();
|
||||
auto enrollments = Face::cfg().getopt<OptIntVec>("enrollments");
|
||||
enrollments.emplace_back(enrollmentId);
|
||||
FaceHalProperties::enrollments(enrollments);
|
||||
FaceHalProperties::next_enrollment({});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", enrollments);
|
||||
Face::cfg().setopt<OptString>("next_enrollment", std::nullopt);
|
||||
// change authenticatorId after new enrollment
|
||||
auto id = FaceHalProperties::authenticator_id().value_or(0);
|
||||
auto id = Face::cfg().get<std::int64_t>("authenticator_id");
|
||||
auto newId = id + 1;
|
||||
FaceHalProperties::authenticator_id(newId);
|
||||
Face::cfg().set<std::int64_t>("authenticator_id", newId);
|
||||
LOG(INFO) << "Enrolled: " << enrollmentId;
|
||||
}
|
||||
cb->onEnrollmentProgress(enrollmentId, left);
|
||||
@@ -159,10 +161,12 @@ void FakeFaceEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareA
|
||||
|
||||
void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationId*/,
|
||||
const std::future<void>& cancel) {
|
||||
BEGIN_OP(getLatency(FaceHalProperties::operation_authenticate_latency()));
|
||||
BEGIN_OP(getLatency(Face::cfg().getopt<OptIntVec>("operation_authenticate_latency")));
|
||||
|
||||
auto id = FaceHalProperties::enrollment_hit().value_or(0);
|
||||
auto enrolls = FaceHalProperties::enrollments();
|
||||
// SLEEP_MS(3000); //emulate hw HAL
|
||||
|
||||
auto id = Face::cfg().get<std::int32_t>("enrollment_hit");
|
||||
auto enrolls = Face::cfg().getopt<OptIntVec>("enrollments");
|
||||
auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
|
||||
|
||||
auto vec2str = [](std::vector<AcquiredInfo> va) {
|
||||
@@ -192,10 +196,12 @@ void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationI
|
||||
}
|
||||
|
||||
int64_t now = Util::getSystemNanoTime();
|
||||
int64_t duration =
|
||||
FaceHalProperties::operation_authenticate_duration().value_or(defaultAuthDuration);
|
||||
auto acquired =
|
||||
FaceHalProperties::operation_authenticate_acquired().value_or(defaultAcquiredInfo);
|
||||
int64_t duration = Face::cfg().get<std::int32_t>("operation_authenticate_duration");
|
||||
auto acquired = Face::cfg().get<std::string>("operation_authenticate_acquired");
|
||||
if (acquired.empty()) {
|
||||
Face::cfg().set<std::string>("operation_authenticate_acquired", defaultAcquiredInfo);
|
||||
acquired = defaultAcquiredInfo;
|
||||
}
|
||||
auto acquiredInfos = Util::parseIntSequence(acquired);
|
||||
int N = acquiredInfos.size();
|
||||
|
||||
@@ -211,21 +217,21 @@ void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationI
|
||||
|
||||
int i = 0;
|
||||
do {
|
||||
if (FaceHalProperties::lockout().value_or(false)) {
|
||||
if (Face::cfg().get<bool>("lockout")) {
|
||||
LOG(ERROR) << "Fail: lockout";
|
||||
cb->onLockoutPermanent();
|
||||
cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */);
|
||||
return;
|
||||
}
|
||||
|
||||
if (FaceHalProperties::operation_authenticate_fails().value_or(false)) {
|
||||
if (Face::cfg().get<bool>("operation_authenticate_fails")) {
|
||||
LOG(ERROR) << "Fail: operation_authenticate_fails";
|
||||
mLockoutTracker.addFailedAttempt(cb);
|
||||
cb->onAuthenticationFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
auto err = FaceHalProperties::operation_authenticate_error().value_or(0);
|
||||
auto err = Face::cfg().get<std::int32_t>("operation_authenticate_error");
|
||||
if (err != 0) {
|
||||
LOG(ERROR) << "Fail: operation_authenticate_error";
|
||||
auto ec = convertError(err);
|
||||
@@ -249,6 +255,15 @@ void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationI
|
||||
LOG(INFO) << "AcquiredInfo:" << i << ": (" << (int)ac.first << "," << (int)ac.second
|
||||
<< ")";
|
||||
i++;
|
||||
|
||||
// the captured face id may change during authentication period
|
||||
auto idnew = Face::cfg().get<std::int32_t>("enrollment_hit");
|
||||
if (id != idnew) {
|
||||
isEnrolled = std::find(enrolls.begin(), enrolls.end(), idnew) != enrolls.end();
|
||||
LOG(INFO) << "enrollment_hit changed from " << id << " to " << idnew;
|
||||
id = idnew;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SLEEP_MS(duration / N);
|
||||
@@ -292,9 +307,9 @@ std::pair<Error, int32_t> FakeFaceEngine::convertError(int32_t code) {
|
||||
}
|
||||
|
||||
void FakeFaceEngine::detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel) {
|
||||
BEGIN_OP(getLatency(FaceHalProperties::operation_detect_interaction_latency()));
|
||||
BEGIN_OP(getLatency(Face::cfg().getopt<OptIntVec>("operation_detect_interaction_latency")));
|
||||
|
||||
if (FaceHalProperties::operation_detect_interaction_fails().value_or(false)) {
|
||||
if (Face::cfg().get<bool>("operation_detect_interaction_fails")) {
|
||||
LOG(ERROR) << "Fail: operation_detect_interaction_fails";
|
||||
cb->onError(Error::VENDOR, 0 /* vendorError */);
|
||||
return;
|
||||
@@ -306,8 +321,8 @@ void FakeFaceEngine::detectInteractionImpl(ISessionCallback* cb, const std::futu
|
||||
return;
|
||||
}
|
||||
|
||||
auto id = FaceHalProperties::enrollment_hit().value_or(0);
|
||||
auto enrolls = FaceHalProperties::enrollments();
|
||||
auto id = Face::cfg().get<std::int32_t>("enrollment_hit");
|
||||
auto enrolls = Face::cfg().getopt<OptIntVec>("enrollments");
|
||||
auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
|
||||
if (id <= 0 || !isEnrolled) {
|
||||
LOG(ERROR) << "Fail: not enrolled";
|
||||
@@ -321,7 +336,7 @@ void FakeFaceEngine::detectInteractionImpl(ISessionCallback* cb, const std::futu
|
||||
void FakeFaceEngine::enumerateEnrollmentsImpl(ISessionCallback* cb) {
|
||||
BEGIN_OP(0);
|
||||
std::vector<int32_t> enrollments;
|
||||
for (const auto& enrollmentId : FaceHalProperties::enrollments()) {
|
||||
for (const auto& enrollmentId : Face::cfg().getopt<OptIntVec>("enrollments")) {
|
||||
if (enrollmentId) {
|
||||
enrollments.push_back(*enrollmentId);
|
||||
}
|
||||
@@ -334,20 +349,20 @@ void FakeFaceEngine::removeEnrollmentsImpl(ISessionCallback* cb,
|
||||
BEGIN_OP(0);
|
||||
|
||||
std::vector<std::optional<int32_t>> newEnrollments;
|
||||
for (const auto& enrollment : FaceHalProperties::enrollments()) {
|
||||
for (const auto& enrollment : Face::cfg().getopt<OptIntVec>("enrollments")) {
|
||||
auto id = enrollment.value_or(0);
|
||||
if (std::find(enrollmentIds.begin(), enrollmentIds.end(), id) == enrollmentIds.end()) {
|
||||
newEnrollments.emplace_back(id);
|
||||
}
|
||||
}
|
||||
FaceHalProperties::enrollments(newEnrollments);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", newEnrollments);
|
||||
cb->onEnrollmentsRemoved(enrollmentIds);
|
||||
}
|
||||
|
||||
void FakeFaceEngine::getFeaturesImpl(ISessionCallback* cb) {
|
||||
BEGIN_OP(0);
|
||||
|
||||
if (FaceHalProperties::enrollments().empty()) {
|
||||
if (Face::cfg().getopt<OptIntVec>("enrollments").empty()) {
|
||||
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
|
||||
return;
|
||||
}
|
||||
@@ -365,7 +380,7 @@ void FakeFaceEngine::setFeatureImpl(ISessionCallback* cb, const keymaster::Hardw
|
||||
Feature feature, bool enabled) {
|
||||
BEGIN_OP(0);
|
||||
|
||||
if (FaceHalProperties::enrollments().empty()) {
|
||||
if (Face::cfg().getopt<OptIntVec>("enrollments").empty()) {
|
||||
LOG(ERROR) << "Unable to set feature, enrollments are empty";
|
||||
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
|
||||
return;
|
||||
@@ -377,7 +392,7 @@ void FakeFaceEngine::setFeatureImpl(ISessionCallback* cb, const keymaster::Hardw
|
||||
return;
|
||||
}
|
||||
|
||||
auto features = FaceHalProperties::features();
|
||||
auto features = Face::cfg().getopt<OptIntVec>("features");
|
||||
|
||||
auto itr = std::find_if(features.begin(), features.end(), [feature](const auto& theFeature) {
|
||||
return *theFeature == (int)feature;
|
||||
@@ -389,7 +404,7 @@ void FakeFaceEngine::setFeatureImpl(ISessionCallback* cb, const keymaster::Hardw
|
||||
features.push_back((int)feature);
|
||||
}
|
||||
|
||||
FaceHalProperties::features(features);
|
||||
Face::cfg().setopt<OptIntVec>("features", features);
|
||||
cb->onFeatureSet(feature);
|
||||
}
|
||||
|
||||
@@ -399,22 +414,22 @@ void FakeFaceEngine::getAuthenticatorIdImpl(ISessionCallback* cb) {
|
||||
if (GetSensorStrength() != common::SensorStrength::STRONG) {
|
||||
cb->onAuthenticatorIdRetrieved(0);
|
||||
} else {
|
||||
cb->onAuthenticatorIdRetrieved(FaceHalProperties::authenticator_id().value_or(0));
|
||||
cb->onAuthenticatorIdRetrieved(Face::cfg().get<std::int64_t>("authenticator_id"));
|
||||
}
|
||||
}
|
||||
|
||||
void FakeFaceEngine::invalidateAuthenticatorIdImpl(ISessionCallback* cb) {
|
||||
BEGIN_OP(0);
|
||||
int64_t authenticatorId = FaceHalProperties::authenticator_id().value_or(0);
|
||||
int64_t authenticatorId = Face::cfg().get<std::int64_t>("authenticator_id");
|
||||
int64_t newId = authenticatorId + 1;
|
||||
FaceHalProperties::authenticator_id(newId);
|
||||
Face::cfg().set<std::int64_t>("authenticator_id", newId);
|
||||
cb->onAuthenticatorIdInvalidated(newId);
|
||||
}
|
||||
|
||||
void FakeFaceEngine::resetLockoutImpl(ISessionCallback* cb,
|
||||
const keymaster::HardwareAuthToken& /*hat*/) {
|
||||
BEGIN_OP(0);
|
||||
FaceHalProperties::lockout(false);
|
||||
Face::cfg().set<bool>("lockout", false);
|
||||
mLockoutTracker.reset();
|
||||
cb->onLockoutCleared();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "FakeLockoutTracker.h"
|
||||
#include <android-base/logging.h>
|
||||
#include <face.sysprop.h>
|
||||
#include "Face.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
using namespace ::android::face::virt;
|
||||
@@ -36,15 +37,15 @@ void FakeLockoutTracker::reset(bool dueToTimerExpire) {
|
||||
}
|
||||
|
||||
void FakeLockoutTracker::addFailedAttempt(ISessionCallback* cb) {
|
||||
bool lockoutEnabled = FaceHalProperties::lockout_enable().value_or(false);
|
||||
bool timedLockoutenabled = FaceHalProperties::lockout_timed_enable().value_or(false);
|
||||
bool lockoutEnabled = Face::cfg().get<bool>("lockout_enable");
|
||||
bool timedLockoutenabled = Face::cfg().get<bool>("lockout_timed_enable");
|
||||
if (lockoutEnabled) {
|
||||
mFailedCount++;
|
||||
mTimedFailedCount++;
|
||||
mLastFailedTime = Util::getSystemNanoTime();
|
||||
int32_t lockoutTimedThreshold = FaceHalProperties::lockout_timed_threshold().value_or(3);
|
||||
int32_t lockoutTimedThreshold = Face::cfg().get<std::int32_t>("lockout_timed_threshold");
|
||||
int32_t lockoutPermanetThreshold =
|
||||
FaceHalProperties::lockout_permanent_threshold().value_or(5);
|
||||
Face::cfg().get<std::int32_t>("lockout_permanent_threshold");
|
||||
if (mFailedCount >= lockoutPermanetThreshold) {
|
||||
mCurrentMode = LockoutMode::kPermanent;
|
||||
LOG(ERROR) << "FakeLockoutTracker: lockoutPermanent";
|
||||
@@ -68,7 +69,7 @@ FakeLockoutTracker::LockoutMode FakeLockoutTracker::getMode() {
|
||||
}
|
||||
|
||||
int32_t FakeLockoutTracker::getTimedLockoutDuration() {
|
||||
return FaceHalProperties::lockout_timed_duration().value_or(10 * 1000);
|
||||
return Face::cfg().get<std::int32_t>("lockout_timed_duration");
|
||||
}
|
||||
|
||||
int64_t FakeLockoutTracker::getLockoutTimeLeft() {
|
||||
|
||||
275
biometrics/face/aidl/default/VirtualHal.cpp
Normal file
275
biometrics/face/aidl/default/VirtualHal.cpp
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 <unordered_map>
|
||||
|
||||
#include "VirtualHal.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "util/CancellationSignal.h"
|
||||
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "FaceVirtualHalAidl"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
using AcquiredInfoAndVendorCode = virtualhal::AcquiredInfoAndVendorCode;
|
||||
using Tag = AcquiredInfoAndVendorCode::Tag;
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setEnrollments(const std::vector<int32_t>& enrollments) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", intVec2OptIntVec(enrollments));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setEnrollmentHit(int32_t enrollment_hit) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", enrollment_hit);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setNextEnrollment(
|
||||
const ::aidl::android::hardware::biometrics::face::NextEnrollment& next_enrollment) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
std::ostringstream os;
|
||||
os << next_enrollment.id << ":";
|
||||
|
||||
int stepSize = next_enrollment.progressSteps.size();
|
||||
for (int i = 0; i < stepSize; i++) {
|
||||
auto& step = next_enrollment.progressSteps[i];
|
||||
os << step.durationMs;
|
||||
int acSize = step.acquiredInfoAndVendorCodes.size();
|
||||
for (int j = 0; j < acSize; j++) {
|
||||
if (j == 0) os << "-[";
|
||||
auto& acquiredInfoAndVendorCode = step.acquiredInfoAndVendorCodes[j];
|
||||
if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::vendorCode)
|
||||
os << acquiredInfoAndVendorCode.get<Tag::vendorCode>();
|
||||
else if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::acquiredInfo)
|
||||
os << (int)acquiredInfoAndVendorCode.get<Tag::acquiredInfo>();
|
||||
else
|
||||
LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode union tag";
|
||||
if (j == acSize - 1)
|
||||
os << "]";
|
||||
else
|
||||
os << ",";
|
||||
}
|
||||
if (i == stepSize - 1)
|
||||
os << ":";
|
||||
else
|
||||
os << ",";
|
||||
}
|
||||
|
||||
os << (next_enrollment.result ? "true" : "false");
|
||||
Face::cfg().set<std::string>("next_enrollment", os.str());
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setAuthenticatorId(int64_t in_id) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int64_t>("authenticator_id", in_id);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setChallenge(int64_t in_challenge) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int64_t>("challenge", in_challenge);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateFails(bool in_fail) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<bool>("operation_authenticate_fails", in_fail);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateLatency(
|
||||
const std::vector<int32_t>& in_latency) {
|
||||
ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
|
||||
if (!status.isOk()) {
|
||||
return status;
|
||||
}
|
||||
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().setopt<OptIntVec>("operation_authenticate_latency", intVec2OptIntVec(in_latency));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateDuration(int32_t in_duration) {
|
||||
if (in_duration < 0) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative"));
|
||||
}
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int32_t>("operation_authenticate_duration", in_duration);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateError(int32_t in_error) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int32_t>("operation_authenticate_error", in_error);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateAcquired(
|
||||
const std::vector<AcquiredInfoAndVendorCode>& in_acquired) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().setopt<OptIntVec>("operation_authenticate_acquired",
|
||||
acquiredInfoVec2OptIntVec(in_acquired));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationEnrollLatency(const std::vector<int32_t>& in_latency) {
|
||||
ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
|
||||
if (!status.isOk()) {
|
||||
return status;
|
||||
}
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().setopt<OptIntVec>("operation_enroll_latency", intVec2OptIntVec(in_latency));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionLatency(
|
||||
const std::vector<int32_t>& in_latency) {
|
||||
ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
|
||||
if (!status.isOk()) {
|
||||
return status;
|
||||
}
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().setopt<OptIntVec>("operation_detect_interact_latency",
|
||||
intVec2OptIntVec(in_latency));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionFails(bool in_fails) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<bool>("operation_detect_interaction_fails", in_fails);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setLockout(bool in_lockout) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<bool>("lockout", in_lockout);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setLockoutEnable(bool in_enable) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<bool>("lockout_enable", in_enable);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setLockoutTimedEnable(bool in_enable) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<bool>("lockout_timed_enable", in_enable);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setLockoutTimedThreshold(int32_t in_threshold) {
|
||||
if (in_threshold < 0) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative"));
|
||||
}
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int32_t>("lockout_timed_threshold", in_threshold);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setLockoutTimedDuration(int32_t in_duration) {
|
||||
if (in_duration < 0) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative"));
|
||||
}
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int32_t>("lockout_timed_duration", in_duration);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setLockoutPermanentThreshold(int32_t in_threshold) {
|
||||
if (in_threshold < 0) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative"));
|
||||
}
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int32_t>("lockout_permanent_threshold", in_threshold);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::resetConfigurations() {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().init();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setType(
|
||||
::aidl::android::hardware::biometrics::face::FaceSensorType in_type) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<std::string>("type", Face::type2String(in_type));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setSensorStrength(common::SensorStrength in_strength) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<std::string>("strength", Face::strength2String(in_strength));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
OptIntVec VirtualHal::intVec2OptIntVec(const std::vector<int32_t>& in_vec) {
|
||||
OptIntVec optIntVec;
|
||||
std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec),
|
||||
[](int value) { return std::optional<int>(value); });
|
||||
return optIntVec;
|
||||
}
|
||||
|
||||
OptIntVec VirtualHal::acquiredInfoVec2OptIntVec(
|
||||
const std::vector<AcquiredInfoAndVendorCode>& in_vec) {
|
||||
OptIntVec optIntVec;
|
||||
std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec),
|
||||
[](AcquiredInfoAndVendorCode ac) {
|
||||
int value;
|
||||
if (ac.getTag() == AcquiredInfoAndVendorCode::acquiredInfo)
|
||||
value = (int)ac.get<Tag::acquiredInfo>();
|
||||
else if (ac.getTag() == AcquiredInfoAndVendorCode::vendorCode)
|
||||
value = ac.get<Tag::vendorCode>();
|
||||
else
|
||||
LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode tag";
|
||||
return std::optional<int>(value);
|
||||
});
|
||||
return optIntVec;
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::sanityCheckLatency(const std::vector<int32_t>& in_latency) {
|
||||
if (in_latency.size() == 0 || in_latency.size() > 2) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IVirtualHal::STATUS_INVALID_PARAMETER,
|
||||
"Error: input input array must contain 1 or 2 elements"));
|
||||
}
|
||||
|
||||
for (auto x : in_latency) {
|
||||
if (x < 0) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IVirtualHal::STATUS_INVALID_PARAMETER,
|
||||
"Error: input data must not be negative"));
|
||||
}
|
||||
}
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::getFaceHal(std::shared_ptr<IFace>* pFace) {
|
||||
*pFace = mFp;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
} // namespace aidl::android::hardware::biometrics::face
|
||||
66
biometrics/face/aidl/default/VirtualHal.h
Normal file
66
biometrics/face/aidl/default/VirtualHal.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 <aidl/android/hardware/biometrics/face/virtualhal/BnVirtualHal.h>
|
||||
|
||||
#include "Face.h"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
using namespace virtualhal;
|
||||
class VirtualHal : public BnVirtualHal {
|
||||
public:
|
||||
VirtualHal(std::shared_ptr<Face> fp) : mFp(fp) {}
|
||||
|
||||
::ndk::ScopedAStatus setEnrollments(const std::vector<int32_t>& in_id) override;
|
||||
::ndk::ScopedAStatus setEnrollmentHit(int32_t in_hit_id) override;
|
||||
::ndk::ScopedAStatus setNextEnrollment(
|
||||
const ::aidl::android::hardware::biometrics::face::NextEnrollment& in_next_enrollment)
|
||||
override;
|
||||
::ndk::ScopedAStatus setAuthenticatorId(int64_t in_id) override;
|
||||
::ndk::ScopedAStatus setChallenge(int64_t in_challenge) override;
|
||||
::ndk::ScopedAStatus setOperationAuthenticateFails(bool in_fail) override;
|
||||
::ndk::ScopedAStatus setOperationAuthenticateLatency(
|
||||
const std::vector<int32_t>& in_latency) override;
|
||||
::ndk::ScopedAStatus setOperationAuthenticateDuration(int32_t in_duration) override;
|
||||
::ndk::ScopedAStatus setOperationAuthenticateError(int32_t in_error) override;
|
||||
::ndk::ScopedAStatus setOperationAuthenticateAcquired(
|
||||
const std::vector<AcquiredInfoAndVendorCode>& in_acquired) override;
|
||||
::ndk::ScopedAStatus setOperationEnrollLatency(const std::vector<int32_t>& in_latency) override;
|
||||
::ndk::ScopedAStatus setOperationDetectInteractionLatency(
|
||||
const std::vector<int32_t>& in_latency) override;
|
||||
::ndk::ScopedAStatus setOperationDetectInteractionFails(bool in_fails) override;
|
||||
::ndk::ScopedAStatus setLockout(bool in_lockout) override;
|
||||
::ndk::ScopedAStatus setLockoutEnable(bool in_enable) override;
|
||||
::ndk::ScopedAStatus setLockoutTimedEnable(bool in_enable) override;
|
||||
::ndk::ScopedAStatus setLockoutTimedThreshold(int32_t in_threshold) override;
|
||||
::ndk::ScopedAStatus setLockoutTimedDuration(int32_t in_duration) override;
|
||||
::ndk::ScopedAStatus setLockoutPermanentThreshold(int32_t in_threshold) override;
|
||||
::ndk::ScopedAStatus resetConfigurations() override;
|
||||
::ndk::ScopedAStatus setType(
|
||||
::aidl::android::hardware::biometrics::face::FaceSensorType in_type) override;
|
||||
::ndk::ScopedAStatus setSensorStrength(common::SensorStrength in_strength) override;
|
||||
::ndk::ScopedAStatus getFaceHal(std::shared_ptr<IFace>* _aidl_return);
|
||||
|
||||
private:
|
||||
OptIntVec intVec2OptIntVec(const std::vector<int32_t>& intVec);
|
||||
OptIntVec acquiredInfoVec2OptIntVec(const std::vector<AcquiredInfoAndVendorCode>& intVec);
|
||||
::ndk::ScopedAStatus sanityCheckLatency(const std::vector<int32_t>& in_latency);
|
||||
std::shared_ptr<Face> mFp;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::face
|
||||
@@ -23,7 +23,7 @@ apex {
|
||||
key: "com.android.hardware.key",
|
||||
certificate: ":com.android.hardware.certificate",
|
||||
updatable: false,
|
||||
vendor: true,
|
||||
system_ext_specific: true,
|
||||
|
||||
binaries: [
|
||||
// hal
|
||||
@@ -31,9 +31,7 @@ apex {
|
||||
],
|
||||
prebuilts: [
|
||||
// init_rc
|
||||
"face-example-apex.rc",
|
||||
// vintf_fragment
|
||||
"face-example-apex.xml",
|
||||
"face-virtual-apex.rc",
|
||||
],
|
||||
|
||||
overrides: [
|
||||
@@ -42,21 +40,7 @@ apex {
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
name: "face-example-apex.rc",
|
||||
src: ":gen-face-example-apex.rc",
|
||||
installable: false,
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "gen-face-example-apex.rc",
|
||||
srcs: [":face-example.rc"],
|
||||
out: ["face-example-apex.rc"],
|
||||
cmd: "sed -e 's@/vendor/bin/@/apex/com.android.hardware.biometrics.face.virtual/bin/@' $(in) > $(out)",
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
name: "face-example-apex.xml",
|
||||
src: ":face-example.xml",
|
||||
sub_dir: "vintf",
|
||||
name: "face-virtual-apex.rc",
|
||||
src: ":face-virtual.rc",
|
||||
installable: false,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
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: "lockout_enable"
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.lockout_enable"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout_permanent_threshold"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.lockout_permanent_threshold"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout_timed_duration"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.lockout_timed_duration"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout_timed_enable"
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.lockout_timed_enable"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout_timed_threshold"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.lockout_timed_threshold"
|
||||
}
|
||||
prop {
|
||||
api_name: "next_enrollment"
|
||||
type: String
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.next_enrollment"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_acquired"
|
||||
type: String
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_acquired"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_duration"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_duration"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_error"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_error"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_fails"
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_fails"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_latency"
|
||||
type: IntegerList
|
||||
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: IntegerList
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_detect_interaction_latency"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_enroll_latency"
|
||||
type: IntegerList
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_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"
|
||||
}
|
||||
}
|
||||
|
||||
8
biometrics/face/aidl/default/face-default.rc
Normal file
8
biometrics/face/aidl/default/face-default.rc
Normal file
@@ -0,0 +1,8 @@
|
||||
service vendor.face-default /vendor/bin/hw/android.hardware.biometrics.face-service.default default
|
||||
class hal
|
||||
user nobody
|
||||
group nobody
|
||||
interface aidl android.hardware.biometrics.face.IFace/default
|
||||
oneshot
|
||||
disabled
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.biometrics.face</name>
|
||||
<version>4</version>
|
||||
<fqname>IFace/virtual</fqname>
|
||||
<fqname>IFace/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
@@ -1,8 +0,0 @@
|
||||
service vendor.face-example /vendor/bin/hw/android.hardware.biometrics.face-service.example
|
||||
class hal
|
||||
user nobody
|
||||
group nobody
|
||||
interface aidl android.hardware.biometrics.face.IFace/virtual
|
||||
oneshot
|
||||
disabled
|
||||
|
||||
8
biometrics/face/aidl/default/face-virtual.rc
Normal file
8
biometrics/face/aidl/default/face-virtual.rc
Normal file
@@ -0,0 +1,8 @@
|
||||
service face-virtual /apex/com.android.hardware.biometrics.face.virtual/bin/hw/android.hardware.biometrics.face-service.example virtual
|
||||
class hal
|
||||
user nobody
|
||||
group nobody
|
||||
interface aidl android.hardware.biometrics.face.virtualhal.IVirtualHal/virtual
|
||||
oneshot
|
||||
disabled
|
||||
|
||||
@@ -7,7 +7,7 @@ owner: Vendor
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.type"
|
||||
type: String
|
||||
scope: Internal
|
||||
scope: Public
|
||||
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: Internal
|
||||
scope: Public
|
||||
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: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "enrollments"
|
||||
}
|
||||
@@ -36,7 +36,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.features"
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "features"
|
||||
}
|
||||
@@ -46,7 +46,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.enrollment_hit"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "enrollment_hit"
|
||||
}
|
||||
@@ -60,7 +60,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.next_enrollment"
|
||||
type: String
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "next_enrollment"
|
||||
}
|
||||
@@ -69,7 +69,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.authenticator_id"
|
||||
type: Long
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "authenticator_id"
|
||||
}
|
||||
@@ -78,7 +78,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.challenge"
|
||||
type: Long
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "challenge"
|
||||
}
|
||||
@@ -87,7 +87,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.lockout"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout"
|
||||
}
|
||||
@@ -96,7 +96,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_fails"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_fails"
|
||||
}
|
||||
@@ -105,27 +105,18 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_detect_interaction_fails"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_detect_interaction_fails"
|
||||
}
|
||||
|
||||
# force all enroll operations to fail
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_enroll_fails"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "operation_enroll_fails"
|
||||
}
|
||||
|
||||
# add a latency to authentication operations
|
||||
# Note that this latency is the initial authentication latency that occurs before
|
||||
# the HAL will send AcquiredInfo::START and AcquiredInfo::FIRST_FRAME_RECEIVED
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_latency"
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_latency"
|
||||
}
|
||||
@@ -134,7 +125,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_detect_interaction_latency"
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_detect_interaction_latency"
|
||||
}
|
||||
@@ -143,7 +134,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_enroll_latency"
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_enroll_latency"
|
||||
}
|
||||
@@ -153,7 +144,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_duration"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_duration"
|
||||
}
|
||||
@@ -162,7 +153,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_error"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_error"
|
||||
}
|
||||
@@ -171,7 +162,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_acquired"
|
||||
type: String
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_acquired"
|
||||
}
|
||||
@@ -180,7 +171,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.lockout_enable"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_enable"
|
||||
}
|
||||
@@ -189,7 +180,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.lockout_timed_enable"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_timed_enable"
|
||||
}
|
||||
@@ -198,7 +189,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.lockout_timed_threshold"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_timed_threshold"
|
||||
}
|
||||
@@ -207,7 +198,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.lockout_timed_duration"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_timed_duration"
|
||||
}
|
||||
@@ -216,7 +207,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.lockout_permanent_threshold"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_permanent_threshold"
|
||||
}
|
||||
|
||||
@@ -14,25 +14,49 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "FaceVirtualHal"
|
||||
|
||||
#include "Face.h"
|
||||
#include "VirtualHal.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
using aidl::android::hardware::biometrics::face::Face;
|
||||
using aidl::android::hardware::biometrics::face::VirtualHal;
|
||||
|
||||
int main() {
|
||||
LOG(INFO) << "Face HAL started";
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
LOG(ERROR) << "Missing argument -> exiting, Valid arguments:[default|virtual]";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
LOG(INFO) << "Face HAL started: " << argv[1];
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||
std::shared_ptr<Face> hal = ndk::SharedRefBase::make<Face>();
|
||||
std::shared_ptr<VirtualHal> hal_vhal = ndk::SharedRefBase::make<VirtualHal>(hal);
|
||||
|
||||
const std::string instance = std::string(Face::descriptor) + "/virtual";
|
||||
binder_status_t status =
|
||||
AServiceManager_registerLazyService(hal->asBinder().get(), instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK);
|
||||
if (strcmp(argv[1], "default") == 0) {
|
||||
const std::string instance = std::string(Face::descriptor) + "/default";
|
||||
auto binder = hal->asBinder();
|
||||
binder_status_t status =
|
||||
AServiceManager_registerLazyService(binder.get(), instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK);
|
||||
LOG(INFO) << "started IFace/default";
|
||||
} else if (strcmp(argv[1], "virtual") == 0) {
|
||||
const std::string instance = std::string(VirtualHal::descriptor) + "/virtual";
|
||||
auto binder = hal_vhal->asBinder();
|
||||
binder_status_t status =
|
||||
AServiceManager_registerLazyService(binder.get(), instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK);
|
||||
LOG(INFO) << "started IVirtualHal/virtual";
|
||||
} else {
|
||||
LOG(ERROR) << "Unexpected argument: " << argv[1];
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
AServiceManager_forceLazyServicesPersist(true);
|
||||
|
||||
ABinderProcess_joinThreadPool();
|
||||
return EXIT_FAILURE; // should not reach
|
||||
return EXIT_FAILURE; // should not reach here
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <aidl/android/hardware/biometrics/face/BnSessionCallback.h>
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "Face.h"
|
||||
#include "FakeFaceEngine.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
@@ -141,12 +142,12 @@ class FakeFaceEngineTest : public ::testing::Test {
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
FaceHalProperties::enrollments({});
|
||||
FaceHalProperties::challenge({});
|
||||
FaceHalProperties::features({});
|
||||
FaceHalProperties::authenticator_id({});
|
||||
FaceHalProperties::strength("");
|
||||
FaceHalProperties::operation_detect_interaction_latency({});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {});
|
||||
Face::cfg().set<std::int64_t>("challenge", 0);
|
||||
Face::cfg().setopt<OptIntVec>("features", {});
|
||||
Face::cfg().set<std::int64_t>("authenticator_id", 0);
|
||||
Face::cfg().set<std::string>("strength", "");
|
||||
Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {});
|
||||
}
|
||||
|
||||
FakeFaceEngine mEngine;
|
||||
@@ -160,81 +161,83 @@ TEST_F(FakeFaceEngineTest, one_eq_one) {
|
||||
|
||||
TEST_F(FakeFaceEngineTest, GenerateChallenge) {
|
||||
mEngine.generateChallengeImpl(mCallback.get());
|
||||
ASSERT_EQ(FaceHalProperties::challenge().value(), mCallback->mLastChallenge);
|
||||
ASSERT_EQ(Face::cfg().get<std::int64_t>("challenge"), mCallback->mLastChallenge);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, RevokeChallenge) {
|
||||
auto challenge = FaceHalProperties::challenge().value_or(10);
|
||||
auto challenge = Face::cfg().get<std::int64_t>("challenge");
|
||||
mEngine.revokeChallengeImpl(mCallback.get(), challenge);
|
||||
ASSERT_FALSE(FaceHalProperties::challenge().has_value());
|
||||
ASSERT_FALSE(Face::cfg().get<std::int64_t>("challenge"));
|
||||
ASSERT_EQ(challenge, mCallback->mLastChallengeRevoked);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, ResetLockout) {
|
||||
FaceHalProperties::lockout(true);
|
||||
Face::cfg().set<bool>("lockout", true);
|
||||
mEngine.resetLockoutImpl(mCallback.get(), {});
|
||||
ASSERT_FALSE(mCallback->mLockoutPermanent);
|
||||
ASSERT_FALSE(FaceHalProperties::lockout().value_or(true));
|
||||
ASSERT_FALSE(Face::cfg().get<bool>("lockout"));
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, AuthenticatorId) {
|
||||
FaceHalProperties::authenticator_id(50);
|
||||
Face::cfg().set<std::int64_t>("authenticator_id", 50);
|
||||
mEngine.getAuthenticatorIdImpl(mCallback.get());
|
||||
ASSERT_EQ(50, mCallback->mLastAuthenticatorId);
|
||||
ASSERT_FALSE(mCallback->mAuthenticatorIdInvalidated);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, GetAuthenticatorIdWeakReturnsZero) {
|
||||
FaceHalProperties::strength("weak");
|
||||
FaceHalProperties::authenticator_id(500);
|
||||
Face::cfg().set<std::string>("strength", "weak");
|
||||
Face::cfg().set<std::int64_t>("authenticator_id", 500);
|
||||
mEngine.getAuthenticatorIdImpl(mCallback.get());
|
||||
ASSERT_EQ(0, mCallback->mLastAuthenticatorId);
|
||||
ASSERT_FALSE(mCallback->mAuthenticatorIdInvalidated);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, AuthenticatorIdInvalidate) {
|
||||
FaceHalProperties::authenticator_id(500);
|
||||
Face::cfg().set<std::int64_t>("authenticator_id", 500);
|
||||
mEngine.invalidateAuthenticatorIdImpl(mCallback.get());
|
||||
ASSERT_NE(500, FaceHalProperties::authenticator_id().value());
|
||||
ASSERT_NE(500, Face::cfg().get<std::int64_t>("authenticator_id"));
|
||||
ASSERT_TRUE(mCallback->mAuthenticatorIdInvalidated);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, Enroll) {
|
||||
FaceHalProperties::next_enrollment("1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:true");
|
||||
Face::cfg().set<std::string>("next_enrollment",
|
||||
"1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:true");
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.enrollImpl(mCallback.get(), hat, {} /*enrollmentType*/, {} /*features*/,
|
||||
mCancel.get_future());
|
||||
ASSERT_FALSE(FaceHalProperties::next_enrollment().has_value());
|
||||
ASSERT_EQ(1, FaceHalProperties::enrollments().size());
|
||||
ASSERT_EQ(1, FaceHalProperties::enrollments()[0].value());
|
||||
ASSERT_FALSE(Face::cfg().getopt<OptString>("next_enrollment").has_value());
|
||||
ASSERT_EQ(1, Face::cfg().getopt<OptIntVec>("enrollments").size());
|
||||
ASSERT_EQ(1, Face::cfg().getopt<OptIntVec>("enrollments")[0].value());
|
||||
ASSERT_EQ(1, mCallback->mLastEnrolled);
|
||||
ASSERT_EQ(0, mCallback->mRemaining);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, EnrollFails) {
|
||||
FaceHalProperties::next_enrollment("1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:false");
|
||||
Face::cfg().set<std::string>("next_enrollment",
|
||||
"1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:false");
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.enrollImpl(mCallback.get(), hat, {} /*enrollmentType*/, {} /*features*/,
|
||||
mCancel.get_future());
|
||||
ASSERT_FALSE(FaceHalProperties::next_enrollment().has_value());
|
||||
ASSERT_EQ(0, FaceHalProperties::enrollments().size());
|
||||
ASSERT_FALSE(Face::cfg().getopt<OptString>("next_enrollment").has_value());
|
||||
ASSERT_EQ(0, Face::cfg().getopt<OptIntVec>("enrollments").size());
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, EnrollCancel) {
|
||||
FaceHalProperties::next_enrollment("1:2000-[21,8,9],300:false");
|
||||
Face::cfg().set<std::string>("next_enrollment", "1:2000-[21,8,9],300:false");
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mCancel.set_value();
|
||||
mEngine.enrollImpl(mCallback.get(), hat, {} /*enrollmentType*/, {} /*features*/,
|
||||
mCancel.get_future());
|
||||
ASSERT_EQ(Error::CANCELED, mCallback->mError);
|
||||
ASSERT_EQ(-1, mCallback->mLastEnrolled);
|
||||
ASSERT_EQ(0, FaceHalProperties::enrollments().size());
|
||||
ASSERT_TRUE(FaceHalProperties::next_enrollment().has_value());
|
||||
ASSERT_EQ(0, Face::cfg().getopt<OptIntVec>("enrollments").size());
|
||||
ASSERT_FALSE(Face::cfg().get<std::string>("next_enrollment").empty());
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, Authenticate) {
|
||||
FaceHalProperties::enrollments({100});
|
||||
FaceHalProperties::enrollment_hit(100);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {100});
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 100);
|
||||
mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
|
||||
|
||||
ASSERT_EQ(100, mCallback->mLastAuthenticated);
|
||||
@@ -242,32 +245,32 @@ TEST_F(FakeFaceEngineTest, Authenticate) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, AuthenticateCancel) {
|
||||
FaceHalProperties::enrollments({100});
|
||||
FaceHalProperties::enrollment_hit(100);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {100});
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 100);
|
||||
mCancel.set_value();
|
||||
mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
|
||||
ASSERT_EQ(Error::CANCELED, mCallback->mError);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, AuthenticateFailedForUnEnrolled) {
|
||||
FaceHalProperties::enrollments({3});
|
||||
FaceHalProperties::enrollment_hit(100);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {3});
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 100);
|
||||
mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
|
||||
ASSERT_EQ(Error::TIMEOUT, mCallback->mError);
|
||||
ASSERT_TRUE(mCallback->mAuthenticateFailed);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, DetectInteraction) {
|
||||
FaceHalProperties::enrollments({100});
|
||||
FaceHalProperties::enrollment_hit(100);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {100});
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 100);
|
||||
ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
|
||||
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
|
||||
ASSERT_EQ(1, mCallback->mInteractionDetectedCount);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, DetectInteractionCancel) {
|
||||
FaceHalProperties::enrollments({100});
|
||||
FaceHalProperties::enrollment_hit(100);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {100});
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 100);
|
||||
mCancel.set_value();
|
||||
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
|
||||
ASSERT_EQ(Error::CANCELED, mCallback->mError);
|
||||
@@ -279,7 +282,7 @@ TEST_F(FakeFaceEngineTest, GetFeatureEmpty) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, SetFeature) {
|
||||
FaceHalProperties::enrollments({1});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {1});
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
|
||||
auto features = mCallback->mFeatures;
|
||||
@@ -294,7 +297,7 @@ TEST_F(FakeFaceEngineTest, SetFeature) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, ToggleFeature) {
|
||||
FaceHalProperties::enrollments({1});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {1});
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
|
||||
mEngine.getFeaturesImpl(mCallback.get());
|
||||
@@ -310,7 +313,7 @@ TEST_F(FakeFaceEngineTest, ToggleFeature) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, TurningOffNonExistentFeatureDoesNothing) {
|
||||
FaceHalProperties::enrollments({1});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {1});
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, false);
|
||||
mEngine.getFeaturesImpl(mCallback.get());
|
||||
@@ -319,7 +322,7 @@ TEST_F(FakeFaceEngineTest, TurningOffNonExistentFeatureDoesNothing) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, SetMultipleFeatures) {
|
||||
FaceHalProperties::enrollments({1});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {1});
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_DIVERSE_POSES, true);
|
||||
@@ -335,7 +338,7 @@ TEST_F(FakeFaceEngineTest, SetMultipleFeatures) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, SetMultipleFeaturesAndTurnOffSome) {
|
||||
FaceHalProperties::enrollments({1});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {1});
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_DIVERSE_POSES, true);
|
||||
@@ -352,7 +355,7 @@ TEST_F(FakeFaceEngineTest, SetMultipleFeaturesAndTurnOffSome) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, Enumerate) {
|
||||
FaceHalProperties::enrollments({120, 3});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {120, 3});
|
||||
mEngine.enumerateEnrollmentsImpl(mCallback.get());
|
||||
auto enrolls = mCallback->mLastEnrollmentsEnumerated;
|
||||
ASSERT_FALSE(enrolls.empty());
|
||||
@@ -361,7 +364,7 @@ TEST_F(FakeFaceEngineTest, Enumerate) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, RemoveEnrollments) {
|
||||
FaceHalProperties::enrollments({120, 3, 100});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {120, 3, 100});
|
||||
mEngine.removeEnrollmentsImpl(mCallback.get(), {120, 100});
|
||||
mEngine.enumerateEnrollmentsImpl(mCallback.get());
|
||||
auto enrolls = mCallback->mLastEnrollmentsEnumerated;
|
||||
@@ -372,9 +375,9 @@ TEST_F(FakeFaceEngineTest, RemoveEnrollments) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, ResetLockoutWithAuth) {
|
||||
FaceHalProperties::lockout(true);
|
||||
FaceHalProperties::enrollments({33});
|
||||
FaceHalProperties::enrollment_hit(33);
|
||||
Face::cfg().set<bool>("lockout", true);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {33});
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 33);
|
||||
auto cancelFuture = mCancel.get_future();
|
||||
mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, cancelFuture);
|
||||
|
||||
@@ -382,28 +385,30 @@ TEST_F(FakeFaceEngineTest, ResetLockoutWithAuth) {
|
||||
|
||||
mEngine.resetLockoutImpl(mCallback.get(), {} /* hat */);
|
||||
ASSERT_FALSE(mCallback->mLockoutPermanent);
|
||||
FaceHalProperties::enrollment_hit(33);
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 33);
|
||||
mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, cancelFuture);
|
||||
ASSERT_EQ(33, mCallback->mLastAuthenticated);
|
||||
ASSERT_FALSE(mCallback->mAuthenticateFailed);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, LatencyDefault) {
|
||||
FaceHalProperties::operation_detect_interaction_latency({});
|
||||
ASSERT_EQ(DEFAULT_LATENCY,
|
||||
mEngine.getLatency(FaceHalProperties::operation_detect_interaction_latency()));
|
||||
Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {});
|
||||
ASSERT_EQ(DEFAULT_LATENCY, mEngine.getLatency(Face::cfg().getopt<OptIntVec>(
|
||||
"operation_detect_interaction_latency")));
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, LatencyFixed) {
|
||||
FaceHalProperties::operation_detect_interaction_latency({10});
|
||||
ASSERT_EQ(10, mEngine.getLatency(FaceHalProperties::operation_detect_interaction_latency()));
|
||||
Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {10});
|
||||
ASSERT_EQ(10, mEngine.getLatency(
|
||||
Face::cfg().getopt<OptIntVec>("operation_detect_interaction_latency")));
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, LatencyRandom) {
|
||||
FaceHalProperties::operation_detect_interaction_latency({1, 1000});
|
||||
Face::cfg().setopt<OptIntVec>("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());
|
||||
auto x = mEngine.getLatency(
|
||||
Face::cfg().getopt<OptIntVec>("operation_detect_interaction_latency"));
|
||||
ASSERT_TRUE(x >= 1 && x <= 1000);
|
||||
latencySet.insert(x);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "Face.h"
|
||||
#include "FakeLockoutTracker.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
@@ -103,19 +104,21 @@ class FakeLockoutTrackerTest : public ::testing::Test {
|
||||
static constexpr int32_t LOCKOUT_TIMED_DURATION = 100;
|
||||
|
||||
void SetUp() override {
|
||||
FaceHalProperties::lockout_timed_threshold(LOCKOUT_TIMED_THRESHOLD);
|
||||
FaceHalProperties::lockout_timed_duration(LOCKOUT_TIMED_DURATION);
|
||||
FaceHalProperties::lockout_permanent_threshold(LOCKOUT_PERMANENT_THRESHOLD);
|
||||
Face::cfg().set<std::int32_t>("lockout_timed_threshold", LOCKOUT_TIMED_THRESHOLD);
|
||||
Face::cfg().set<std::int32_t>("lockout_timed_duration", LOCKOUT_TIMED_DURATION);
|
||||
Face::cfg().set<std::int32_t>("lockout_permanent_threshold", LOCKOUT_PERMANENT_THRESHOLD);
|
||||
Face::cfg().set<bool>("lockout_enable", false);
|
||||
Face::cfg().set<bool>("lockout", false);
|
||||
mCallback = ndk::SharedRefBase::make<TestSessionCallback>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// reset to default
|
||||
FaceHalProperties::lockout_timed_threshold(5);
|
||||
FaceHalProperties::lockout_timed_duration(20);
|
||||
FaceHalProperties::lockout_permanent_threshold(10000);
|
||||
FaceHalProperties::lockout_enable(false);
|
||||
FaceHalProperties::lockout(false);
|
||||
Face::cfg().set<std::int32_t>("lockout_timed_threshold", 5);
|
||||
Face::cfg().set<std::int32_t>("lockout_timed_duration", 20);
|
||||
Face::cfg().set<std::int32_t>("lockout_permanent_threshold", 10000);
|
||||
Face::cfg().set<bool>("lockout_enable", false);
|
||||
Face::cfg().set<bool>("lockout", false);
|
||||
}
|
||||
|
||||
FakeLockoutTracker mLockoutTracker;
|
||||
@@ -123,7 +126,7 @@ class FakeLockoutTrackerTest : public ::testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptDisable) {
|
||||
FaceHalProperties::lockout_enable(false);
|
||||
Face::cfg().set<bool>("lockout_enable", false);
|
||||
for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD + 1; i++)
|
||||
mLockoutTracker.addFailedAttempt(mCallback.get());
|
||||
ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
|
||||
@@ -131,7 +134,7 @@ TEST_F(FakeLockoutTrackerTest, addFailedAttemptDisable) {
|
||||
}
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptPermanent) {
|
||||
FaceHalProperties::lockout_enable(true);
|
||||
Face::cfg().set<bool>("lockout_enable", true);
|
||||
ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
|
||||
for (int i = 0; i < LOCKOUT_PERMANENT_THRESHOLD - 1; i++)
|
||||
mLockoutTracker.addFailedAttempt(mCallback.get());
|
||||
@@ -145,8 +148,8 @@ TEST_F(FakeLockoutTrackerTest, addFailedAttemptPermanent) {
|
||||
}
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimed) {
|
||||
FaceHalProperties::lockout_enable(true);
|
||||
FaceHalProperties::lockout_timed_enable(true);
|
||||
Face::cfg().set<bool>("lockout_enable", true);
|
||||
Face::cfg().set<bool>("lockout_timed_enable", true);
|
||||
ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
|
||||
for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++)
|
||||
mLockoutTracker.addFailedAttempt(mCallback.get());
|
||||
@@ -168,8 +171,8 @@ TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimed) {
|
||||
}
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockout_TimedThenPermanent) {
|
||||
FaceHalProperties::lockout_enable(true);
|
||||
FaceHalProperties::lockout_timed_enable(true);
|
||||
Face::cfg().set<bool>("lockout_enable", true);
|
||||
Face::cfg().set<bool>("lockout_timed_enable", true);
|
||||
ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
|
||||
for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++)
|
||||
mLockoutTracker.addFailedAttempt(mCallback.get());
|
||||
@@ -182,8 +185,8 @@ TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockout_TimedThenPermanent) {
|
||||
}
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimedTwice) {
|
||||
FaceHalProperties::lockout_enable(true);
|
||||
FaceHalProperties::lockout_timed_enable(true);
|
||||
Face::cfg().set<bool>("lockout_enable", true);
|
||||
Face::cfg().set<bool>("lockout_timed_enable", true);
|
||||
ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
|
||||
ASSERT_EQ(0, mCallback->mLockoutTimed);
|
||||
for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++)
|
||||
@@ -198,7 +201,7 @@ TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimedTwice) {
|
||||
}
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, resetLockout) {
|
||||
FaceHalProperties::lockout_enable(true);
|
||||
Face::cfg().set<bool>("lockout_enable", true);
|
||||
ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
|
||||
for (int i = 0; i < LOCKOUT_PERMANENT_THRESHOLD; i++)
|
||||
mLockoutTracker.addFailedAttempt(mCallback.get());
|
||||
|
||||
237
biometrics/face/aidl/default/tests/VirtualHalTest.cpp
Normal file
237
biometrics/face/aidl/default/tests/VirtualHalTest.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 <face.sysprop.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "Face.h"
|
||||
#include "VirtualHal.h"
|
||||
|
||||
using namespace ::android::face::virt;
|
||||
using namespace ::aidl::android::hardware::biometrics::face;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
|
||||
class VirtualHalTest : public ::testing::Test {
|
||||
public:
|
||||
static const int32_t STATUS_FAILED_TO_SET_PARAMETER = 2;
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
mHal = ndk::SharedRefBase::make<Face>();
|
||||
mVhal = ndk::SharedRefBase::make<VirtualHal>(mHal);
|
||||
ASSERT_TRUE(mVhal != nullptr);
|
||||
mHal->resetConfigToDefault();
|
||||
}
|
||||
|
||||
void TearDown() override { mHal->resetConfigToDefault(); }
|
||||
|
||||
std::shared_ptr<VirtualHal> mVhal;
|
||||
|
||||
ndk::ScopedAStatus validateNonNegativeInputOfInt32(const char* name,
|
||||
ndk::ScopedAStatus (VirtualHal::*f)(int32_t),
|
||||
const std::vector<int32_t>& in_good);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Face> mHal;
|
||||
};
|
||||
|
||||
ndk::ScopedAStatus VirtualHalTest::validateNonNegativeInputOfInt32(
|
||||
const char* name, ndk::ScopedAStatus (VirtualHal::*f)(int32_t),
|
||||
const std::vector<int32_t>& in_params_good) {
|
||||
ndk::ScopedAStatus status;
|
||||
for (auto& param : in_params_good) {
|
||||
status = (*mVhal.*f)(param);
|
||||
if (!status.isOk()) return status;
|
||||
if (Face::cfg().get<int32_t>(name) != param) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER,
|
||||
"Error: fail to set non-negative parameter"));
|
||||
}
|
||||
}
|
||||
|
||||
int32_t old_param = Face::cfg().get<int32_t>(name);
|
||||
status = (*mVhal.*f)(-1);
|
||||
if (status.isOk()) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER, "Error: should return NOK"));
|
||||
}
|
||||
if (status.getServiceSpecificError() != IVirtualHal::STATUS_INVALID_PARAMETER) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER,
|
||||
"Error: unexpected return error code"));
|
||||
}
|
||||
if (Face::cfg().get<int32_t>(name) != old_param) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER,
|
||||
"Error: unexpected parameter change on failed attempt"));
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, init) {
|
||||
mVhal->setLockout(false);
|
||||
ASSERT_TRUE(Face::cfg().get<bool>("lockout") == false);
|
||||
ASSERT_TRUE(Face::cfg().get<std::string>("type") == "rgb");
|
||||
ASSERT_TRUE(Face::cfg().get<std::string>("strength") == "strong");
|
||||
std::int64_t id = Face::cfg().get<std::int64_t>("authenticator_id");
|
||||
ASSERT_TRUE(Face::cfg().get<std::int64_t>("authenticator_id") == 0);
|
||||
ASSERT_TRUE(Face::cfg().getopt<OptIntVec>("enrollments") == OptIntVec());
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, enrollment_hit_int32) {
|
||||
mVhal->setEnrollmentHit(11);
|
||||
ASSERT_TRUE(Face::cfg().get<int32_t>("enrollment_hit") == 11);
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, next_enrollment) {
|
||||
struct {
|
||||
std::string nextEnrollmentStr;
|
||||
face::NextEnrollment nextEnrollment;
|
||||
} testData[] = {
|
||||
{"1:20:true", {1, {{20}}, true}},
|
||||
{"1:50,60,70:true", {1, {{50}, {60}, {70}}, true}},
|
||||
{"2:50-[21],60,70-[4,1002,1]:false",
|
||||
{2,
|
||||
{{50, {{AcquiredInfo::START}}},
|
||||
{60},
|
||||
{70, {{AcquiredInfo::TOO_DARK}, {1002}, {AcquiredInfo::GOOD}}}},
|
||||
false}},
|
||||
};
|
||||
|
||||
for (auto& d : testData) {
|
||||
mVhal->setNextEnrollment(d.nextEnrollment);
|
||||
ASSERT_TRUE(Face::cfg().get<std::string>("next_enrollment") == d.nextEnrollmentStr);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, authenticator_id_int64) {
|
||||
mVhal->setAuthenticatorId(12345678900);
|
||||
ASSERT_TRUE(Face::cfg().get<int64_t>("authenticator_id") == 12345678900);
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, opeationAuthenticateFails_bool) {
|
||||
mVhal->setOperationAuthenticateFails(true);
|
||||
ASSERT_TRUE(Face::cfg().get<bool>("operation_authenticate_fails"));
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, operationAuthenticateAcquired_int32_vector) {
|
||||
using Tag = AcquiredInfoAndVendorCode::Tag;
|
||||
std::vector<AcquiredInfoAndVendorCode> ac{
|
||||
{AcquiredInfo::START}, {AcquiredInfo::TOO_FAR}, {1023}};
|
||||
mVhal->setOperationAuthenticateAcquired(ac);
|
||||
OptIntVec ac_get = Face::cfg().getopt<OptIntVec>("operation_authenticate_acquired");
|
||||
ASSERT_TRUE(ac_get.size() == ac.size());
|
||||
for (int i = 0; i < ac.size(); i++) {
|
||||
int acCode = (ac[i].getTag() == Tag::acquiredInfo) ? (int)ac[i].get<Tag::acquiredInfo>()
|
||||
: ac[i].get<Tag::vendorCode>();
|
||||
ASSERT_TRUE(acCode == ac_get[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, type) {
|
||||
struct {
|
||||
FaceSensorType type;
|
||||
const char* typeStr;
|
||||
} typeMap[] = {{FaceSensorType::RGB, "rgb"},
|
||||
{FaceSensorType::IR, "ir"},
|
||||
{FaceSensorType::UNKNOWN, "unknown"}};
|
||||
for (auto const& x : typeMap) {
|
||||
mVhal->setType(x.type);
|
||||
ASSERT_TRUE(Face::cfg().get<std::string>("type") == x.typeStr);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, sensorStrength) {
|
||||
struct {
|
||||
common::SensorStrength strength;
|
||||
const char* strengthStr;
|
||||
} strengths[] = {{common::SensorStrength::CONVENIENCE, "CONVENIENCE"},
|
||||
{common::SensorStrength::WEAK, "WEAK"},
|
||||
{common::SensorStrength::STRONG, "STRONG"}};
|
||||
|
||||
for (auto const& x : strengths) {
|
||||
mVhal->setSensorStrength(x.strength);
|
||||
ASSERT_TRUE(Face::cfg().get<std::string>("strength") == x.strengthStr);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, setLatency) {
|
||||
ndk::ScopedAStatus status;
|
||||
std::vector<int32_t> in_lats[] = {{1}, {2, 3}, {5, 4}};
|
||||
for (auto const& in_lat : in_lats) {
|
||||
status = mVhal->setOperationAuthenticateLatency(in_lat);
|
||||
ASSERT_TRUE(status.isOk());
|
||||
OptIntVec out_lat = Face::cfg().getopt<OptIntVec>("operation_authenticate_latency");
|
||||
ASSERT_TRUE(in_lat.size() == out_lat.size());
|
||||
for (int i = 0; i < in_lat.size(); i++) {
|
||||
ASSERT_TRUE(in_lat[i] == out_lat[i]);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int32_t> bad_in_lats[] = {{}, {1, 2, 3}, {1, -3}};
|
||||
for (auto const& in_lat : bad_in_lats) {
|
||||
status = mVhal->setOperationAuthenticateLatency(in_lat);
|
||||
ASSERT_TRUE(!status.isOk());
|
||||
ASSERT_TRUE(status.getServiceSpecificError() == IVirtualHal::STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, setOperationAuthenticateDuration) {
|
||||
ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
|
||||
"operation_authenticate_duration", &IVirtualHal::setOperationAuthenticateDuration,
|
||||
{0, 33});
|
||||
ASSERT_TRUE(status.isOk());
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, setLockoutTimedDuration) {
|
||||
ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
|
||||
"lockout_timed_duration", &IVirtualHal::setLockoutTimedDuration, {0, 35});
|
||||
ASSERT_TRUE(status.isOk());
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, setLockoutTimedThreshold) {
|
||||
ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
|
||||
"lockout_timed_threshold", &IVirtualHal::setLockoutTimedThreshold, {0, 36});
|
||||
ASSERT_TRUE(status.isOk());
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, setLockoutPermanentThreshold) {
|
||||
ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
|
||||
"lockout_permanent_threshold", &IVirtualHal::setLockoutPermanentThreshold, {0, 37});
|
||||
ASSERT_TRUE(status.isOk());
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, setOthers) {
|
||||
// Verify that there is no CHECK() failures
|
||||
mVhal->setEnrollments({7, 6, 5});
|
||||
mVhal->setChallenge(111222333444555666);
|
||||
mVhal->setOperationAuthenticateError(4);
|
||||
mVhal->setOperationEnrollLatency({4, 5});
|
||||
mVhal->setLockout(false);
|
||||
mVhal->setLockoutEnable(false);
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::face
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
ABinderProcess_startThreadPool();
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -11,7 +11,7 @@ aidl_interface {
|
||||
name: "android.hardware.biometrics.fingerprint",
|
||||
vendor_available: true,
|
||||
srcs: [
|
||||
"android/hardware/biometrics/fingerprint/**/*.aidl",
|
||||
"android/hardware/biometrics/fingerprint/*.aidl",
|
||||
],
|
||||
imports: [
|
||||
"android.hardware.biometrics.common-V4",
|
||||
@@ -25,6 +25,12 @@ aidl_interface {
|
||||
cpp: {
|
||||
enabled: false,
|
||||
},
|
||||
ndk: {
|
||||
apex_available: [
|
||||
"//apex_available:platform",
|
||||
"//apex_available:anyapex",
|
||||
],
|
||||
},
|
||||
rust: {
|
||||
enabled: true,
|
||||
},
|
||||
@@ -60,5 +66,34 @@ aidl_interface {
|
||||
},
|
||||
|
||||
],
|
||||
frozen: true,
|
||||
}
|
||||
|
||||
aidl_interface {
|
||||
name: "android.hardware.biometrics.fingerprint.virtualhal",
|
||||
srcs: [
|
||||
"android/hardware/biometrics/fingerprint/virtualhal/*.aidl",
|
||||
],
|
||||
imports: [
|
||||
"android.hardware.biometrics.common-V4",
|
||||
"android.hardware.keymaster-V4",
|
||||
"android.hardware.biometrics.fingerprint-V4",
|
||||
],
|
||||
vendor_available: true,
|
||||
unstable: true,
|
||||
backend: {
|
||||
java: {
|
||||
platform_apis: true,
|
||||
},
|
||||
cpp: {
|
||||
enabled: false,
|
||||
},
|
||||
ndk: {
|
||||
apex_available: [
|
||||
"com.android.hardware.biometrics.fingerprint.virtual",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
},
|
||||
},
|
||||
frozen: false,
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.biometrics.fingerprint;
|
||||
/* @hide */
|
||||
@VintfStability
|
||||
interface IVirtualHal {
|
||||
oneway void setEnrollments(in int[] id);
|
||||
oneway void setEnrollmentHit(in int hit_id);
|
||||
oneway void setNextEnrollment(in android.hardware.biometrics.fingerprint.NextEnrollment next_enrollment);
|
||||
oneway void setAuthenticatorId(in long id);
|
||||
oneway void setChallenge(in long challenge);
|
||||
oneway void setOperationAuthenticateFails(in boolean fail);
|
||||
oneway void setOperationAuthenticateLatency(in int[] latencyMs);
|
||||
oneway void setOperationAuthenticateDuration(in int durationMs);
|
||||
oneway void setOperationAuthenticateError(in int error);
|
||||
oneway void setOperationAuthenticateAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquired);
|
||||
oneway void setOperationEnrollError(in int error);
|
||||
oneway void setOperationEnrollLatency(in int[] latencyMs);
|
||||
oneway void setOperationDetectInteractionLatency(in int[] latencyMs);
|
||||
oneway void setOperationDetectInteractionError(in int error);
|
||||
oneway void setOperationDetectInteractionDuration(in int durationMs);
|
||||
oneway void setOperationDetectInteractionAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquired);
|
||||
oneway void setLockout(in boolean lockout);
|
||||
oneway void setLockoutEnable(in boolean enable);
|
||||
oneway void setLockoutTimedThreshold(in int threshold);
|
||||
oneway void setLockoutTimedDuration(in int durationMs);
|
||||
oneway void setLockoutPermanentThreshold(in int threshold);
|
||||
oneway void resetConfigurations();
|
||||
oneway void setType(in android.hardware.biometrics.fingerprint.FingerprintSensorType type);
|
||||
oneway void setSensorId(in int id);
|
||||
oneway void setSensorStrength(in android.hardware.biometrics.common.SensorStrength strength);
|
||||
oneway void setMaxEnrollmentPerUser(in int max);
|
||||
oneway void setSensorLocation(in android.hardware.biometrics.fingerprint.SensorLocation loc);
|
||||
oneway void setNavigationGuesture(in boolean v);
|
||||
oneway void setDetectInteraction(in boolean v);
|
||||
oneway void setDisplayTouch(in boolean v);
|
||||
oneway void setControlIllumination(in boolean v);
|
||||
const int STATUS_INVALID_PARAMETER = 1;
|
||||
}
|
||||
@@ -14,14 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.hardware.biometrics.fingerprint;
|
||||
package android.hardware.biometrics.fingerprint.virtualhal;
|
||||
|
||||
import android.hardware.biometrics.fingerprint.AcquiredInfo;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@VintfStability
|
||||
union AcquiredInfoAndVendorCode {
|
||||
/**
|
||||
* Acquired info as specified in AcqauiredInfo.aidl
|
||||
@@ -14,14 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.hardware.biometrics.fingerprint;
|
||||
package android.hardware.biometrics.fingerprint.virtualhal;
|
||||
|
||||
import android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode;
|
||||
import android.hardware.biometrics.fingerprint.virtualhal.AcquiredInfoAndVendorCode;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@VintfStability
|
||||
parcelable EnrollmentProgressStep {
|
||||
/**
|
||||
* The duration of the enrollment step in milli-seconds
|
||||
@@ -14,19 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.hardware.biometrics.fingerprint;
|
||||
package android.hardware.biometrics.fingerprint.virtualhal;
|
||||
|
||||
import android.hardware.biometrics.common.SensorStrength;
|
||||
import android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode;
|
||||
import android.hardware.biometrics.fingerprint.FingerprintSensorType;
|
||||
import android.hardware.biometrics.fingerprint.NextEnrollment;
|
||||
import android.hardware.biometrics.fingerprint.IFingerprint;
|
||||
import android.hardware.biometrics.fingerprint.SensorLocation;
|
||||
import android.hardware.biometrics.fingerprint.virtualhal.AcquiredInfoAndVendorCode;
|
||||
import android.hardware.biometrics.fingerprint.virtualhal.NextEnrollment;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@VintfStability
|
||||
oneway interface IVirtualHal {
|
||||
interface IVirtualHal {
|
||||
/**
|
||||
* The operation failed due to invalid input parameters, the error messages should
|
||||
* gives more details
|
||||
@@ -315,4 +315,5 @@ oneway interface IVirtualHal {
|
||||
void setDetectInteraction(in boolean v);
|
||||
void setDisplayTouch(in boolean v);
|
||||
void setControlIllumination(in boolean v);
|
||||
IFingerprint getFingerprintHal();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
package android.hardware.biometrics.fingerprint.virtualhal;
|
||||
|
||||
import android.hardware.biometrics.fingerprint.virtualhal.EnrollmentProgressStep;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
parcelable NextEnrollment {
|
||||
/**
|
||||
* Identifier of the next enrollment if successful
|
||||
*/
|
||||
int id;
|
||||
|
||||
/**
|
||||
* Specification of the progress steps of the next enrollment, each step consists of duration
|
||||
* and sequence of acquired info codes to be generated by HAL.
|
||||
* See EnrollmentProgressStep.aidl for more details
|
||||
*/
|
||||
EnrollmentProgressStep[] progressSteps;
|
||||
|
||||
/**
|
||||
* Success or failure of the next enrollment
|
||||
*/
|
||||
boolean result = true;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
The aidl files in this directory are used only by fingerprint virtual hal
|
||||
which is controlled/configured via IVirtualHal interface
|
||||
@@ -8,10 +8,9 @@ package {
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.biometrics.fingerprint-service.example",
|
||||
vendor: true,
|
||||
relative_install_path: "hw",
|
||||
cc_library_static {
|
||||
name: "android.hardware.biometrics.fingerprint-service.lib",
|
||||
vendor_available: true,
|
||||
local_include_dirs: ["include"],
|
||||
srcs: [
|
||||
"FakeLockoutTracker.cpp",
|
||||
@@ -30,22 +29,80 @@ cc_binary {
|
||||
"libbinder_ndk",
|
||||
"liblog",
|
||||
],
|
||||
static_libs: [
|
||||
whole_static_libs: [
|
||||
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
|
||||
"libbase",
|
||||
"android.hardware.biometrics.fingerprint-V5-ndk",
|
||||
"android.hardware.biometrics.fingerprint.virtualhal-ndk",
|
||||
"android.hardware.biometrics.fingerprint-V4-ndk",
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
"android.hardware.biometrics.common.util",
|
||||
"android.hardware.biometrics.common.config",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
],
|
||||
product_variables: {
|
||||
debuggable: {
|
||||
cflags: ["-DFPS_DEBUGGABLE"],
|
||||
},
|
||||
},
|
||||
apex_available: [
|
||||
"com.android.hardware.biometrics.fingerprint.virtual",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.biometrics.fingerprint-service.example",
|
||||
system_ext_specific: true,
|
||||
relative_install_path: "hw",
|
||||
local_include_dirs: ["include"],
|
||||
srcs: [
|
||||
],
|
||||
stl: "c++_static",
|
||||
shared_libs: [
|
||||
"libbinder_ndk",
|
||||
"liblog",
|
||||
],
|
||||
whole_static_libs: [
|
||||
"android.hardware.biometrics.fingerprint-service.lib",
|
||||
],
|
||||
installable: false, // install APEX instead
|
||||
product_variables: {
|
||||
debuggable: {
|
||||
cflags: ["-DFPS_DEBUGGABLE"],
|
||||
},
|
||||
},
|
||||
apex_available: [
|
||||
"com.android.hardware.biometrics.fingerprint.virtual",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.biometrics.fingerprint-service.default",
|
||||
//system_ext_specific: true,
|
||||
vendor: true,
|
||||
relative_install_path: "hw",
|
||||
init_rc: ["fingerprint-default.rc"],
|
||||
vintf_fragments: ["fingerprint-default.xml"],
|
||||
local_include_dirs: ["include"],
|
||||
srcs: [
|
||||
],
|
||||
stl: "c++_static",
|
||||
shared_libs: [
|
||||
"libbinder_ndk",
|
||||
"liblog",
|
||||
],
|
||||
whole_static_libs: [
|
||||
"android.hardware.biometrics.fingerprint-service.lib",
|
||||
],
|
||||
product_variables: {
|
||||
debuggable: {
|
||||
cflags: ["-DFPS_DEBUGGABLE"],
|
||||
},
|
||||
},
|
||||
apex_available: [
|
||||
"//apex_available:platform",
|
||||
],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
@@ -63,14 +120,13 @@ cc_test {
|
||||
],
|
||||
static_libs: [
|
||||
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
|
||||
"android.hardware.biometrics.fingerprint-V5-ndk",
|
||||
"android.hardware.biometrics.fingerprint-V4-ndk",
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
"android.hardware.biometrics.common.util",
|
||||
"android.hardware.biometrics.common.config",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
],
|
||||
vendor: true,
|
||||
test_suites: ["general-tests"],
|
||||
require_root: true,
|
||||
}
|
||||
@@ -91,14 +147,13 @@ cc_test {
|
||||
],
|
||||
static_libs: [
|
||||
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
|
||||
"android.hardware.biometrics.fingerprint-V5-ndk",
|
||||
"android.hardware.biometrics.fingerprint-V4-ndk",
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
"android.hardware.biometrics.common.util",
|
||||
"android.hardware.biometrics.common.config",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
],
|
||||
vendor: true,
|
||||
test_suites: ["general-tests"],
|
||||
require_root: true,
|
||||
}
|
||||
@@ -117,14 +172,13 @@ cc_test {
|
||||
],
|
||||
static_libs: [
|
||||
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
|
||||
"android.hardware.biometrics.fingerprint-V5-ndk",
|
||||
"android.hardware.biometrics.fingerprint-V4-ndk",
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
"android.hardware.biometrics.common.util",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
"android.hardware.biometrics.common.config",
|
||||
],
|
||||
vendor: true,
|
||||
test_suites: ["general-tests"],
|
||||
require_root: true,
|
||||
}
|
||||
@@ -145,14 +199,13 @@ cc_test {
|
||||
],
|
||||
static_libs: [
|
||||
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
|
||||
"android.hardware.biometrics.fingerprint-V5-ndk",
|
||||
"android.hardware.biometrics.fingerprint-V4-ndk",
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
"android.hardware.biometrics.common.util",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
"android.hardware.biometrics.common.config",
|
||||
],
|
||||
vendor: true,
|
||||
test_suites: ["general-tests"],
|
||||
require_root: true,
|
||||
}
|
||||
@@ -178,7 +231,8 @@ cc_test {
|
||||
],
|
||||
static_libs: [
|
||||
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
|
||||
"android.hardware.biometrics.fingerprint-V5-ndk",
|
||||
"android.hardware.biometrics.fingerprint-V4-ndk",
|
||||
"android.hardware.biometrics.fingerprint.virtualhal-ndk",
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
"android.hardware.biometrics.common.util",
|
||||
@@ -190,7 +244,6 @@ cc_test {
|
||||
cflags: ["-DFPS_DEBUGGABLE"],
|
||||
},
|
||||
},
|
||||
vendor: true,
|
||||
test_suites: ["general-tests"],
|
||||
require_root: true,
|
||||
}
|
||||
@@ -198,39 +251,34 @@ cc_test {
|
||||
sysprop_library {
|
||||
name: "android.hardware.biometrics.fingerprint.VirtualProps",
|
||||
srcs: ["fingerprint.sysprop"],
|
||||
property_owner: "Vendor",
|
||||
vendor: true,
|
||||
property_owner: "Platform",
|
||||
vendor_available: true,
|
||||
apex_available: [
|
||||
"com.android.hardware.biometrics.fingerprint.virtual",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
name: "fingerprint-example.rc",
|
||||
src: "fingerprint-example.rc",
|
||||
installable: false,
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
name: "fingerprint-example.xml",
|
||||
src: "fingerprint-example.xml",
|
||||
sub_dir: "vintf",
|
||||
name: "fingerprint-virtual.rc",
|
||||
src: "fingerprint-virtual.rc",
|
||||
installable: false,
|
||||
}
|
||||
|
||||
apex {
|
||||
name: "com.android.hardware.biometrics.fingerprint.virtual",
|
||||
manifest: "apex_manifest.json",
|
||||
file_contexts: "apex_file_contexts",
|
||||
file_contexts: ":com.android.biometrics.virtual.fingerprint-file_contexts",
|
||||
key: "com.android.hardware.key",
|
||||
certificate: ":com.android.hardware.certificate",
|
||||
updatable: false,
|
||||
vendor: true,
|
||||
system_ext_specific: true,
|
||||
|
||||
binaries: [
|
||||
"android.hardware.biometrics.fingerprint-service.example",
|
||||
],
|
||||
prebuilts: [
|
||||
// init_rc
|
||||
"fingerprint-example.rc",
|
||||
// vintf_fragment
|
||||
"fingerprint-example.xml",
|
||||
"fingerprint-virtual.rc",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -389,10 +389,10 @@ void FakeFingerprintEngine::resetLockoutImpl(ISessionCallback* cb,
|
||||
if (isLockoutTimerStarted) isLockoutTimerAborted = true;
|
||||
}
|
||||
|
||||
void FakeFingerprintEngine::clearLockout(ISessionCallback* cb) {
|
||||
void FakeFingerprintEngine::clearLockout(ISessionCallback* cb, bool dueToTimeout) {
|
||||
Fingerprint::cfg().set<bool>("lockout", false);
|
||||
cb->onLockoutCleared();
|
||||
mLockoutTracker.reset();
|
||||
mLockoutTracker.reset(dueToTimeout);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus FakeFingerprintEngine::onPointerDownImpl(int32_t /*pointerId*/, int32_t /*x*/,
|
||||
@@ -536,7 +536,7 @@ void FakeFingerprintEngine::startLockoutTimer(int64_t timeout, ISessionCallback*
|
||||
void FakeFingerprintEngine::lockoutTimerExpired(ISessionCallback* cb) {
|
||||
BEGIN_OP(0);
|
||||
if (!isLockoutTimerAborted) {
|
||||
clearLockout(cb);
|
||||
clearLockout(cb, true);
|
||||
}
|
||||
isLockoutTimerStarted = false;
|
||||
isLockoutTimerAborted = false;
|
||||
|
||||
@@ -23,8 +23,11 @@ using namespace ::android::fingerprint::virt;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
void FakeLockoutTracker::reset() {
|
||||
mFailedCount = 0;
|
||||
void FakeLockoutTracker::reset(bool dueToTimeout) {
|
||||
if (!dueToTimeout) {
|
||||
mFailedCount = 0;
|
||||
}
|
||||
mFailedCountTimed = 0;
|
||||
mLockoutTimedStart = 0;
|
||||
mCurrentMode = LockoutMode::kNone;
|
||||
}
|
||||
@@ -33,6 +36,7 @@ void FakeLockoutTracker::addFailedAttempt() {
|
||||
bool enabled = Fingerprint::cfg().get<bool>("lockout_enable");
|
||||
if (enabled) {
|
||||
mFailedCount++;
|
||||
mFailedCountTimed++;
|
||||
int32_t lockoutTimedThreshold =
|
||||
Fingerprint::cfg().get<std::int32_t>("lockout_timed_threshold");
|
||||
int32_t lockoutPermanetThreshold =
|
||||
@@ -40,7 +44,7 @@ void FakeLockoutTracker::addFailedAttempt() {
|
||||
if (mFailedCount >= lockoutPermanetThreshold) {
|
||||
mCurrentMode = LockoutMode::kPermanent;
|
||||
Fingerprint::cfg().set<bool>("lockout", true);
|
||||
} else if (mFailedCount >= lockoutTimedThreshold) {
|
||||
} else if (mFailedCountTimed >= lockoutTimedThreshold) {
|
||||
if (mCurrentMode == LockoutMode::kNone) {
|
||||
mCurrentMode = LockoutMode::kTimed;
|
||||
mLockoutTimedStart = Util::getSystemNanoTime();
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define LOG_TAG "FingerprintVirtualHalAidl"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
using AcquiredInfoAndVendorCode = virtualhal::AcquiredInfoAndVendorCode;
|
||||
using Tag = AcquiredInfoAndVendorCode::Tag;
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setEnrollments(const std::vector<int32_t>& enrollments) {
|
||||
@@ -41,8 +41,7 @@ using Tag = AcquiredInfoAndVendorCode::Tag;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setNextEnrollment(
|
||||
const ::aidl::android::hardware::biometrics::fingerprint::NextEnrollment& next_enrollment) {
|
||||
::ndk::ScopedAStatus VirtualHal::setNextEnrollment(const NextEnrollment& next_enrollment) {
|
||||
Fingerprint::cfg().sourcedFromAidl();
|
||||
std::ostringstream os;
|
||||
os << next_enrollment.id << ":";
|
||||
@@ -333,4 +332,10 @@ OptIntVec VirtualHal::acquiredInfoVec2OptIntVec(
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::getFingerprintHal(
|
||||
std::shared_ptr<::aidl::android::hardware::biometrics::fingerprint::IFingerprint>* pFp) {
|
||||
LOG(INFO) << " calling getFingerprintHal in VirtualHal.cpp";
|
||||
*pFp = mFp;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
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: "lockout_enable"
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout_enable"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout_permanent_threshold"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout_permanent_threshold"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout_timed_duration"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout_timed_duration"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout_timed_threshold"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout_timed_threshold"
|
||||
}
|
||||
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: IntegerList
|
||||
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: IntegerList
|
||||
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: IntegerList
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
service vendor.fingerprint-default /vendor/bin/hw/android.hardware.biometrics.fingerprint-service.default default
|
||||
class hal
|
||||
user nobody
|
||||
group nobody
|
||||
interface aidl android.hardware.biometrics.fingerprint.IFingerprint/default
|
||||
oneshot
|
||||
disabled
|
||||
@@ -1,7 +1,10 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.biometrics.fingerprint</name>
|
||||
<version>5</version>
|
||||
<fqname>IFingerprint/virtual</fqname>
|
||||
<version>4</version>
|
||||
<interface>
|
||||
<name>IFingerprint</name>
|
||||
<instance>default</instance>
|
||||
</interface>
|
||||
</hal>
|
||||
</manifest>
|
||||
@@ -1,7 +0,0 @@
|
||||
service vendor.fingerprint-example /apex/com.android.hardware.biometrics.fingerprint.virtual/bin/hw/android.hardware.biometrics.fingerprint-service.example
|
||||
class hal
|
||||
user nobody
|
||||
group nobody
|
||||
interface aidl android.hardware.biometrics.fingerprint.IFingerprint/virtual
|
||||
oneshot
|
||||
disabled
|
||||
@@ -0,0 +1,7 @@
|
||||
service fingerprint-virtual /apex/com.android.hardware.biometrics.fingerprint.virtual/bin/hw/android.hardware.biometrics.fingerprint-service.example virtual
|
||||
class hal
|
||||
user nobody
|
||||
group nobody
|
||||
interface aidl android.hardware.biometrics.fingerprint.virtualhal.IVirtualHal/virtual
|
||||
oneshot
|
||||
disabled
|
||||
@@ -7,7 +7,7 @@ owner: Vendor
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.type"
|
||||
type: String
|
||||
scope: Internal
|
||||
scope: Public
|
||||
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: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "enrollments"
|
||||
}
|
||||
@@ -27,7 +27,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.enrollment_hit"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "enrollment_hit"
|
||||
}
|
||||
@@ -42,7 +42,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.next_enrollment"
|
||||
type: String
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "next_enrollment"
|
||||
}
|
||||
@@ -51,7 +51,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.authenticator_id"
|
||||
type: Long
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "authenticator_id"
|
||||
}
|
||||
@@ -60,7 +60,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.challenge"
|
||||
type: Long
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "challenge"
|
||||
}
|
||||
@@ -69,7 +69,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_fails"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_fails"
|
||||
}
|
||||
@@ -82,7 +82,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_error"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_detect_interaction_error"
|
||||
}
|
||||
@@ -91,7 +91,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_enroll_error"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_enroll_error"
|
||||
}
|
||||
@@ -104,7 +104,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_latency"
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_latency"
|
||||
}
|
||||
@@ -114,7 +114,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_latency"
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_detect_interaction_latency"
|
||||
}
|
||||
@@ -124,7 +124,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_enroll_latency"
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_enroll_latency"
|
||||
}
|
||||
@@ -134,7 +134,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_duration"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_duration"
|
||||
}
|
||||
@@ -143,7 +143,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_error"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_error"
|
||||
}
|
||||
@@ -153,7 +153,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.sensor_location"
|
||||
type: String
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "sensor_location"
|
||||
}
|
||||
@@ -162,7 +162,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_authenticate_acquired"
|
||||
type: String
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_acquired"
|
||||
}
|
||||
@@ -172,7 +172,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_duration"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_detect_interaction_duration"
|
||||
}
|
||||
@@ -184,7 +184,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_acquired"
|
||||
type: String
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_detect_interaction_acquired"
|
||||
}
|
||||
@@ -193,7 +193,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.sensor_id"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "sensor_id"
|
||||
}
|
||||
@@ -203,7 +203,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.sensor_strength"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "sensor_strength"
|
||||
}
|
||||
@@ -213,7 +213,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.max_enrollments"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "max_enrollments"
|
||||
}
|
||||
@@ -222,7 +222,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.navigation_guesture"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "navigation_guesture"
|
||||
}
|
||||
@@ -231,7 +231,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.detect_interaction"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "detect_interaction"
|
||||
}
|
||||
@@ -240,7 +240,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.udfps.display_touch"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "display_touch"
|
||||
}
|
||||
@@ -249,7 +249,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.udfps.control_illumination"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "control_illumination"
|
||||
}
|
||||
@@ -258,7 +258,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout"
|
||||
}
|
||||
@@ -267,7 +267,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout_enable"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_enable"
|
||||
}
|
||||
@@ -276,7 +276,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout_timed_threshold"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_timed_threshold"
|
||||
}
|
||||
@@ -285,7 +285,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout_timed_duration"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_timed_duration"
|
||||
}
|
||||
@@ -294,7 +294,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.fingerprint.virtual.lockout_permanent_threshold"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_permanent_threshold"
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ class FakeFingerprintEngine {
|
||||
std::pair<Error, int32_t> convertError(int32_t code);
|
||||
int32_t getRandomInRange(int32_t bound1, int32_t bound2);
|
||||
bool checkSensorLockout(ISessionCallback*);
|
||||
void clearLockout(ISessionCallback* cb);
|
||||
void clearLockout(ISessionCallback* cb, bool dueToTimeout = false);
|
||||
void waitForFingerDown(ISessionCallback* cb, const std::future<void>& cancel);
|
||||
|
||||
FakeLockoutTracker mLockoutTracker;
|
||||
|
||||
@@ -24,12 +24,12 @@ namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
class FakeLockoutTracker {
|
||||
public:
|
||||
FakeLockoutTracker() : mFailedCount(0) {}
|
||||
FakeLockoutTracker() : mFailedCount(0), mFailedCountTimed(0) {}
|
||||
~FakeLockoutTracker() {}
|
||||
|
||||
enum class LockoutMode : int8_t { kNone = 0, kTimed, kPermanent };
|
||||
|
||||
void reset();
|
||||
void reset(bool dueToTimeout = false);
|
||||
LockoutMode getMode();
|
||||
void addFailedAttempt();
|
||||
int64_t getLockoutTimeLeft();
|
||||
@@ -44,6 +44,7 @@ class FakeLockoutTracker {
|
||||
|
||||
private:
|
||||
int32_t mFailedCount;
|
||||
int32_t mFailedCountTimed;
|
||||
int64_t mLockoutTimedStart;
|
||||
LockoutMode mCurrentMode;
|
||||
};
|
||||
|
||||
@@ -16,21 +16,21 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/biometrics/fingerprint/BnVirtualHal.h>
|
||||
#include <aidl/android/hardware/biometrics/fingerprint/virtualhal/BnVirtualHal.h>
|
||||
|
||||
#include "Fingerprint.h"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::fingerprint {
|
||||
|
||||
using namespace virtualhal;
|
||||
|
||||
class VirtualHal : public BnVirtualHal {
|
||||
public:
|
||||
VirtualHal(Fingerprint* fp) : mFp(fp) {}
|
||||
VirtualHal(std::shared_ptr<Fingerprint> fp) : mFp(fp) {}
|
||||
|
||||
::ndk::ScopedAStatus setEnrollments(const std::vector<int32_t>& in_id) override;
|
||||
::ndk::ScopedAStatus setEnrollmentHit(int32_t in_hit_id) override;
|
||||
::ndk::ScopedAStatus setNextEnrollment(
|
||||
const ::aidl::android::hardware::biometrics::fingerprint::NextEnrollment&
|
||||
in_next_enrollment) override;
|
||||
::ndk::ScopedAStatus setNextEnrollment(const NextEnrollment& in_next_enrollment) override;
|
||||
::ndk::ScopedAStatus setAuthenticatorId(int64_t in_id) override;
|
||||
::ndk::ScopedAStatus setChallenge(int64_t in_challenge) override;
|
||||
::ndk::ScopedAStatus setOperationAuthenticateFails(bool in_fail) override;
|
||||
@@ -67,12 +67,15 @@ class VirtualHal : public BnVirtualHal {
|
||||
::ndk::ScopedAStatus setDetectInteraction(bool in_v) override;
|
||||
::ndk::ScopedAStatus setDisplayTouch(bool in_v) override;
|
||||
::ndk::ScopedAStatus setControlIllumination(bool in_v) override;
|
||||
::ndk::ScopedAStatus getFingerprintHal(
|
||||
std::shared_ptr<::aidl::android::hardware::biometrics::fingerprint::IFingerprint>*
|
||||
_aidl_return);
|
||||
|
||||
private:
|
||||
OptIntVec intVec2OptIntVec(const std::vector<int32_t>& intVec);
|
||||
OptIntVec acquiredInfoVec2OptIntVec(const std::vector<AcquiredInfoAndVendorCode>& intVec);
|
||||
::ndk::ScopedAStatus sanityCheckLatency(const std::vector<int32_t>& in_latency);
|
||||
Fingerprint* mFp;
|
||||
std::shared_ptr<Fingerprint> mFp;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::fingerprint
|
||||
|
||||
@@ -24,21 +24,38 @@
|
||||
using aidl::android::hardware::biometrics::fingerprint::Fingerprint;
|
||||
using aidl::android::hardware::biometrics::fingerprint::VirtualHal;
|
||||
|
||||
int main() {
|
||||
LOG(INFO) << "Fingerprint HAL started";
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
LOG(ERROR) << "Missing argument -> exiting";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Fingerprint HAL started: " << argv[1];
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||
std::shared_ptr<Fingerprint> hal = ndk::SharedRefBase::make<Fingerprint>();
|
||||
auto binder = hal->asBinder();
|
||||
|
||||
std::shared_ptr<VirtualHal> hal_ext = ndk::SharedRefBase::make<VirtualHal>(hal.get());
|
||||
auto binder_ext = hal_ext->asBinder();
|
||||
std::shared_ptr<VirtualHal> hal_vhal = ndk::SharedRefBase::make<VirtualHal>(hal);
|
||||
|
||||
if (hal->connected()) {
|
||||
CHECK(STATUS_OK == AIBinder_setExtension(binder.get(), binder_ext.get()));
|
||||
const std::string instance = std::string(Fingerprint::descriptor) + "/virtual";
|
||||
binder_status_t status =
|
||||
AServiceManager_registerLazyService(binder.get(), instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK);
|
||||
if (strcmp(argv[1], "default") == 0) {
|
||||
const std::string instance = std::string(Fingerprint::descriptor) + "/default";
|
||||
auto binder = hal->asBinder();
|
||||
auto binder_ext = hal_vhal->asBinder();
|
||||
CHECK(STATUS_OK == AIBinder_setExtension(binder.get(), binder_ext.get()));
|
||||
binder_status_t status =
|
||||
AServiceManager_registerLazyService(binder.get(), instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK);
|
||||
LOG(INFO) << "started IFingerprint/default";
|
||||
} else if (strcmp(argv[1], "virtual") == 0) {
|
||||
const std::string instance = std::string(VirtualHal::descriptor) + "/virtual";
|
||||
auto binder = hal_vhal->asBinder();
|
||||
binder_status_t status =
|
||||
AServiceManager_registerLazyService(binder.get(), instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK);
|
||||
LOG(INFO) << "started IVirtualHal/virtual";
|
||||
} else {
|
||||
LOG(ERROR) << "Unexpected argument: " << argv[1];
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
AServiceManager_forceLazyServicesPersist(true);
|
||||
} else {
|
||||
LOG(ERROR) << "Fingerprint HAL is not connected";
|
||||
|
||||
@@ -75,7 +75,7 @@ TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimed) {
|
||||
prevTimeLeft = currTimeLeft;
|
||||
}
|
||||
ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
|
||||
mLockoutTracker.reset();
|
||||
mLockoutTracker.reset(true);
|
||||
}
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptPermanent) {
|
||||
|
||||
@@ -35,7 +35,7 @@ class VirtualHalTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
mHal = ndk::SharedRefBase::make<Fingerprint>();
|
||||
mVhal = ndk::SharedRefBase::make<VirtualHal>(mHal.get());
|
||||
mVhal = ndk::SharedRefBase::make<VirtualHal>(mHal);
|
||||
ASSERT_TRUE(mVhal != nullptr);
|
||||
mHal->resetConfigToDefault();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user