diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING index f030af0ff3..3e06595fe1 100644 --- a/audio/aidl/TEST_MAPPING +++ b/audio/aidl/TEST_MAPPING @@ -39,6 +39,9 @@ { "name": "VtsHalAECTargetTest" }, + { + "name": "VtsHalAGC1TargetTest" + }, { "name": "VtsHalAGC2TargetTest" }, diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl index c738c2720c..0baac3dfb7 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl @@ -41,6 +41,7 @@ parcelable Descriptor { const String EFFECT_TYPE_UUID_EQUALIZER = "0bed4300-ddd6-11db-8f34-0002a5d5c51b"; const String EFFECT_TYPE_UUID_BASS_BOOST = "0634f220-ddd4-11db-a0fc-0002a5d5c51b"; const String EFFECT_TYPE_UUID_VIRTUALIZER = "37cc2c00-dddd-11db-8577-0002a5d5c51b"; + const String EFFECT_TYPE_UUID_AGC1 = "0a8abfe0-654c-11e0-ba26-0002a5d5c51b"; const String EFFECT_TYPE_UUID_AGC2 = "ae3c653b-be18-4ab8-8938-418f0a7f06ac"; const String EFFECT_TYPE_UUID_AEC = "7b491460-8d4d-11e0-bd61-0002a5d5c51b"; const String EFFECT_TYPE_UUID_NS = "58b4b260-8e06-11e0-aa8e-0002a5d5c51b"; diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl index 19b1752ff0..14aa1e8df5 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl @@ -44,6 +44,7 @@ union Parameter { union Id { int vendorEffectTag; android.hardware.audio.effect.AcousticEchoCanceler.Id acousticEchoCancelerTag; + android.hardware.audio.effect.AutomaticGainControlV1.Id automaticGainControlV1Tag; android.hardware.audio.effect.AutomaticGainControlV2.Id automaticGainControlV2Tag; android.hardware.audio.effect.BassBoost.Id bassBoostTag; android.hardware.audio.effect.Downmix.Id downmixTag; @@ -75,6 +76,7 @@ union Parameter { union Specific { android.hardware.audio.effect.VendorExtension vendorEffect; android.hardware.audio.effect.AcousticEchoCanceler acousticEchoCanceler; + android.hardware.audio.effect.AutomaticGainControlV1 automaticGainControlV1; android.hardware.audio.effect.AutomaticGainControlV2 automaticGainControlV2; android.hardware.audio.effect.BassBoost bassBoost; android.hardware.audio.effect.Downmix downmix; diff --git a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl index 9b045b41f8..01ca1c6cbe 100644 --- a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl +++ b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl @@ -56,6 +56,10 @@ parcelable Descriptor { * UUID for virtualizer effect type. */ const String EFFECT_TYPE_UUID_VIRTUALIZER = "37cc2c00-dddd-11db-8577-0002a5d5c51b"; + /** + * UUID for Automatic Gain Control V1 (AGC1) type. + */ + const String EFFECT_TYPE_UUID_AGC1 = "0a8abfe0-654c-11e0-ba26-0002a5d5c51b"; /** * UUID for Automatic Gain Control V2 (AGC2) type. */ diff --git a/audio/aidl/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/android/hardware/audio/effect/Parameter.aidl index 1d23221c9b..9f8874bc02 100644 --- a/audio/aidl/android/hardware/audio/effect/Parameter.aidl +++ b/audio/aidl/android/hardware/audio/effect/Parameter.aidl @@ -17,6 +17,7 @@ package android.hardware.audio.effect; import android.hardware.audio.effect.AcousticEchoCanceler; +import android.hardware.audio.effect.AutomaticGainControlV1; import android.hardware.audio.effect.AutomaticGainControlV2; import android.hardware.audio.effect.BassBoost; import android.hardware.audio.effect.Downmix; @@ -83,6 +84,7 @@ union Parameter { * */ AcousticEchoCanceler.Id acousticEchoCancelerTag; + AutomaticGainControlV1.Id automaticGainControlV1Tag; AutomaticGainControlV2.Id automaticGainControlV2Tag; BassBoost.Id bassBoostTag; Downmix.Id downmixTag; @@ -165,6 +167,7 @@ union Parameter { union Specific { VendorExtension vendorEffect; AcousticEchoCanceler acousticEchoCanceler; + AutomaticGainControlV1 automaticGainControlV1; AutomaticGainControlV2 automaticGainControlV2; BassBoost bassBoost; Downmix downmix; diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml index 14995d70fb..67855397a4 100644 --- a/audio/aidl/default/audio_effects_config.xml +++ b/audio/aidl/default/audio_effects_config.xml @@ -29,6 +29,7 @@ --> + @@ -67,6 +68,7 @@ + diff --git a/audio/aidl/default/automaticGainControlV1/Android.bp b/audio/aidl/default/automaticGainControlV1/Android.bp new file mode 100644 index 0000000000..4ae8e63709 --- /dev/null +++ b/audio/aidl/default/automaticGainControlV1/Android.bp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2023 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_shared { + name: "libagc1sw", + defaults: [ + "aidlaudioeffectservice_defaults", + "latest_android_media_audio_common_types_ndk_shared", + "latest_android_hardware_audio_effect_ndk_shared", + ], + srcs: [ + "AutomaticGainControlV1Sw.cpp", + ":effectCommonFile", + ], + relative_install_path: "soundfx", + visibility: [ + "//hardware/interfaces/audio/aidl/default", + ], +} diff --git a/audio/aidl/default/automaticGainControlV1/AutomaticGainControlV1Sw.cpp b/audio/aidl/default/automaticGainControlV1/AutomaticGainControlV1Sw.cpp new file mode 100644 index 0000000000..39290b4792 --- /dev/null +++ b/audio/aidl/default/automaticGainControlV1/AutomaticGainControlV1Sw.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2023 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 "AHAL_AutomaticGainControlV1Sw" + +#include + +#include "AutomaticGainControlV1Sw.h" + +using aidl::android::hardware::audio::effect::AutomaticGainControlV1Sw; +using aidl::android::hardware::audio::effect::Descriptor; +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::kAutomaticGainControlV1SwImplUUID; +using aidl::android::media::audio::common::AudioUuid; + +extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid, + std::shared_ptr* instanceSpp) { + if (!in_impl_uuid || *in_impl_uuid != kAutomaticGainControlV1SwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + if (instanceSpp) { + *instanceSpp = ndk::SharedRefBase::make(); + LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created"; + return EX_NONE; + } else { + LOG(ERROR) << __func__ << " invalid input parameter!"; + return EX_ILLEGAL_ARGUMENT; + } +} + +extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) { + if (!in_impl_uuid || *in_impl_uuid != kAutomaticGainControlV1SwImplUUID) { + LOG(ERROR) << __func__ << "uuid not supported"; + return EX_ILLEGAL_ARGUMENT; + } + *_aidl_return = AutomaticGainControlV1Sw::kDescriptor; + return EX_NONE; +} + +namespace aidl::android::hardware::audio::effect { + +const std::string AutomaticGainControlV1Sw::kEffectName = "AutomaticGainControlV1Sw"; + +const std::vector AutomaticGainControlV1Sw::kRanges = { + MAKE_RANGE(AutomaticGainControlV1, targetPeakLevelDbFs, -3100, 0), + MAKE_RANGE(AutomaticGainControlV1, maxCompressionGainDb, 0, 9000)}; + +const Capability AutomaticGainControlV1Sw::kCapability = { + .range = AutomaticGainControlV1Sw::kRanges}; + +const Descriptor AutomaticGainControlV1Sw::kDescriptor = { + .common = {.id = {.type = kAutomaticGainControlV1TypeUUID, + .uuid = kAutomaticGainControlV1SwImplUUID, + .proxy = std::nullopt}, + .flags = {.type = Flags::Type::INSERT, + .insert = Flags::Insert::FIRST, + .volume = Flags::Volume::CTRL}, + .name = AutomaticGainControlV1Sw::kEffectName, + .implementor = "The Android Open Source Project"}, + .capability = AutomaticGainControlV1Sw::kCapability}; + +ndk::ScopedAStatus AutomaticGainControlV1Sw::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << kDescriptor.toString(); + *_aidl_return = kDescriptor; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus AutomaticGainControlV1Sw::setParameterSpecific( + const Parameter::Specific& specific) { + RETURN_IF(Parameter::Specific::automaticGainControlV1 != specific.getTag(), EX_ILLEGAL_ARGUMENT, + "EffectNotSupported"); + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + auto& param = specific.get(); + RETURN_IF(!inRange(param, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange"); + auto tag = param.getTag(); + switch (tag) { + case AutomaticGainControlV1::targetPeakLevelDbFs: { + RETURN_IF(mContext->setTargetPeakLevel( + param.get()) != + RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "targetPeakLevelNotSupported"); + return ndk::ScopedAStatus::ok(); + } + case AutomaticGainControlV1::maxCompressionGainDb: { + RETURN_IF(mContext->setMaxCompressionGain( + param.get()) != + RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "maxCompressionGainNotSupported"); + return ndk::ScopedAStatus::ok(); + } + case AutomaticGainControlV1::enableLimiter: { + RETURN_IF( + mContext->setEnableLimiter( + param.get()) != RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "enableLimiterNotSupported"); + return ndk::ScopedAStatus::ok(); + } + default: { + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV1TagNotSupported"); + } + } +} + +ndk::ScopedAStatus AutomaticGainControlV1Sw::getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) { + auto tag = id.getTag(); + RETURN_IF(Parameter::Id::automaticGainControlV1Tag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); + auto specificId = id.get(); + auto specificIdTag = specificId.getTag(); + switch (specificIdTag) { + case AutomaticGainControlV1::Id::commonTag: + return getParameterAutomaticGainControlV1( + specificId.get(), specific); + default: + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV1TagNotSupported"); + } +} + +ndk::ScopedAStatus AutomaticGainControlV1Sw::getParameterAutomaticGainControlV1( + const AutomaticGainControlV1::Tag& tag, Parameter::Specific* specific) { + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + AutomaticGainControlV1 param; + switch (tag) { + case AutomaticGainControlV1::targetPeakLevelDbFs: { + param.set(mContext->getTargetPeakLevel()); + break; + } + case AutomaticGainControlV1::maxCompressionGainDb: { + param.set( + mContext->getMaxCompressionGain()); + break; + } + case AutomaticGainControlV1::enableLimiter: { + param.set(mContext->getEnableLimiter()); + break; + } + default: { + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV1TagNotSupported"); + } + } + + specific->set(param); + return ndk::ScopedAStatus::ok(); +} + +std::shared_ptr AutomaticGainControlV1Sw::createContext( + const Parameter::Common& common) { + if (mContext) { + LOG(DEBUG) << __func__ << " context already exist"; + } else { + mContext = + std::make_shared(1 /* statusFmqDepth */, common); + } + return mContext; +} + +std::shared_ptr AutomaticGainControlV1Sw::getContext() { + return mContext; +} + +RetCode AutomaticGainControlV1Sw::releaseContext() { + if (mContext) { + mContext.reset(); + } + return RetCode::SUCCESS; +} + +// Processing method running in EffectWorker thread. +IEffect::Status AutomaticGainControlV1Sw::effectProcessImpl(float* in, float* out, int samples) { + // TODO: get data buffer and process. + LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples; + for (int i = 0; i < samples; i++) { + *out++ = *in++; + } + return {STATUS_OK, samples, samples}; +} + +RetCode AutomaticGainControlV1SwContext::setTargetPeakLevel(int targetPeakLevel) { + mTargetPeakLevel = targetPeakLevel; + return RetCode::SUCCESS; +} + +int AutomaticGainControlV1SwContext::getTargetPeakLevel() { + return mTargetPeakLevel; +} + +RetCode AutomaticGainControlV1SwContext::setMaxCompressionGain(int maxCompressionGain) { + mMaxCompressionGain = maxCompressionGain; + return RetCode::SUCCESS; +} + +int AutomaticGainControlV1SwContext::getMaxCompressionGain() { + return mMaxCompressionGain; +} + +RetCode AutomaticGainControlV1SwContext::setEnableLimiter(bool enableLimiter) { + mEnableLimiter = enableLimiter; + return RetCode::SUCCESS; +} + +bool AutomaticGainControlV1SwContext::getEnableLimiter() { + return mEnableLimiter; +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/automaticGainControlV1/AutomaticGainControlV1Sw.h b/audio/aidl/default/automaticGainControlV1/AutomaticGainControlV1Sw.h new file mode 100644 index 0000000000..6ba7328521 --- /dev/null +++ b/audio/aidl/default/automaticGainControlV1/AutomaticGainControlV1Sw.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2023 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 "effect-impl/EffectImpl.h" +#include "effect-impl/EffectUUID.h" + +namespace aidl::android::hardware::audio::effect { + +class AutomaticGainControlV1SwContext final : public EffectContext { + public: + AutomaticGainControlV1SwContext(int statusDepth, const Parameter::Common& common) + : EffectContext(statusDepth, common) { + LOG(DEBUG) << __func__; + } + + RetCode setTargetPeakLevel(int targetPeakLevel); + int getTargetPeakLevel(); + RetCode setMaxCompressionGain(int maxCompressionGainDb); + int getMaxCompressionGain(); + RetCode setEnableLimiter(bool enableLimiter); + bool getEnableLimiter(); + + private: + int mTargetPeakLevel = 0; + int mMaxCompressionGain = 0; + bool mEnableLimiter = false; +}; + +class AutomaticGainControlV1Sw final : public EffectImpl { + public: + static const std::string kEffectName; + static const bool kStrengthSupported; + static const Capability kCapability; + static const Descriptor kDescriptor; + AutomaticGainControlV1Sw() { LOG(DEBUG) << __func__; } + ~AutomaticGainControlV1Sw() { + cleanUp(); + LOG(DEBUG) << __func__; + } + + ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override; + ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override; + ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, + Parameter::Specific* specific) override; + + std::shared_ptr createContext(const Parameter::Common& common) override; + std::shared_ptr getContext() override; + RetCode releaseContext() override; + + std::string getEffectName() override { return kEffectName; }; + IEffect::Status effectProcessImpl(float* in, float* out, int samples) override; + + private: + static const std::vector kRanges; + std::shared_ptr mContext; + ndk::ScopedAStatus getParameterAutomaticGainControlV1(const AutomaticGainControlV1::Tag& tag, + Parameter::Specific* specific); +}; +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/include/effect-impl/EffectUUID.h b/audio/aidl/default/include/effect-impl/EffectUUID.h index f40661082a..30a6581fc8 100644 --- a/audio/aidl/default/include/effect-impl/EffectUUID.h +++ b/audio/aidl/default/include/effect-impl/EffectUUID.h @@ -45,6 +45,18 @@ static const AudioUuid kAcousticEchoCancelerSwImplUUID = {static_cast(0 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; +// 0a8abfe0-654c-11e0-ba26-0002a5d5c51b +static const AudioUuid kAutomaticGainControlV1TypeUUID = {static_cast(0x0a8abfe0), + 0x654c, + 0x11e0, + 0xba26, + {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; +// aa8130e0-66fc-11e0-bad0-0002a5d5c51b +static const AudioUuid kAutomaticGainControlV1SwImplUUID = {static_cast(0xaa8130e0), + 0x66fc, + 0x11e0, + 0xbad0, + {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; // ae3c653b-be18-4ab8-8938-418f0a7f06ac static const AudioUuid kAutomaticGainControlV2TypeUUID = {static_cast(0xae3c653b), 0xbe18, @@ -306,6 +318,7 @@ static const AudioUuid kVolumeBundleImplUUID = {static_cast(0x119341a0) */ static const std::map kUuidNameTypeMap = { {"acoustic_echo_canceler", kAcousticEchoCancelerTypeUUID}, + {"automatic_gain_control_v1", kAutomaticGainControlV1TypeUUID}, {"automatic_gain_control_v2", kAutomaticGainControlV2TypeUUID}, {"bassboost", kBassBoostTypeUUID}, {"downmix", kDownmixTypeUUID}, diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp index a1a2bd9abe..8db8eaf9aa 100644 --- a/audio/aidl/vts/Android.bp +++ b/audio/aidl/vts/Android.bp @@ -140,6 +140,12 @@ cc_test { srcs: ["VtsHalAECTargetTest.cpp"], } +cc_test { + name: "VtsHalAGC1TargetTest", + defaults: ["VtsHalAudioTargetTestDefaults"], + srcs: ["VtsHalAGC1TargetTest.cpp"], +} + cc_test { name: "VtsHalAGC2TargetTest", defaults: ["VtsHalAudioTargetTestDefaults"], diff --git a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp new file mode 100644 index 0000000000..a6fc1aa0e8 --- /dev/null +++ b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2023 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 +#include + +#define LOG_TAG "VtsHalAGC1ParamTest" + +#include "EffectHelper.h" + +using namespace android; + +using aidl::android::hardware::audio::effect::AutomaticGainControlV1; +using aidl::android::hardware::audio::effect::Descriptor; +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::IFactory; +using aidl::android::hardware::audio::effect::kAutomaticGainControlV1TypeUUID; +using aidl::android::hardware::audio::effect::Parameter; + +enum ParamName { + PARAM_INSTANCE_NAME, + PARAM_TARGET_PEAK_LEVEL, + PARAM_MAX_COMPRESSION_GAIN, + PARAM_ENABLE_LIMITER +}; +using AGC1ParamTestParam = + std::tuple, Descriptor>, int /* targetPeakLevel */, + int /* maxCompressionGain */, bool /* enableLimiter */>; + +class AGC1ParamTest : public ::testing::TestWithParam, public EffectHelper { + public: + AGC1ParamTest() + : mTargetPeakLevel(std::get(GetParam())), + mMaxCompressionGain(std::get(GetParam())), + mEnableLimiter(std::get(GetParam())) { + std::tie(mFactory, mDescriptor) = std::get(GetParam()); + } + + void SetUp() override { + ASSERT_NE(nullptr, mFactory); + ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor)); + + Parameter::Specific specific = getDefaultParamSpecific(); + Parameter::Common common = EffectHelper::createParamCommon( + 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */, + kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */); + IEffect::OpenEffectReturn ret; + ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE)); + ASSERT_NE(nullptr, mEffect); + } + + void TearDown() override { + ASSERT_NO_FATAL_FAILURE(close(mEffect)); + ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect)); + } + + Parameter::Specific getDefaultParamSpecific() { + AutomaticGainControlV1 AGC1 = + AutomaticGainControlV1::make(0); + Parameter::Specific specific = + Parameter::Specific::make(AGC1); + return specific; + } + + static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100; + std::shared_ptr mFactory; + std::shared_ptr mEffect; + Descriptor mDescriptor; + int mTargetPeakLevel; + int mMaxCompressionGain; + bool mEnableLimiter; + + void SetAndGetParameters() { + for (auto& it : mTags) { + auto& tag = it.first; + auto& AGC1 = it.second; + + // validate parameter + Descriptor desc; + ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc)); + const bool valid = + isParameterValid(AGC1, + desc); + const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT; + + // set parameter + Parameter expectParam; + Parameter::Specific specific; + specific.set(AGC1); + expectParam.set(specific); + EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString(); + + // only get if parameter in range and set success + if (expected == EX_NONE) { + Parameter getParam; + Parameter::Id id; + AutomaticGainControlV1::Id specificId; + specificId.set(tag); + id.set(specificId); + EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam)); + + EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString() + << "\ngetParam:" << getParam.toString(); + } + } + } + + void addTargetPeakLevelParam(int targetPeakLevel) { + AutomaticGainControlV1 AGC1; + AGC1.set(targetPeakLevel); + mTags.push_back({AutomaticGainControlV1::targetPeakLevelDbFs, AGC1}); + } + void addMaxCompressionGainParam(int maxCompressionGainDb) { + AutomaticGainControlV1 AGC1; + AGC1.set(maxCompressionGainDb); + mTags.push_back({AutomaticGainControlV1::maxCompressionGainDb, AGC1}); + } + void addEnableLimiterParam(bool enableLimiter) { + AutomaticGainControlV1 AGC1; + AGC1.set(enableLimiter); + mTags.push_back({AutomaticGainControlV1::enableLimiter, AGC1}); + } + + private: + std::vector> mTags; + void CleanUp() { mTags.clear(); } +}; + +TEST_P(AGC1ParamTest, SetAndGetTargetPeakLevelParam) { + EXPECT_NO_FATAL_FAILURE(addTargetPeakLevelParam(mTargetPeakLevel)); + SetAndGetParameters(); +} + +TEST_P(AGC1ParamTest, SetAndGetMaxCompressionGain) { + EXPECT_NO_FATAL_FAILURE(addMaxCompressionGainParam(mMaxCompressionGain)); + SetAndGetParameters(); +} + +TEST_P(AGC1ParamTest, SetAndGetEnableLimiter) { + EXPECT_NO_FATAL_FAILURE(addEnableLimiterParam(mEnableLimiter)); + SetAndGetParameters(); +} + +std::vector, Descriptor>> kDescPair; +INSTANTIATE_TEST_SUITE_P( + AGC1ParamTest, AGC1ParamTest, + ::testing::Combine( + testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors( + IFactory::descriptor, kAutomaticGainControlV1TypeUUID)), + testing::ValuesIn(EffectHelper::getTestValueSet< + AutomaticGainControlV1, int, Range::automaticGainControlV1, + AutomaticGainControlV1::targetPeakLevelDbFs>( + kDescPair, EffectHelper::expandTestValueBasic)), + testing::ValuesIn(EffectHelper::getTestValueSet< + AutomaticGainControlV1, int, Range::automaticGainControlV1, + AutomaticGainControlV1::maxCompressionGainDb>( + kDescPair, EffectHelper::expandTestValueBasic)), + testing::Bool()), + [](const testing::TestParamInfo& info) { + auto descriptor = std::get(info.param).second; + std::string targetPeakLevel = + std::to_string(std::get(info.param)); + std::string maxCompressionGain = + std::to_string(std::get(info.param)); + std::string enableLimiter = std::to_string(std::get(info.param)); + + std::string name = "Implementor_" + descriptor.common.implementor + "_name_" + + descriptor.common.name + "_UUID_" + + descriptor.common.id.uuid.toString() + "_target_peak_level_" + + targetPeakLevel + "_max_compression_gain_" + maxCompressionGain + + "_enable_limiter_" + enableLimiter; + std::replace_if( + name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_'); + return name; + }); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AGC1ParamTest); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + return RUN_ALL_TESTS(); +}