diff --git a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp index c5e2346cc9..925f9ecc86 100644 --- a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp +++ b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp @@ -32,27 +32,19 @@ using aidl::android::hardware::audio::effect::LoudnessEnhancer; 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_GAIN_MB }; -using LoudnessEnhancerParamTestParam = - std::tuple, Descriptor>, int>; +static constexpr float kMaxAudioSample = 1; +static constexpr int kZeroGain = 0; +static constexpr int kMaxGain = std::numeric_limits::max(); +static constexpr int kMinGain = std::numeric_limits::min(); +static constexpr float kAbsError = 0.0001; // Every int 32 bit value is a valid gain, so testing the corner cases and one regular value. // TODO : Update the test values once range/capability is updated by implementation. -const std::vector kGainMbValues = {std::numeric_limits::min(), 100, - std::numeric_limits::max()}; +static const std::vector kGainMbValues = {kMinGain, -100, -50, kZeroGain, 50, 100, kMaxGain}; -class LoudnessEnhancerParamTest : public ::testing::TestWithParam, - public EffectHelper { +class LoudnessEnhancerEffectHelper : public EffectHelper { public: - LoudnessEnhancerParamTest() : mParamGainMb(std::get(GetParam())) { - std::tie(mFactory, mDescriptor) = std::get(GetParam()); - } - - void SetUp() override { + void SetUpLoudnessEnhancer() { ASSERT_NE(nullptr, mFactory); ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor)); @@ -60,13 +52,14 @@ class LoudnessEnhancerParamTest : public ::testing::TestWithParam mFactory; - std::shared_ptr mEffect; - Descriptor mDescriptor; - int mParamGainMb = 0; + Parameter createLoudnessParam(int gainMb) { + LoudnessEnhancer le; + le.set(gainMb); + Parameter param; + Parameter::Specific specific; + specific.set(le); + param.set(specific); + return param; + } - void SetAndGetParameters() { - for (auto& it : mTags) { - auto& tag = it.first; - auto& le = it.second; - - // set parameter - Parameter expectParam; - Parameter::Specific specific; - specific.set(le); - expectParam.set(specific); - // All values are valid, set parameter should succeed - EXPECT_STATUS(EX_NONE, mEffect->setParameter(expectParam)) << expectParam.toString(); - - // get parameter - Parameter getParam; - Parameter::Id id; - LoudnessEnhancer::Id leId; - leId.set(tag); - id.set(leId); - EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam)); - - EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString() - << "\ngetParam:" << getParam.toString(); + binder_exception_t isGainValid(int gainMb) { + LoudnessEnhancer le; + le.set(gainMb); + if (isParameterValid(le, mDescriptor)) { + return EX_NONE; + } else { + return EX_ILLEGAL_ARGUMENT; } } - void addGainMbParam(int gainMb) { - LoudnessEnhancer le; - le.set(gainMb); - mTags.push_back({LoudnessEnhancer::gainMb, le}); + void setParameters(int gain, binder_exception_t expected) { + // set parameter + auto param = createLoudnessParam(gain); + EXPECT_STATUS(expected, mEffect->setParameter(param)) << param.toString(); } - private: - std::vector> mTags; - void CleanUp() { mTags.clear(); } + void validateParameters(int gain) { + // get parameter + LoudnessEnhancer::Id leId; + Parameter getParam; + Parameter::Id id; + + LoudnessEnhancer::Tag tag(LoudnessEnhancer::gainMb); + leId.set(tag); + id.set(leId); + EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam)); + auto expectedParam = createLoudnessParam(gain); + EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString() + << "\ngetParam:" << getParam.toString(); + } + + static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100; + IEffect::OpenEffectReturn mOpenEffectReturn; + std::shared_ptr mFactory; + std::shared_ptr mEffect; + Descriptor mDescriptor; +}; + +/** + * Here we focus on specific parameter checking, general IEffect interfaces testing performed in + * VtsAudioEffectTargetTest. + */ +enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB }; +using LoudnessEnhancerParamTestParam = + std::tuple, Descriptor>, int>; + +class LoudnessEnhancerParamTest : public ::testing::TestWithParam, + public LoudnessEnhancerEffectHelper { + public: + LoudnessEnhancerParamTest() : mParamGainMb(std::get(GetParam())) { + std::tie(mFactory, mDescriptor) = std::get(GetParam()); + } + + void SetUp() override { SetUpLoudnessEnhancer(); } + void TearDown() override { TearDownLoudnessEnhancer(); } + int mParamGainMb = 0; }; TEST_P(LoudnessEnhancerParamTest, SetAndGetGainMb) { - EXPECT_NO_FATAL_FAILURE(addGainMbParam(mParamGainMb)); - SetAndGetParameters(); + binder_exception_t expected = isGainValid(mParamGainMb); + setParameters(mParamGainMb, expected); + if (expected == EX_NONE) { + validateParameters(mParamGainMb); + } +} + +using LoudnessEnhancerDataTestParam = std::pair, Descriptor>; + +class LoudnessEnhancerDataTest : public ::testing::TestWithParam, + public LoudnessEnhancerEffectHelper { + public: + LoudnessEnhancerDataTest() { + std::tie(mFactory, mDescriptor) = GetParam(); + generateInputBuffer(); + mOutputBuffer.resize(kBufferSize); + } + + void SetUp() override { + SetUpLoudnessEnhancer(); + + // Creating AidlMessageQueues + mStatusMQ = std::make_unique(mOpenEffectReturn.statusMQ); + mInputMQ = std::make_unique(mOpenEffectReturn.inputDataMQ); + mOutputMQ = std::make_unique(mOpenEffectReturn.outputDataMQ); + } + + void TearDown() override { TearDownLoudnessEnhancer(); } + + // Fill inputBuffer with random values between -kMaxAudioSample to kMaxAudioSample + void generateInputBuffer() { + for (size_t i = 0; i < kBufferSize; i++) { + mInputBuffer.push_back(((static_cast(std::rand()) / RAND_MAX) * 2 - 1) * + kMaxAudioSample); + } + } + + // Add gains to the mInputBuffer and store processed output to mOutputBuffer + void processAndWriteToOutput() { + // Check AidlMessageQueues are not null + ASSERT_TRUE(mStatusMQ->isValid()); + ASSERT_TRUE(mInputMQ->isValid()); + ASSERT_TRUE(mOutputMQ->isValid()); + + // Enabling the process + ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START)); + ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING)); + + // Write from buffer to message queues and calling process + EXPECT_NO_FATAL_FAILURE(EffectHelper::writeToFmq(mStatusMQ, mInputMQ, mInputBuffer)); + + // Read the updated message queues into buffer + EXPECT_NO_FATAL_FAILURE(EffectHelper::readFromFmq(mStatusMQ, 1, mOutputMQ, + mOutputBuffer.size(), mOutputBuffer)); + + // Disable the process + ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP)); + } + + void assertGreaterGain(const std::vector& first, const std::vector& second) { + for (size_t i = 0; i < first.size(); i++) { + if (first[i] != 0) { + ASSERT_GT(abs(first[i]), abs(second[i])); + + } else { + ASSERT_EQ(first[i], second[i]); + } + } + } + + void assertSequentialGains(const std::vector& gainValues, bool isIncreasing) { + std::vector baseOutput(kBufferSize); + + // Process a reference output buffer with 0 gain which gives compressed input values + binder_exception_t expected; + expected = isGainValid(kZeroGain); + ASSERT_EQ(expected, EX_NONE); + setParameters(kZeroGain, expected); + ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput()); + baseOutput = mOutputBuffer; + + // Compare the outputs for increasing gain + for (int gain : gainValues) { + // Setting the parameters + binder_exception_t expected = isGainValid(gain); + if (expected != EX_NONE) { + GTEST_SKIP() << "Gains not supported."; + } + setParameters(gain, expected); + ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput()); + + // Compare the mOutputBuffer values with baseOutput and update it + if (isIncreasing) { + ASSERT_NO_FATAL_FAILURE(assertGreaterGain(mOutputBuffer, baseOutput)); + } else { + ASSERT_NO_FATAL_FAILURE(assertGreaterGain(baseOutput, mOutputBuffer)); + } + + baseOutput = mOutputBuffer; + } + } + + std::unique_ptr mStatusMQ; + std::unique_ptr mInputMQ; + std::unique_ptr mOutputMQ; + + std::vector mInputBuffer; + std::vector mOutputBuffer; + static constexpr float kBufferSize = 128; +}; + +TEST_P(LoudnessEnhancerDataTest, IncreasingGains) { + static const std::vector kIncreasingGains = {50, 100}; + + assertSequentialGains(kIncreasingGains, true /*isIncreasing*/); +} + +TEST_P(LoudnessEnhancerDataTest, DecreasingGains) { + static const std::vector kDecreasingGains = {-50, -100}; + + assertSequentialGains(kDecreasingGains, false /*isIncreasing*/); +} + +TEST_P(LoudnessEnhancerDataTest, MinimumGain) { + // Setting the parameters + binder_exception_t expected = isGainValid(kMinGain); + if (expected != EX_NONE) { + GTEST_SKIP() << "Minimum integer value not supported"; + } + setParameters(kMinGain, expected); + ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput()); + + // Validate that mOutputBuffer has 0 values for INT_MIN gain + for (size_t i = 0; i < mOutputBuffer.size(); i++) { + ASSERT_FLOAT_EQ(mOutputBuffer[i], 0); + } +} + +TEST_P(LoudnessEnhancerDataTest, MaximumGain) { + // Setting the parameters + binder_exception_t expected = isGainValid(kMaxGain); + if (expected != EX_NONE) { + GTEST_SKIP() << "Maximum integer value not supported"; + } + setParameters(kMaxGain, expected); + ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput()); + + // Validate that mOutputBuffer reaches to kMaxAudioSample for INT_MAX gain + for (size_t i = 0; i < mOutputBuffer.size(); i++) { + if (mInputBuffer[i] != 0) { + EXPECT_NEAR(kMaxAudioSample, abs(mOutputBuffer[i]), kAbsError); + } else { + ASSERT_EQ(mOutputBuffer[i], mInputBuffer[i]); + } + } } INSTANTIATE_TEST_SUITE_P( @@ -140,6 +311,20 @@ INSTANTIATE_TEST_SUITE_P( GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerParamTest); +INSTANTIATE_TEST_SUITE_P( + LoudnessEnhancerTest, LoudnessEnhancerDataTest, + testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors( + IFactory::descriptor, getEffectTypeUuidLoudnessEnhancer())), + [](const testing::TestParamInfo& info) { + auto descriptor = info.param; + std::string name = getPrefix(descriptor.second); + std::replace_if( + name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_'); + return name; + }); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerDataTest); + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());