AIDL effect: Initial IEffect interface implementation and vts test
Bug: 238913361
Test: atest VtsHalAudioEffectTargetTest
Merged-In: Id64d28af9122e82acd96e3349cf37c3d9728069a
Change-Id: Id64d28af9122e82acd96e3349cf37c3d9728069a
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index ad933bc..d6e6f50 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -166,3 +166,19 @@
},
},
}
+
+latest_android_hardware_audio_effect = "android.hardware.audio.effect-V1"
+
+cc_defaults {
+ name: "latest_android_hardware_audio_effect_ndk_shared",
+ shared_libs: [
+ latest_android_hardware_audio_effect + "-ndk",
+ ],
+}
+
+cc_defaults {
+ name: "latest_android_hardware_audio_effect_ndk_static",
+ static_libs: [
+ latest_android_hardware_audio_effect + "-ndk",
+ ],
+}
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 5d63347..53ed908 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -68,6 +68,7 @@
"libbase",
"libbinder_ndk",
"android.hardware.audio.effect-V1-ndk",
+ "libequalizer",
],
cflags: [
"-Wall",
@@ -80,7 +81,10 @@
cc_library_static {
name: "libaudioeffectserviceexampleimpl",
defaults: ["aidlaudioeffectservice_defaults"],
- export_include_dirs: ["include"],
+ export_include_dirs: [
+ "include",
+ "include/equalizer-impl/",
+ ],
srcs: [
"EffectFactory.cpp",
],
diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp
index a31e23f..ea9d470 100644
--- a/audio/aidl/default/EffectFactory.cpp
+++ b/audio/aidl/default/EffectFactory.cpp
@@ -36,6 +36,8 @@
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
id.uuid = EqualizerUUID;
mIdentityList.push_back(id);
+ // TODO: Add visualizer with default implementation later
+#if 0
id.type = {static_cast<int32_t>(0xd3467faa),
0xacc7,
0x4d34,
@@ -43,6 +45,7 @@
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
id.uuid = VisualizerUUID;
mIdentityList.push_back(id);
+#endif
}
ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type,
@@ -56,4 +59,28 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Factory::createEffect(
+ const AudioUuid& in_impl_uuid,
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>* _aidl_return) {
+ LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString();
+ if (in_impl_uuid == EqualizerUUID) {
+ *_aidl_return = ndk::SharedRefBase::make<Equalizer>();
+ } else {
+ LOG(ERROR) << __func__ << ": UUID "
+ << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Factory::destroyEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_handle) {
+ if (in_handle) {
+ // TODO: b/245393900 need check the instance state with IEffect.getState before destroy.
+ return ndk::ScopedAStatus::ok();
+ } else {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+}
+
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/EffectMain.cpp b/audio/aidl/default/EffectMain.cpp
index 3b3c39b..b30f2e7 100644
--- a/audio/aidl/default/EffectMain.cpp
+++ b/audio/aidl/default/EffectMain.cpp
@@ -23,10 +23,11 @@
int main() {
// This is a debug implementation, always enable debug logging.
android::base::SetMinimumLogSeverity(::android::base::DEBUG);
- ABinderProcess_setThreadPoolMaxThreadCount(16);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
auto effectFactory =
ndk::SharedRefBase::make<aidl::android::hardware::audio::effect::Factory>();
+
std::string serviceName = std::string() + effectFactory->descriptor + "/default";
binder_status_t status =
AServiceManager_addService(effectFactory->asBinder().get(), serviceName.c_str());
diff --git a/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc b/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc
index 01c0e6e..68bbf5b 100644
--- a/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc
+++ b/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc
@@ -2,7 +2,7 @@
class hal
user audioserver
# media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
- group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub
+ group audio media
capabilities BLOCK_SUSPEND
ioprio rt 4
task_profiles ProcessCapacityHigh HighPerformance
diff --git a/audio/aidl/default/equalizer/Android.bp b/audio/aidl/default/equalizer/Android.bp
new file mode 100644
index 0000000..b842149
--- /dev/null
+++ b/audio/aidl/default/equalizer/Android.bp
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+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: "libequalizer",
+ vendor: true,
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libstagefright_foundation",
+ ],
+ defaults: [
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ ],
+ include_dirs: ["hardware/interfaces/audio/aidl/default/include/equalizer-impl"],
+ srcs: [
+ "Equalizer.cpp",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/audio/aidl/default/equalizer/Equalizer.cpp b/audio/aidl/default/equalizer/Equalizer.cpp
new file mode 100644
index 0000000..dae3ab7
--- /dev/null
+++ b/audio/aidl/default/equalizer/Equalizer.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "AHAL_Equalizer"
+#include <android-base/logging.h>
+
+#include "Equalizer.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+Equalizer::Equalizer() {
+ // Implementation UUID
+ mDesc.common.id.uuid = {static_cast<int32_t>(0xce772f20),
+ 0x847d,
+ 0x11df,
+ 0xbb17,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+}
+
+ndk::ScopedAStatus Equalizer::open() {
+ LOG(DEBUG) << __func__;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Equalizer::close() {
+ LOG(DEBUG) << __func__;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Equalizer::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << "descriptor " << mDesc.toString();
+ *_aidl_return = mDesc;
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
index 7670250..8da5525 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
@@ -40,6 +40,28 @@
const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_instance,
std::vector<Descriptor::Identity>* out_descriptor) override;
+ /**
+ * @brief Create an effect instance for a certain implementation (identified by UUID).
+ *
+ * @param in_impl_uuid Effect implementation UUID.
+ * @param _aidl_return A pointer to created effect instance.
+ * @return ndk::ScopedAStatus
+ */
+ ndk::ScopedAStatus createEffect(
+ const ::aidl::android::media::audio::common::AudioUuid& in_impl_uuid,
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>* _aidl_return)
+ override;
+
+ /**
+ * @brief Destroy an effect instance.
+ *
+ * @param in_handle Effect instance handle.
+ * @return ndk::ScopedAStatus
+ */
+ ndk::ScopedAStatus destroyEffect(
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_handle)
+ override;
+
private:
// List of effect descriptors supported by the devices.
std::vector<Descriptor::Identity> mIdentityList;
diff --git a/audio/aidl/default/include/equalizer-impl/Equalizer.h b/audio/aidl/default/include/equalizer-impl/Equalizer.h
index 86f8c3a..44b1d6d 100644
--- a/audio/aidl/default/include/equalizer-impl/Equalizer.h
+++ b/audio/aidl/default/include/equalizer-impl/Equalizer.h
@@ -16,16 +16,28 @@
#pragma once
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
#include <cstdlib>
namespace aidl::android::hardware::audio::effect {
// Equalizer implementation UUID.
static const ::aidl::android::media::audio::common::AudioUuid EqualizerUUID = {
- static_cast<int32_t>(0xce772f20),
- 0x847d,
- 0x11df,
- 0xbb17,
+ static_cast<int32_t>(0x0bed4300),
+ 0xddd6,
+ 0x11db,
+ 0x8f34,
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-} // namespace aidl::android::hardware::audio::effect
\ No newline at end of file
+class Equalizer : public BnEffect {
+ public:
+ Equalizer();
+ ndk::ScopedAStatus open() override;
+ ndk::ScopedAStatus close() override;
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+
+ private:
+ // Effect descriptor.
+ Descriptor mDesc = {.common.id.type = EqualizerUUID};
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index f70948c..9b100b1 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -14,7 +14,11 @@
* limitations under the License.
*/
+#include <memory>
#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
#define LOG_TAG "VtsHalAudioEffect"
@@ -35,37 +39,88 @@
using ndk::ScopedAStatus;
using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::IFactory;
using aidl::android::media::audio::common::AudioUuid;
-namespace ndk {
-std::ostream& operator<<(std::ostream& str, const ScopedAStatus& status) {
- str << status.getDescription();
- return str;
-}
-} // namespace ndk
-
-class EffectFactory : public testing::TestWithParam<std::string> {
+class EffectFactoryHelper {
public:
- void SetUp() override { ASSERT_NO_FATAL_FAILURE(ConnectToService()); }
+ EffectFactoryHelper(const std::string& name) : mServiceName(name) {}
- void TearDown() override {}
-
- void ConnectToService() {
- serviceName = GetParam();
- factory = IFactory::fromBinder(binderUtil.connectToService(serviceName));
- ASSERT_NE(factory, nullptr);
+ void ConnectToFactoryService() {
+ mEffectFactory = IFactory::fromBinder(binderUtil.connectToService(mServiceName));
+ ASSERT_NE(mEffectFactory, nullptr);
}
- void RestartService() {
- ASSERT_NE(factory, nullptr);
- factory = IFactory::fromBinder(binderUtil.restartService());
- ASSERT_NE(factory, nullptr);
+ void RestartFactoryService() {
+ ASSERT_NE(mEffectFactory, nullptr);
+ mEffectFactory = IFactory::fromBinder(binderUtil.restartService());
+ ASSERT_NE(mEffectFactory, nullptr);
}
- std::shared_ptr<IFactory> factory;
- std::string serviceName;
+ void QueryAllEffects() {
+ EXPECT_NE(mEffectFactory, nullptr);
+ ScopedAStatus status =
+ mEffectFactory->queryEffects(std::nullopt, std::nullopt, &mCompleteIds);
+ EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+ }
+
+ void QueryEffects(const std::optional<AudioUuid>& in_type,
+ const std::optional<AudioUuid>& in_instance,
+ std::vector<Descriptor::Identity>* _aidl_return) {
+ EXPECT_NE(mEffectFactory, nullptr);
+ ScopedAStatus status = mEffectFactory->queryEffects(in_type, in_instance, _aidl_return);
+ EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+ mIds = *_aidl_return;
+ }
+
+ void CreateEffects() {
+ EXPECT_NE(mEffectFactory, nullptr);
+ ScopedAStatus status;
+ for (const auto& id : mIds) {
+ std::shared_ptr<IEffect> effect;
+ status = mEffectFactory->createEffect(id.uuid, &effect);
+ EXPECT_EQ(status.getExceptionCode(), EX_NONE) << id.toString();
+ EXPECT_NE(effect, nullptr) << id.toString();
+ mEffectIdMap[effect] = id;
+ }
+ }
+
+ void DestroyEffects() {
+ EXPECT_NE(mEffectFactory, nullptr);
+ ScopedAStatus status;
+ for (const auto& it : mEffectIdMap) {
+ status = mEffectFactory->destroyEffect(it.first);
+ EXPECT_EQ(status.getExceptionCode(), EX_NONE) << it.second.toString();
+ }
+ mEffectIdMap.clear();
+ }
+
+ 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::unordered_map<std::shared_ptr<IEffect>, Descriptor::Identity>& GetEffectMap() {
+ return mEffectIdMap;
+ }
+
+ private:
+ std::shared_ptr<IFactory> mEffectFactory;
+ std::string mServiceName;
AudioHalBinderServiceUtil binderUtil;
+ std::vector<Descriptor::Identity> mIds;
+ std::vector<Descriptor::Identity> mCompleteIds;
+ std::unordered_map<std::shared_ptr<IEffect>, Descriptor::Identity> mEffectIdMap;
+};
+
+/// Effect factory testing.
+class EffectFactoryTest : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override { ASSERT_NO_FATAL_FAILURE(mFactory.ConnectToFactoryService()); }
+
+ void TearDown() override { mFactory.DestroyEffects(); }
+
+ 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),
@@ -77,25 +132,23 @@
static_cast<int32_t>(0x0), 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
};
-TEST_P(EffectFactory, SetupAndTearDown) {
+TEST_P(EffectFactoryTest, SetupAndTearDown) {
// Intentionally empty test body.
}
-TEST_P(EffectFactory, CanBeRestarted) {
- ASSERT_NO_FATAL_FAILURE(RestartService());
+TEST_P(EffectFactoryTest, CanBeRestarted) {
+ ASSERT_NO_FATAL_FAILURE(mFactory.RestartFactoryService());
}
-TEST_P(EffectFactory, QueriedDescriptorList) {
+TEST_P(EffectFactoryTest, QueriedDescriptorList) {
std::vector<Descriptor::Identity> descriptors;
- ScopedAStatus status = factory->queryEffects(std::nullopt, std::nullopt, &descriptors);
- EXPECT_EQ(EX_NONE, status.getExceptionCode());
+ mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
EXPECT_NE(static_cast<int>(descriptors.size()), 0);
}
-TEST_P(EffectFactory, DescriptorUUIDNotNull) {
+TEST_P(EffectFactoryTest, DescriptorUUIDNotNull) {
std::vector<Descriptor::Identity> descriptors;
- ScopedAStatus status = factory->queryEffects(std::nullopt, std::nullopt, &descriptors);
- EXPECT_EQ(EX_NONE, status.getExceptionCode());
+ 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);
@@ -103,28 +156,176 @@
}
}
-TEST_P(EffectFactory, QueriedDescriptorNotExistType) {
+TEST_P(EffectFactoryTest, QueriedDescriptorNotExistType) {
std::vector<Descriptor::Identity> descriptors;
- ScopedAStatus status = factory->queryEffects(nullUuid, std::nullopt, &descriptors);
- EXPECT_EQ(EX_NONE, status.getExceptionCode());
+ mFactory.QueryEffects(nullUuid, std::nullopt, &descriptors);
EXPECT_EQ(static_cast<int>(descriptors.size()), 0);
}
-TEST_P(EffectFactory, QueriedDescriptorNotExistInstance) {
+TEST_P(EffectFactoryTest, QueriedDescriptorNotExistInstance) {
std::vector<Descriptor::Identity> descriptors;
- ScopedAStatus status = factory->queryEffects(std::nullopt, nullUuid, &descriptors);
- EXPECT_EQ(EX_NONE, status.getExceptionCode());
+ mFactory.QueryEffects(std::nullopt, nullUuid, &descriptors);
EXPECT_EQ(static_cast<int>(descriptors.size()), 0);
}
-INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactory,
+TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) {
+ std::vector<Descriptor::Identity> descriptors;
+ mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+ int numIds = static_cast<int>(mFactory.GetEffectIds().size());
+ EXPECT_NE(numIds, 0);
+
+ EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+ mFactory.CreateEffects();
+ EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), numIds);
+ mFactory.DestroyEffects();
+ EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+
+ // Create and destroy again
+ mFactory.CreateEffects();
+ EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), numIds);
+ mFactory.DestroyEffects();
+ EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+}
+
+TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) {
+ std::vector<Descriptor::Identity> descriptors;
+ mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+ int numIds = static_cast<int>(mFactory.GetEffectIds().size());
+ EXPECT_NE(numIds, 0);
+
+ EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+ mFactory.CreateEffects();
+ EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), numIds);
+ // Create effect instances of same implementation
+ mFactory.CreateEffects();
+ EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 2 * numIds);
+
+ mFactory.CreateEffects();
+ EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 3 * numIds);
+
+ mFactory.DestroyEffects();
+ EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+}
+
+INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactoryTest,
testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
android::PrintInstanceNameToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EffectFactory);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EffectFactoryTest);
+
+/// Effect testing.
+class AudioEffect : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(mFactory.ConnectToFactoryService());
+ ASSERT_NO_FATAL_FAILURE(mFactory.CreateEffects());
+ }
+
+ void TearDown() override {
+ CloseEffects();
+ ASSERT_NO_FATAL_FAILURE(mFactory.DestroyEffects());
+ }
+
+ void OpenEffects() {
+ auto open = [](const std::shared_ptr<IEffect>& effect) {
+ ScopedAStatus status = effect->open();
+ EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+ };
+ EXPECT_NO_FATAL_FAILURE(ForEachEffect(open));
+ }
+
+ void CloseEffects() {
+ auto close = [](const std::shared_ptr<IEffect>& effect) {
+ ScopedAStatus status = effect->close();
+ EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+ };
+ EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
+ }
+
+ void GetEffectDescriptors() {
+ auto get = [](const std::shared_ptr<IEffect>& effect) {
+ Descriptor desc;
+ ScopedAStatus status = effect->getDescriptor(&desc);
+ EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+ };
+ EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
+ }
+
+ template <typename Functor>
+ void ForEachEffect(Functor functor) {
+ auto effectMap = mFactory.GetEffectMap();
+ ScopedAStatus status;
+ for (const auto& it : effectMap) {
+ SCOPED_TRACE(it.second.toString());
+ functor(it.first);
+ }
+ }
+
+ EffectFactoryHelper mFactory = EffectFactoryHelper(GetParam());
+};
+
+TEST_P(AudioEffect, OpenEffectTest) {
+ EXPECT_NO_FATAL_FAILURE(OpenEffects());
+}
+
+TEST_P(AudioEffect, OpenAndCloseEffect) {
+ EXPECT_NO_FATAL_FAILURE(OpenEffects());
+ EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+TEST_P(AudioEffect, CloseUnopenedEffectTest) {
+ EXPECT_NO_FATAL_FAILURE(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());
+
+ EXPECT_NO_FATAL_FAILURE(OpenEffects());
+ EXPECT_NO_FATAL_FAILURE(OpenEffects());
+ EXPECT_NO_FATAL_FAILURE(CloseEffects());
+
+ EXPECT_NO_FATAL_FAILURE(OpenEffects());
+ EXPECT_NO_FATAL_FAILURE(CloseEffects());
+ EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+TEST_P(AudioEffect, GetDescriptors) {
+ EXPECT_NO_FATAL_FAILURE(GetEffectDescriptors());
+}
+
+TEST_P(AudioEffect, DescriptorIdExistAndUnique) {
+ auto checker = [&](const std::shared_ptr<IEffect>& effect) {
+ Descriptor desc;
+ std::vector<Descriptor::Identity> idList;
+ ScopedAStatus status = effect->getDescriptor(&desc);
+ EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+ mFactory.QueryEffects(desc.common.id.type, desc.common.id.uuid, &idList);
+ EXPECT_EQ(static_cast<int>(idList.size()), 1);
+ };
+ EXPECT_NO_FATAL_FAILURE(ForEachEffect(checker));
+
+ // Check unique with a set
+ auto stringHash = [](const Descriptor::Identity& id) {
+ return std::hash<std::string>()(id.toString());
+ };
+ auto vec = mFactory.GetCompleteEffectIdList();
+ std::unordered_set<Descriptor::Identity, decltype(stringHash)> idSet(0, stringHash);
+ for (auto it : vec) {
+ EXPECT_EQ(static_cast<int>(idSet.count(it)), 0);
+ idSet.insert(it);
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(AudioEffectTest, AudioEffect,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
+ android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffect);
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