AIDL effect: Add Equalizer parameters implementation and vts
Bug: 238913361
Test: atest VtsHalAudioEffectTargetTest
atest VtsHalAudioEffectFactoryTargetTest
atest VtsHalEqualizerTargetTest
Change-Id: I94b2283ca2aa0e45715e1c9ac3ea6ad809ec2a2c
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 63fc415..8de1d79 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -60,6 +60,7 @@
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
],
+ header_libs: ["libaudioaidl_headers"],
cflags: [
"-Wall",
"-Wextra",
@@ -75,6 +76,7 @@
cc_test {
name: "VtsHalAudioEffectTargetTest",
defaults: [
+ "latest_android_hardware_audio_common_ndk_static",
"latest_android_media_audio_common_types_ndk_static",
"VtsHalTargetTestDefaults",
"use_libaidlvintf_gtest_helper_static",
@@ -84,12 +86,49 @@
],
shared_libs: [
"libbinder_ndk",
+ "libfmq",
],
static_libs: [
"android.hardware.audio.effect-V1-ndk",
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
+ "libaudioaidlcommon",
],
+ header_libs: ["libaudioaidl_headers"],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
+
+cc_test {
+ name: "VtsHalEqualizerTargetTest",
+ defaults: [
+ "latest_android_hardware_audio_common_ndk_static",
+ "latest_android_media_audio_common_types_ndk_static",
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: [
+ "VtsHalEqualizerTargetTest.cpp",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libfmq",
+ ],
+ static_libs: [
+ "android.hardware.audio.effect-V1-ndk",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
+ "libaudioaidlcommon",
+ ],
+ header_libs: ["libaudioaidl_headers"],
cflags: [
"-Wall",
"-Wextra",
diff --git a/audio/aidl/vts/EffectFactoryHelper.h b/audio/aidl/vts/EffectFactoryHelper.h
index cf94e58..63efae0 100644
--- a/audio/aidl/vts/EffectFactoryHelper.h
+++ b/audio/aidl/vts/EffectFactoryHelper.h
@@ -24,13 +24,14 @@
#include <android/binder_auto_utils.h>
#include "TestUtils.h"
+#include "effect-impl/EffectUUID.h"
using namespace android;
using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectNullUuid;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::IFactory;
-using aidl::android::hardware::audio::effect::Parameter;
using aidl::android::hardware::audio::effect::Processing;
using aidl::android::media::audio::common::AudioUuid;
@@ -69,7 +70,6 @@
}
void CreateEffects() {
- ASSERT_NE(mEffectFactory, nullptr);
for (const auto& id : mIds) {
std::shared_ptr<IEffect> effect;
EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect));
@@ -80,6 +80,26 @@
}
}
+ void QueryAndCreateEffects(const AudioUuid& type = EffectNullUuid) {
+ std::vector<Descriptor::Identity> ids;
+ ASSERT_NE(mEffectFactory, nullptr);
+
+ if (type == EffectNullUuid) {
+ EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, &ids));
+ } else {
+ EXPECT_IS_OK(mEffectFactory->queryEffects(type, std::nullopt, &ids));
+ }
+ for (const auto& id : ids) {
+ ASSERT_EQ(id.type, type);
+ std::shared_ptr<IEffect> effect;
+ EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect));
+ EXPECT_NE(effect, nullptr) << id.toString();
+ if (effect) {
+ mEffectIdMap[effect] = id;
+ }
+ }
+ }
+
void CreateEffectsAndExpect(
const std::vector<std::pair<Descriptor::Identity, binder_exception_t>>& uuid_status) {
ASSERT_NE(mEffectFactory, nullptr);
@@ -126,8 +146,10 @@
std::shared_ptr<IFactory> GetFactory() { return mEffectFactory; }
const std::vector<Descriptor::Identity>& GetEffectIds() { return mIds; }
- const std::vector<Descriptor::Identity>& GetCompleteEffectIdList() { return mCompleteIds; }
- const std::map<std::shared_ptr<IEffect>, Descriptor::Identity>& GetEffectMap() {
+ const std::vector<Descriptor::Identity>& GetCompleteEffectIdList() const {
+ return mCompleteIds;
+ }
+ const std::map<std::shared_ptr<IEffect>, Descriptor::Identity>& GetEffectMap() const {
return mEffectIdMap;
}
void ClearEffectMap() { mEffectIdMap.clear(); }
diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h
new file mode 100644
index 0000000..c58ed13
--- /dev/null
+++ b/audio/aidl/vts/EffectHelper.h
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <aidl/android/media/audio/common/AudioChannelLayout.h>
+#include <aidl/android/media/audio/common/AudioDeviceType.h>
+#include <android/binder_auto_utils.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "AudioHalBinderServiceUtil.h"
+#include "EffectFactoryHelper.h"
+#include "TestUtils.h"
+
+using namespace android;
+using aidl::android::hardware::audio::effect::CommandId;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectNullUuid;
+using aidl::android::hardware::audio::effect::EffectZeroUuid;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::Parameter;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioUuid;
+using aidl::android::media::audio::common::PcmType;
+
+const AudioFormatDescription DefaultFormat = {
+ .type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT, .encoding = ""};
+
+class EffectHelper {
+ public:
+ explicit EffectHelper(const std::string& name) : mFactoryHelper(EffectFactoryHelper(name)) {
+ mFactoryHelper.ConnectToFactoryService();
+ }
+
+ void OpenEffects(const AudioUuid& type = EffectNullUuid) {
+ auto open = [&](const std::shared_ptr<IEffect>& effect) {
+ IEffect::OpenEffectReturn ret;
+ EXPECT_IS_OK(effect->open(mCommon, mSpecific, &ret));
+ EffectParam params;
+ params.statusMQ = std::make_unique<StatusMQ>(ret.statusMQ);
+ params.inputMQ = std::make_unique<DataMQ>(ret.inputDataMQ);
+ params.outputMQ = std::make_unique<DataMQ>(ret.outputDataMQ);
+ mEffectParams.push_back(std::move(params));
+ };
+ EXPECT_NO_FATAL_FAILURE(ForEachEffect(open, type));
+ }
+
+ void CloseEffects(const binder_status_t status = EX_NONE) {
+ auto close = [&](const std::shared_ptr<IEffect>& effect) {
+ EXPECT_STATUS(status, effect->close());
+ };
+
+ EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
+ }
+
+ void CreateEffects(const int n = 1) {
+ for (int i = 0; i < n; i++) {
+ ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateAllEffects());
+ }
+ }
+
+ void CreateEffectsWithUUID(const AudioUuid& type = EffectNullUuid) {
+ ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateEffects(type));
+ }
+
+ void QueryEffects() { ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateAllEffects()); }
+
+ void DestroyEffects(const binder_status_t status = EX_NONE, const int remaining = 0) {
+ ASSERT_NO_FATAL_FAILURE(mFactoryHelper.DestroyEffects(status, remaining));
+ mEffectDescriptors.clear();
+ }
+
+ void GetEffectDescriptors() {
+ auto get = [&](const std::shared_ptr<IEffect>& effect) {
+ Descriptor desc;
+ EXPECT_IS_OK(effect->getDescriptor(&desc));
+ mEffectDescriptors.push_back(std::move(desc));
+ };
+ EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
+ }
+
+ void CommandEffects(CommandId command) {
+ auto close = [&](const std::shared_ptr<IEffect>& effect) {
+ EXPECT_IS_OK(effect->command(command));
+ };
+ EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
+ }
+
+ void CommandEffectsExpectStatus(CommandId command, const binder_status_t status) {
+ auto func = [&](const std::shared_ptr<IEffect>& effect) {
+ EXPECT_STATUS(status, effect->command(command));
+ };
+ EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
+ }
+
+ void ExpectState(State expected) {
+ auto get = [&](const std::shared_ptr<IEffect>& effect) {
+ State state = State::INIT;
+ EXPECT_IS_OK(effect->getState(&state));
+ EXPECT_EQ(expected, state);
+ };
+ EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
+ }
+
+ void SetParameter() {
+ auto func = [&](const std::shared_ptr<IEffect>& effect) {
+ Parameter param;
+ param.set<Parameter::common>(mCommon);
+ EXPECT_IS_OK(effect->setParameter(param));
+ };
+ EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
+ }
+
+ void VerifyParameters() {
+ auto func = [&](const std::shared_ptr<IEffect>& effect) {
+ Parameter paramCommonGet = Parameter(), paramCommonExpect = Parameter();
+ Parameter::Id id;
+ id.set<Parameter::Id::commonTag>(0);
+ paramCommonExpect.set<Parameter::common>(mCommon);
+ EXPECT_IS_OK(effect->getParameter(id, ¶mCommonGet));
+ EXPECT_EQ(paramCommonExpect, paramCommonGet)
+ << paramCommonExpect.toString() << " vs " << paramCommonGet.toString();
+ };
+ EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
+ }
+
+ void QueryEffects(const std::optional<AudioUuid>& in_type,
+ const std::optional<AudioUuid>& in_instance,
+ std::vector<Descriptor::Identity>* _aidl_return) {
+ mFactoryHelper.QueryEffects(in_type, in_instance, _aidl_return);
+ }
+
+ template <typename Functor>
+ void ForEachEffect(Functor functor, const std::optional<AudioUuid>& type = EffectNullUuid) {
+ auto effectMap = mFactoryHelper.GetEffectMap();
+ for (const auto& it : effectMap) {
+ SCOPED_TRACE(it.second.toString());
+ if (type != EffectNullUuid && it.second.type != type) continue;
+ functor(it.first);
+ }
+ }
+
+ template <typename Functor>
+ void ForEachDescriptor(Functor functor) {
+ for (size_t i = 0; i < mEffectDescriptors.size(); i++) {
+ SCOPED_TRACE(mEffectDescriptors[i].toString());
+ functor(i, mEffectDescriptors[i]);
+ }
+ }
+
+ static const size_t mWriteMQSize = 0x400;
+
+ enum class IO : char { INPUT = 0, OUTPUT = 1, INOUT = 2 };
+
+ void initParamCommonFormat(IO io = IO::INOUT,
+ const AudioFormatDescription& format = DefaultFormat) {
+ if (io == IO::INPUT || io == IO::INOUT) {
+ mCommon.input.base.format = format;
+ }
+ if (io == IO::OUTPUT || io == IO::INOUT) {
+ mCommon.output.base.format = format;
+ }
+ }
+
+ void initParamCommonSampleRate(IO io = IO::INOUT, const int& sampleRate = 48000) {
+ if (io == IO::INPUT || io == IO::INOUT) {
+ mCommon.input.base.sampleRate = sampleRate;
+ }
+ if (io == IO::OUTPUT || io == IO::INOUT) {
+ mCommon.output.base.sampleRate = sampleRate;
+ }
+ }
+
+ void initParamCommonFrameCount(IO io = IO::INOUT, const long& frameCount = 48000) {
+ if (io == IO::INPUT || io == IO::INOUT) {
+ mCommon.input.frameCount = frameCount;
+ }
+ if (io == IO::OUTPUT || io == IO::INOUT) {
+ mCommon.output.frameCount = frameCount;
+ }
+ }
+ void initParamCommon(int session = -1, int ioHandle = -1, int iSampleRate = 48000,
+ int oSampleRate = 48000, long iFrameCount = 0x100,
+ long oFrameCount = 0x100) {
+ mCommon.session = session;
+ mCommon.ioHandle = ioHandle;
+
+ auto& input = mCommon.input;
+ auto& output = mCommon.output;
+ input.base.sampleRate = iSampleRate;
+ input.base.channelMask = mInputChannelLayout;
+ input.frameCount = iFrameCount;
+ output.base.sampleRate = oSampleRate;
+ output.base.channelMask = mOutputChannelLayout;
+ output.frameCount = oFrameCount;
+ inputFrameSize = android::hardware::audio::common::getFrameSizeInBytes(
+ input.base.format, input.base.channelMask);
+ outputFrameSize = android::hardware::audio::common::getFrameSizeInBytes(
+ output.base.format, output.base.channelMask);
+ }
+
+ void setSpecific(Parameter::Specific& specific) { mSpecific = specific; }
+
+ // usually this function only call once.
+ void PrepareInputData(size_t s = mWriteMQSize) {
+ size_t maxInputSize = s;
+ for (auto& it : mEffectParams) {
+ auto& mq = it.inputMQ;
+ EXPECT_NE(nullptr, mq);
+ EXPECT_TRUE(mq->isValid());
+ const size_t bytesToWrite = mq->availableToWrite();
+ EXPECT_EQ(inputFrameSize * mCommon.input.frameCount, bytesToWrite);
+ EXPECT_NE(0UL, bytesToWrite);
+ EXPECT_TRUE(s <= bytesToWrite);
+ maxInputSize = std::max(maxInputSize, bytesToWrite);
+ }
+ mInputBuffer.resize(maxInputSize);
+ std::fill(mInputBuffer.begin(), mInputBuffer.end(), 0x5a);
+ }
+
+ void writeToFmq(size_t s = mWriteMQSize) {
+ for (auto& it : mEffectParams) {
+ auto& mq = it.inputMQ;
+ EXPECT_NE(nullptr, mq);
+ const size_t bytesToWrite = mq->availableToWrite();
+ EXPECT_NE(0Ul, bytesToWrite);
+ EXPECT_TRUE(s <= bytesToWrite);
+ EXPECT_TRUE(mq->write(mInputBuffer.data(), s));
+ }
+ }
+
+ void readFromFmq(size_t expectSize = mWriteMQSize) {
+ for (auto& it : mEffectParams) {
+ IEffect::Status status{};
+ auto& statusMq = it.statusMQ;
+ EXPECT_NE(nullptr, statusMq);
+ EXPECT_TRUE(statusMq->readBlocking(&status, 1));
+ EXPECT_EQ(STATUS_OK, status.status);
+ EXPECT_EQ(expectSize, (unsigned)status.fmqByteProduced);
+
+ auto& outputMq = it.outputMQ;
+ EXPECT_NE(nullptr, outputMq);
+ EXPECT_EQ(expectSize, outputMq->availableToRead());
+ }
+ }
+
+ void setInputChannelLayout(AudioChannelLayout input) { mInputChannelLayout = input; }
+ void setOutputChannelLayout(AudioChannelLayout output) { mOutputChannelLayout = output; }
+ const std::vector<Descriptor::Identity>& GetCompleteEffectIdList() const {
+ return mFactoryHelper.GetCompleteEffectIdList();
+ }
+ const std::vector<Descriptor>& getDescriptorVec() const { return mEffectDescriptors; }
+
+ private:
+ EffectFactoryHelper mFactoryHelper;
+
+ AudioChannelLayout mInputChannelLayout =
+ AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ AudioChannelLayout::LAYOUT_STEREO);
+ AudioChannelLayout mOutputChannelLayout =
+ AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ AudioChannelLayout::LAYOUT_STEREO);
+
+ Parameter::Common mCommon;
+ Parameter::Specific mSpecific;
+
+ size_t inputFrameSize, outputFrameSize;
+ std::vector<int8_t> mInputBuffer; // reuse same buffer for all effects testing
+
+ typedef ::android::AidlMessageQueue<
+ IEffect::Status, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+ StatusMQ;
+ typedef ::android::AidlMessageQueue<
+ int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+ DataMQ;
+
+ class EffectParam {
+ public:
+ std::unique_ptr<StatusMQ> statusMQ;
+ std::unique_ptr<DataMQ> inputMQ;
+ std::unique_ptr<DataMQ> outputMQ;
+ };
+ std::vector<EffectParam> mEffectParams;
+ std::vector<Descriptor> mEffectDescriptors;
+};
diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
index 454ce29..da8ca37 100644
--- a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
@@ -37,6 +37,8 @@
using namespace android;
using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectNullUuid;
+using aidl::android::hardware::audio::effect::EffectZeroUuid;
using aidl::android::hardware::audio::effect::IFactory;
using aidl::android::hardware::audio::effect::Processing;
using aidl::android::media::audio::common::AudioUuid;
@@ -50,17 +52,8 @@
EffectFactoryHelper mFactory = EffectFactoryHelper(GetParam());
- // TODO: these UUID can get from config file
- // ec7178ec-e5e1-4432-a3f4-4657e6795210
- const AudioUuid nullUuid = {static_cast<int32_t>(0xec7178ec),
- 0xe5e1,
- 0x4432,
- 0xa3f4,
- {0x46, 0x57, 0xe6, 0x79, 0x52, 0x10}};
- const AudioUuid zeroUuid = {
- static_cast<int32_t>(0x0), 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
- const Descriptor::Identity nullDesc = {.uuid = nullUuid};
- const Descriptor::Identity zeroDesc = {.uuid = zeroUuid};
+ const Descriptor::Identity nullDesc = {.uuid = EffectNullUuid};
+ const Descriptor::Identity zeroDesc = {.uuid = EffectZeroUuid};
};
TEST_P(EffectFactoryTest, SetupAndTearDown) {
@@ -82,20 +75,20 @@
mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
// TODO: Factory eventually need to return the full list of MUST supported AOSP effects.
for (auto& desc : descriptors) {
- EXPECT_NE(desc.type, zeroUuid);
- EXPECT_NE(desc.uuid, zeroUuid);
+ EXPECT_NE(desc.type, EffectNullUuid);
+ EXPECT_NE(desc.uuid, EffectNullUuid);
}
}
TEST_P(EffectFactoryTest, QueriedDescriptorNotExistType) {
std::vector<Descriptor::Identity> descriptors;
- mFactory.QueryEffects(nullUuid, std::nullopt, &descriptors);
+ mFactory.QueryEffects(EffectNullUuid, std::nullopt, &descriptors);
EXPECT_EQ(descriptors.size(), 0UL);
}
TEST_P(EffectFactoryTest, QueriedDescriptorNotExistInstance) {
std::vector<Descriptor::Identity> descriptors;
- mFactory.QueryEffects(std::nullopt, nullUuid, &descriptors);
+ mFactory.QueryEffects(std::nullopt, EffectNullUuid, &descriptors);
EXPECT_EQ(descriptors.size(), 0UL);
}
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index 23b20bd..7ed1f01 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -14,14 +14,14 @@
* limitations under the License.
*/
+#define LOG_TAG "VtsHalAudioEffectTargetTest"
+
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
-#define LOG_TAG "VtsHalAudioEffect"
-
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <android-base/logging.h>
@@ -30,13 +30,13 @@
#include <android/binder_manager.h>
#include <android/binder_process.h>
+#include <Utils.h>
#include <aidl/android/hardware/audio/effect/IEffect.h>
#include <aidl/android/hardware/audio/effect/IFactory.h>
-#include <aidl/android/media/audio/common/AudioChannelLayout.h>
#include <aidl/android/media/audio/common/AudioDeviceType.h>
#include "AudioHalBinderServiceUtil.h"
-#include "EffectFactoryHelper.h"
+#include "EffectHelper.h"
#include "TestUtils.h"
using namespace android;
@@ -49,201 +49,72 @@
using aidl::android::hardware::audio::effect::IFactory;
using aidl::android::hardware::audio::effect::Parameter;
using aidl::android::hardware::audio::effect::State;
-using aidl::android::media::audio::common::AudioChannelLayout;
using aidl::android::media::audio::common::AudioDeviceType;
-class AudioEffect : public testing::TestWithParam<std::string> {
+class AudioEffectTest : public testing::TestWithParam<std::string>, public EffectHelper {
public:
+ AudioEffectTest() : EffectHelper(GetParam()) {}
+
void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(mFactoryHelper.ConnectToFactoryService());
CreateEffects();
+ initParamCommonFormat();
initParamCommon();
- initParamSpecific();
+ // initParamSpecific();
}
void TearDown() override {
CloseEffects();
DestroyEffects();
}
-
- void OpenEffects() {
- auto open = [&](const std::shared_ptr<IEffect>& effect) {
- IEffect::OpenEffectReturn ret;
- EXPECT_IS_OK(effect->open(mCommon, mSpecific, &ret));
- };
- EXPECT_NO_FATAL_FAILURE(ForEachEffect(open));
- }
-
- void CloseEffects(const binder_status_t status = EX_NONE) {
- auto close = [&](const std::shared_ptr<IEffect>& effect) {
- EXPECT_STATUS(status, effect->close());
- };
-
- EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
- }
-
- void CreateEffects(const int n = 1) {
- for (int i = 0; i < n; i++) {
- ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateAllEffects());
- }
- }
-
- void DestroyEffects(const binder_status_t status = EX_NONE, const int remaining = 0) {
- ASSERT_NO_FATAL_FAILURE(mFactoryHelper.DestroyEffects(status, remaining));
- }
-
- void GetEffectDescriptors() {
- auto get = [](const std::shared_ptr<IEffect>& effect) {
- Descriptor desc;
- EXPECT_IS_OK(effect->getDescriptor(&desc));
- };
- EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
- }
-
- void CommandEffects(CommandId command) {
- auto close = [&](const std::shared_ptr<IEffect>& effect) {
- EXPECT_IS_OK(effect->command(command));
- };
- EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
- }
-
- void CommandEffectsExpectStatus(CommandId command, const binder_status_t status) {
- auto func = [&](const std::shared_ptr<IEffect>& effect) {
- EXPECT_STATUS(status, effect->command(command));
- };
- EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
- }
-
- void ExpectState(State expected) {
- auto get = [&](const std::shared_ptr<IEffect>& effect) {
- State state = State::INIT;
- EXPECT_IS_OK(effect->getState(&state));
- EXPECT_EQ(expected, state);
- };
- EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
- }
-
- void SetParameter() {
- auto func = [&](const std::shared_ptr<IEffect>& effect) {
- Parameter param;
- param.set<Parameter::common>(mCommon);
- EXPECT_IS_OK(effect->setParameter(param));
- };
- EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
- }
-
- void VerifyParameters() {
- auto func = [&](const std::shared_ptr<IEffect>& effect) {
- Parameter paramCommonGet = Parameter(), paramCommonExpect = Parameter();
- Parameter::Id id;
- id.set<Parameter::Id::commonTag>(0);
- paramCommonExpect.set<Parameter::common>(mCommon);
- EXPECT_IS_OK(effect->getParameter(id, ¶mCommonGet));
- EXPECT_EQ(paramCommonExpect, paramCommonGet)
- << paramCommonExpect.toString() << " vs " << paramCommonGet.toString();
- };
- EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
- }
-
- template <typename Functor>
- void ForEachEffect(Functor functor) {
- auto effectMap = mFactoryHelper.GetEffectMap();
- for (const auto& it : effectMap) {
- SCOPED_TRACE(it.second.toString());
- functor(it.first);
- }
- }
-
- void initParamCommon(int session = -1, int ioHandle = -1,
- AudioDeviceType deviceType = AudioDeviceType::NONE,
- int iSampleRate = 48000, int oSampleRate = 48000, long iFrameCount = 0x100,
- long oFrameCount = 0x100) {
- mCommon.session = session;
- mCommon.ioHandle = ioHandle;
- mCommon.device.type = deviceType;
- mCommon.input.base.sampleRate = iSampleRate;
- mCommon.input.base.channelMask = mInputChannelLayout;
- mCommon.input.frameCount = iFrameCount;
- mCommon.output.base.sampleRate = oSampleRate;
- mCommon.output.base.channelMask = mOutputChannelLayout;
- mCommon.output.frameCount = oFrameCount;
- }
-
- void initParamSpecific(Parameter::Specific::Tag tag = Parameter::Specific::equalizer) {
- switch (tag) {
- case Parameter::Specific::equalizer:
- mSpecific.set<Parameter::Specific::equalizer>();
- break;
- default:
- return;
- }
- }
-
- void setInputChannelLayout(AudioChannelLayout input) { mInputChannelLayout = input; }
- void setOutputChannelLayout(AudioChannelLayout output) { mOutputChannelLayout = output; }
-
- EffectFactoryHelper mFactoryHelper = EffectFactoryHelper(GetParam());
-
- private:
- AudioChannelLayout mInputChannelLayout =
- AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
- AudioChannelLayout::LAYOUT_STEREO);
- AudioChannelLayout mOutputChannelLayout =
- AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
- AudioChannelLayout::LAYOUT_STEREO);
-
- Parameter::Common mCommon;
- Parameter::Specific mSpecific;
- static IEffect::OpenEffectReturn mOpenReturn;
};
-TEST_P(AudioEffect, OpenEffectTest) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
+TEST_P(AudioEffectTest, OpenEffectTest) {
+ OpenEffects();
}
-TEST_P(AudioEffect, OpenAndCloseEffect) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+TEST_P(AudioEffectTest, OpenAndCloseEffect) {
+ OpenEffects();
+ CloseEffects();
}
-TEST_P(AudioEffect, CloseUnopenedEffectTest) {
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+TEST_P(AudioEffectTest, CloseUnopenedEffectTest) {
+ CloseEffects();
}
-TEST_P(AudioEffect, DoubleOpenCloseEffects) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+TEST_P(AudioEffectTest, DoubleOpenCloseEffects) {
+ OpenEffects();
+ CloseEffects();
+ OpenEffects();
+ CloseEffects();
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ OpenEffects();
+ OpenEffects();
+ CloseEffects();
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ OpenEffects();
+ CloseEffects();
+ CloseEffects();
}
-TEST_P(AudioEffect, GetDescriptors) {
- EXPECT_NO_FATAL_FAILURE(GetEffectDescriptors());
+TEST_P(AudioEffectTest, GetDescriptors) {
+ GetEffectDescriptors();
}
-TEST_P(AudioEffect, DescriptorIdExistAndUnique) {
+TEST_P(AudioEffectTest, DescriptorIdExistAndUnique) {
auto checker = [&](const std::shared_ptr<IEffect>& effect) {
Descriptor desc;
std::vector<Descriptor::Identity> idList;
EXPECT_IS_OK(effect->getDescriptor(&desc));
- mFactoryHelper.QueryEffects(desc.common.id.type, desc.common.id.uuid, &idList);
+ QueryEffects(desc.common.id.type, desc.common.id.uuid, &idList);
EXPECT_EQ(idList.size(), 1UL);
};
- EXPECT_NO_FATAL_FAILURE(ForEachEffect(checker));
+ ForEachEffect(checker);
// Check unique with a set
auto stringHash = [](const Descriptor::Identity& id) {
return std::hash<std::string>()(id.toString());
};
- auto vec = mFactoryHelper.GetCompleteEffectIdList();
+ auto vec = GetCompleteEffectIdList();
std::unordered_set<Descriptor::Identity, decltype(stringHash)> idSet(0, stringHash);
for (auto it : vec) {
EXPECT_EQ(idSet.count(it), 0UL);
@@ -253,218 +124,235 @@
/// State testing.
// An effect instance is in INIT state by default after it was created.
-TEST_P(AudioEffect, InitStateAfterCreation) {
+TEST_P(AudioEffectTest, InitStateAfterCreation) {
ExpectState(State::INIT);
}
// An effect instance transfer to INIT state after it was open successfully with IEffect.open().
-TEST_P(AudioEffect, IdleStateAfterOpen) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
+TEST_P(AudioEffectTest, IdleStateAfterOpen) {
+ OpenEffects();
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ CloseEffects();
}
// An effect instance is in PROCESSING state after it receive an START command.
-TEST_P(AudioEffect, ProcessingStateAfterStart) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+TEST_P(AudioEffectTest, ProcessingStateAfterStart) {
+ OpenEffects();
+ CommandEffects(CommandId::START);
ExpectState(State::PROCESSING);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ CommandEffects(CommandId::STOP);
+ CloseEffects();
}
// An effect instance transfer to IDLE state after Command.Id.STOP in PROCESSING state.
-TEST_P(AudioEffect, IdleStateAfterStop) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+TEST_P(AudioEffectTest, IdleStateAfterStop) {
+ OpenEffects();
+ CommandEffects(CommandId::START);
ExpectState(State::PROCESSING);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+ CommandEffects(CommandId::STOP);
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ CloseEffects();
}
// An effect instance transfer to IDLE state after Command.Id.RESET in PROCESSING state.
-TEST_P(AudioEffect, IdleStateAfterReset) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+TEST_P(AudioEffectTest, IdleStateAfterReset) {
+ OpenEffects();
+ CommandEffects(CommandId::START);
ExpectState(State::PROCESSING);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::RESET));
+ CommandEffects(CommandId::RESET);
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ CloseEffects();
}
// An effect instance transfer to INIT if instance receive a close() call.
-TEST_P(AudioEffect, InitStateAfterClose) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+TEST_P(AudioEffectTest, InitStateAfterClose) {
+ OpenEffects();
+ CommandEffects(CommandId::START);
ExpectState(State::PROCESSING);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+ CommandEffects(CommandId::STOP);
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ CloseEffects();
ExpectState(State::INIT);
}
// An effect instance shouldn't accept any command before open.
-TEST_P(AudioEffect, NoCommandAcceptedBeforeOpen) {
+TEST_P(AudioEffectTest, NoCommandAcceptedBeforeOpen) {
ExpectState(State::INIT);
- EXPECT_NO_FATAL_FAILURE(CommandEffectsExpectStatus(CommandId::START, EX_ILLEGAL_STATE));
- EXPECT_NO_FATAL_FAILURE(CommandEffectsExpectStatus(CommandId::STOP, EX_ILLEGAL_STATE));
- EXPECT_NO_FATAL_FAILURE(CommandEffectsExpectStatus(CommandId::RESET, EX_ILLEGAL_STATE));
+ CommandEffectsExpectStatus(CommandId::START, EX_ILLEGAL_STATE);
+ CommandEffectsExpectStatus(CommandId::STOP, EX_ILLEGAL_STATE);
+ CommandEffectsExpectStatus(CommandId::RESET, EX_ILLEGAL_STATE);
ExpectState(State::INIT);
}
// No-op when receive STOP command in IDLE state.
-TEST_P(AudioEffect, StopCommandInIdleStateNoOp) {
+TEST_P(AudioEffectTest, StopCommandInIdleStateNoOp) {
ExpectState(State::INIT);
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
+ OpenEffects();
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+ CommandEffects(CommandId::STOP);
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ CloseEffects();
}
// No-op when receive STOP command in IDLE state.
-TEST_P(AudioEffect, ResetCommandInIdleStateNoOp) {
+TEST_P(AudioEffectTest, ResetCommandInIdleStateNoOp) {
ExpectState(State::INIT);
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
+ OpenEffects();
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::RESET));
+ CommandEffects(CommandId::RESET);
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ CloseEffects();
}
// Repeat START and STOP command.
-TEST_P(AudioEffect, RepeatStartAndStop) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+TEST_P(AudioEffectTest, RepeatStartAndStop) {
+ OpenEffects();
+ CommandEffects(CommandId::START);
ExpectState(State::PROCESSING);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+ CommandEffects(CommandId::STOP);
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+ CommandEffects(CommandId::START);
ExpectState(State::PROCESSING);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+ CommandEffects(CommandId::STOP);
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ CloseEffects();
}
// Repeat START and RESET command.
-TEST_P(AudioEffect, RepeatStartAndReset) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+TEST_P(AudioEffectTest, RepeatStartAndReset) {
+ OpenEffects();
+ CommandEffects(CommandId::START);
ExpectState(State::PROCESSING);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::RESET));
+ CommandEffects(CommandId::RESET);
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+ CommandEffects(CommandId::START);
ExpectState(State::PROCESSING);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::RESET));
+ CommandEffects(CommandId::RESET);
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ CloseEffects();
}
// Repeat START and STOP command, try to close at PROCESSING state.
-TEST_P(AudioEffect, CloseProcessingStateEffects) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+TEST_P(AudioEffectTest, CloseProcessingStateEffects) {
+ OpenEffects();
+ CommandEffects(CommandId::START);
ExpectState(State::PROCESSING);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+ CommandEffects(CommandId::STOP);
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+ CommandEffects(CommandId::START);
ExpectState(State::PROCESSING);
- EXPECT_NO_FATAL_FAILURE(CloseEffects(EX_ILLEGAL_STATE));
+ CloseEffects(EX_ILLEGAL_STATE);
// cleanup
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+ CommandEffects(CommandId::STOP);
ExpectState(State::IDLE);
}
// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
-TEST_P(AudioEffect, DestroyOpenEffects) {
+TEST_P(AudioEffectTest, DestroyOpenEffects) {
// cleanup all effects.
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
- ASSERT_NO_FATAL_FAILURE(DestroyEffects());
+ CloseEffects();
+ DestroyEffects();
// open effects, destroy without close, expect to get EX_ILLEGAL_STATE status.
- EXPECT_NO_FATAL_FAILURE(CreateEffects());
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(DestroyEffects(EX_ILLEGAL_STATE, 1));
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ CreateEffects();
+ OpenEffects();
+ DestroyEffects(EX_ILLEGAL_STATE, 1);
+ CloseEffects();
}
/// Parameter testing.
// Verify parameters pass in open can be successfully get.
-TEST_P(AudioEffect, VerifyParametersAfterOpen) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(VerifyParameters());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+TEST_P(AudioEffectTest, VerifyParametersAfterOpen) {
+ OpenEffects();
+ VerifyParameters();
+ CloseEffects();
}
// Verify parameters pass in set can be successfully get.
-TEST_P(AudioEffect, SetAndGetParameter) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(VerifyParameters());
- initParamCommon(1 /* session */, 1 /* ioHandle */, AudioDeviceType::IN_DEFAULT /* deviceType */,
- 44100 /* iSampleRate */, 44100 /* oSampleRate */);
- EXPECT_NO_FATAL_FAILURE(SetParameter());
- EXPECT_NO_FATAL_FAILURE(VerifyParameters());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+TEST_P(AudioEffectTest, SetAndGetParameter) {
+ OpenEffects();
+ VerifyParameters();
+ initParamCommon(1 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */,
+ 44100 /* oSampleRate */);
+ SetParameter();
+ VerifyParameters();
+ CloseEffects();
}
// Verify parameters pass in set can be successfully get.
-TEST_P(AudioEffect, SetAndGetParameterInProcessing) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(VerifyParameters());
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+TEST_P(AudioEffectTest, SetAndGetParameterInProcessing) {
+ OpenEffects();
+ VerifyParameters();
+ CommandEffects(CommandId::START);
ExpectState(State::PROCESSING);
- initParamCommon(1 /* session */, 1 /* ioHandle */, AudioDeviceType::IN_DEFAULT /* deviceType */,
- 44100 /* iSampleRate */, 44100 /* oSampleRate */);
- EXPECT_NO_FATAL_FAILURE(SetParameter());
- EXPECT_NO_FATAL_FAILURE(VerifyParameters());
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+ initParamCommon(1 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */,
+ 44100 /* oSampleRate */);
+ SetParameter();
+ VerifyParameters();
+ CommandEffects(CommandId::STOP);
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ CloseEffects();
}
// Parameters kept after reset.
-TEST_P(AudioEffect, ResetAndVerifyParameter) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(VerifyParameters());
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+TEST_P(AudioEffectTest, ResetAndVerifyParameter) {
+ OpenEffects();
+ VerifyParameters();
+ CommandEffects(CommandId::START);
ExpectState(State::PROCESSING);
- initParamCommon(1 /* session */, 1 /* ioHandle */, AudioDeviceType::IN_DEFAULT /* deviceType */,
- 44100 /* iSampleRate */, 44100 /* oSampleRate */);
- EXPECT_NO_FATAL_FAILURE(SetParameter());
- EXPECT_NO_FATAL_FAILURE(VerifyParameters());
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::RESET));
+ initParamCommon(1 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */,
+ 44100 /* oSampleRate */);
+ SetParameter();
+ VerifyParameters();
+ CommandEffects(CommandId::RESET);
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(VerifyParameters());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ VerifyParameters();
+ CloseEffects();
}
// Multiple instances of same implementation running.
-TEST_P(AudioEffect, MultipleInstancesRunning) {
- EXPECT_NO_FATAL_FAILURE(CreateEffects(3));
+TEST_P(AudioEffectTest, MultipleInstancesRunning) {
+ CreateEffects(3);
ExpectState(State::INIT);
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
+ OpenEffects();
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+ CommandEffects(CommandId::START);
ExpectState(State::PROCESSING);
- initParamCommon(1 /* session */, 1 /* ioHandle */, AudioDeviceType::IN_DEFAULT /* deviceType */,
- 44100 /* iSampleRate */, 44100 /* oSampleRate */);
- EXPECT_NO_FATAL_FAILURE(SetParameter());
- EXPECT_NO_FATAL_FAILURE(VerifyParameters());
- EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+ initParamCommon(1 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */,
+ 44100 /* oSampleRate */);
+ SetParameter();
+ VerifyParameters();
+ CommandEffects(CommandId::STOP);
ExpectState(State::IDLE);
- EXPECT_NO_FATAL_FAILURE(VerifyParameters());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ VerifyParameters();
+ CloseEffects();
}
-INSTANTIATE_TEST_SUITE_P(AudioEffectTest, AudioEffect,
+// Send data to effects and expect it to consume by check statusMQ.
+TEST_P(AudioEffectTest, ExpectEffectsToConsumeDataInMQ) {
+ OpenEffects();
+ PrepareInputData(mWriteMQSize);
+
+ CommandEffects(CommandId::START);
+ writeToFmq(mWriteMQSize);
+ readFromFmq(mWriteMQSize);
+
+ ExpectState(State::PROCESSING);
+ CommandEffects(CommandId::STOP);
+ // cleanup
+ CommandEffects(CommandId::STOP);
+ ExpectState(State::IDLE);
+ CloseEffects();
+}
+
+INSTANTIATE_TEST_SUITE_P(AudioEffectTestTest, AudioEffectTest,
testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
android::PrintInstanceNameToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffect);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffectTest);
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
ABinderProcess_setThreadPoolMaxThreadCount(1);
ABinderProcess_startThreadPool();
return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}
diff --git a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
new file mode 100644
index 0000000..3b9699b
--- /dev/null
+++ b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <limits>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "VtsHalEqualizerTest"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+
+#include <Utils.h>
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <aidl/android/media/audio/common/AudioChannelLayout.h>
+#include <aidl/android/media/audio/common/AudioDeviceType.h>
+
+#include "AudioHalBinderServiceUtil.h"
+#include "EffectHelper.h"
+#include "TestUtils.h"
+#include "effect-impl/EffectUUID.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Capability;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectNullUuid;
+using aidl::android::hardware::audio::effect::Equalizer;
+using aidl::android::hardware::audio::effect::EqualizerTypeUUID;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::Parameter;
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEfectTargetTest.
+ */
+using EqualizerParamTestParam = std::tuple<int, int, int>;
+
+class EqualizerParamTest : public ::testing::TestWithParam<EqualizerParamTestParam>,
+ public EffectHelper {
+ public:
+ EqualizerParamTest()
+ : EffectHelper(android::getAidlHalInstanceNames(IFactory::descriptor)[0]),
+ mParamPresetIndex(std::get<0 /* kPresetIndexRange */>(GetParam())),
+ mParamBandIndex(std::get<1 /* kBandIndexRange */>(GetParam())),
+ mParamBandLevel(std::get<2 /* kBandLevelRange */>(GetParam())) {}
+
+ void SetUp() override {
+ CreateEffectsWithUUID(EqualizerTypeUUID);
+ initParamCommonFormat();
+ initParamCommon();
+ initParamSpecific();
+ OpenEffects(EqualizerTypeUUID);
+ SCOPED_TRACE(testing::Message() << "preset: " << mParamPresetIndex << " bandIdx "
+ << mParamBandIndex << " level " << mParamBandLevel);
+ }
+
+ void TearDown() override {
+ CloseEffects();
+ DestroyEffects();
+ CleanUp();
+ }
+
+ const int mParamPresetIndex;
+ const int mParamBandIndex;
+ const int mParamBandLevel;
+
+ void SetAndGetEqualizerParameters() {
+ auto functor = [&](const std::shared_ptr<IEffect>& effect) {
+ for (auto& it : mTags) {
+ auto& tag = it.first;
+ auto& eq = it.second;
+
+ // validate parameter
+ Descriptor desc;
+ ASSERT_STATUS(EX_NONE, effect->getDescriptor(&desc));
+ const bool valid = isTagInRange(it.first, it.second, desc);
+ const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+
+ // set
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::equalizer>(*eq.get());
+ expectParam.set<Parameter::specific>(specific);
+ EXPECT_STATUS(expected, effect->setParameter(expectParam))
+ << expectParam.toString();
+
+ // get
+ if (expected == EX_NONE) {
+ Parameter getParam;
+ Parameter::Specific::Id id;
+ id.set<Parameter::Specific::Id::equalizerTag>(tag);
+ // if set success, then get should match
+ EXPECT_STATUS(expected, effect->getParameter(id, &getParam));
+ EXPECT_EQ(expectParam, getParam) << "\n"
+ << expectParam.toString() << "\n"
+ << getParam.toString();
+ }
+ }
+ };
+ EXPECT_NO_FATAL_FAILURE(ForEachEffect(functor));
+ }
+
+ void addPresetParam(int preset) {
+ Equalizer eq;
+ eq.set<Equalizer::preset>(preset);
+ mTags.push_back({Equalizer::preset, std::make_unique<Equalizer>(std::move(eq))});
+ }
+
+ void addBandLevelsParam(std::vector<Equalizer::BandLevel>& bandLevels) {
+ Equalizer eq;
+ eq.set<Equalizer::bandLevels>(bandLevels);
+ mTags.push_back({Equalizer::bandLevels, std::make_unique<Equalizer>(std::move(eq))});
+ }
+
+ bool isTagInRange(const Equalizer::Tag& tag, const std::unique_ptr<Equalizer>& eq,
+ const Descriptor& desc) const {
+ std::cout << "xxx" << toString(tag) << " " << desc.toString();
+ const Equalizer::Capability& eqCap = desc.capability.get<Capability::equalizer>();
+ switch (tag) {
+ case Equalizer::preset: {
+ int index = eq->get<Equalizer::preset>();
+ return isPresetIndexInRange(eqCap, index);
+ }
+ case Equalizer::bandLevels: {
+ auto& bandLevel = eq->get<Equalizer::bandLevels>();
+ return isBandIndexInRange(eqCap, bandLevel);
+ }
+ default:
+ return false;
+ }
+ return false;
+ }
+
+ bool isPresetIndexInRange(const Equalizer::Capability& cap, int idx) const {
+ const auto [min, max] =
+ std::minmax_element(cap.presets.begin(), cap.presets.end(),
+ [](const auto& a, const auto& b) { return a.index < b.index; });
+ return idx >= min->index && idx <= max->index;
+ }
+
+ bool isBandIndexInRange(const Equalizer::Capability& cap,
+ const std::vector<Equalizer::BandLevel>& bandLevel) const {
+ for (auto& it : bandLevel) {
+ if (!isBandIndexInRange(cap, it.index)) return false;
+ }
+ return true;
+ }
+
+ bool isBandIndexInRange(const Equalizer::Capability& cap, int idx) const {
+ const auto [min, max] =
+ std::minmax_element(cap.bandFrequencies.begin(), cap.bandFrequencies.end(),
+ [](const auto& a, const auto& b) { return a.index < b.index; });
+ return idx >= min->index && idx <= max->index;
+ }
+
+ private:
+ Equalizer::VendorExtension mVendorExtension;
+ std::vector<std::pair<Equalizer::Tag, std::unique_ptr<Equalizer>>> mTags;
+
+ bool validCapabilityTag(Capability& cap) { return cap.getTag() == Capability::equalizer; }
+
+ void initParamSpecific() {
+ Equalizer eq;
+ eq.set<Equalizer::preset>(0);
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::equalizer>(eq);
+ setSpecific(specific);
+ }
+
+ void CleanUp() { mTags.clear(); }
+};
+
+TEST_P(EqualizerParamTest, SetAndGetPreset) {
+ EXPECT_NO_FATAL_FAILURE(addPresetParam(mParamPresetIndex));
+ SetAndGetEqualizerParameters();
+}
+
+TEST_P(EqualizerParamTest, SetAndGetSingleBand) {
+ Equalizer::BandLevel bandLevel = {mParamBandIndex, mParamBandLevel};
+ std::vector<Equalizer::BandLevel> bandLevels;
+ bandLevels.push_back(bandLevel);
+ EXPECT_NO_FATAL_FAILURE(addBandLevelsParam(bandLevels));
+ SetAndGetEqualizerParameters();
+}
+
+/**
+ Testing preset index range with [-10, 10], assuming the min/max preset index supported by
+effect is in this range.
+ This range is verified with IEffect.getDescriptor(): for any index supported vts expect EX_NONE
+from IEffect.setParameter(), otherwise expect EX_ILLEGAL_ARGUMENT.
+ */
+constexpr std::pair<int, int> kPresetIndexRange = {-1, 10}; // valid range [0, 9]
+constexpr std::pair<int, int> kBandIndexRange = {-1, 5}; // valid range [0, 4]
+constexpr std::pair<int, int> kBandLevelRange = {-5, 5}; // needs update with implementation
+
+INSTANTIATE_TEST_SUITE_P(
+ EqualizerTest, EqualizerParamTest,
+ ::testing::Combine(testing::Range(kPresetIndexRange.first, kPresetIndexRange.second),
+ testing::Range(kBandIndexRange.first, kBandIndexRange.second),
+ testing::Range(kBandLevelRange.first, kBandLevelRange.second)));
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EqualizerTest);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}