Implement libAudioHal AIDL EffectsFactoryHalInterface getProcessings
Bug: 281572768
Test: atest EffectsFactoryHalInterfaceTest
Test: atest --test-mapping hardware/interfaces/audio/aidl/vts:presubmit
Change-Id: I97484647ef55cbe08e6edd82663615c02a043823
Merged-In: I97484647ef55cbe08e6edd82663615c02a043823
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
index ec1f75c..bc9d4d5 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
@@ -288,6 +288,11 @@
ConversionResult<media::audio::common::AudioOutputFlags>
legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
+ConversionResult<audio_stream_type_t>
+aidl2legacy_AudioStreamType_audio_stream_type_t(media::audio::common::AudioStreamType aidl);
+ConversionResult<media::audio::common::AudioStreamType>
+legacy2aidl_audio_stream_type_t_AudioStreamType(audio_stream_type_t legacy);
+
// This type is unnamed in the original definition, thus we name it here.
using audio_port_config_mix_ext_usecase = decltype(audio_port_config_mix_ext::usecase);
ConversionResult<audio_port_config_mix_ext_usecase>
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 5bd0114..b0d48b7 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -72,11 +72,6 @@
media::audio::common::AudioPortDeviceExt* aidl,
media::AudioPortDeviceExtSys* aidlDeviceExt);
-ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
- media::audio::common::AudioStreamType aidl);
-ConversionResult<media::audio::common::AudioStreamType>
-legacy2aidl_audio_stream_type_t_AudioStreamType(audio_stream_type_t legacy);
-
ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortMixExt(
const media::audio::common::AudioPortMixExt& aidl, media::AudioPortRole role,
const media::AudioPortMixExtSys& aidlMixExt);
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
index 0dcb8ee..7b9088e 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -40,6 +40,8 @@
using ::aidl::android::hardware::audio::effect::Descriptor;
using ::aidl::android::hardware::audio::effect::IFactory;
using ::aidl::android::hardware::audio::effect::Processing;
+using ::aidl::android::media::audio::common::AudioSource;
+using ::aidl::android::media::audio::common::AudioStreamType;
using ::aidl::android::media::audio::common::AudioUuid;
using ::android::base::unexpected;
using ::android::detail::AudioHalVersionInfo;
@@ -96,7 +98,13 @@
return list;
}()),
mEffectCount(mNonProxyDescList.size() + mProxyDescList.size()),
- mEffectProcessings(nullptr /* TODO: add AIDL implementation */) {
+ mAidlProcessings([this]() -> std::vector<Processing> {
+ std::vector<Processing> processings;
+ if (!mFactory || !mFactory->queryProcessing(std::nullopt, &processings).isOk()) {
+ ALOGE("%s queryProcessing failed", __func__);
+ }
+ return processings;
+ }()) {
ALOG_ASSERT(mFactory != nullptr, "Provided IEffectsFactory service is NULL");
ALOGI("%s with %zu nonProxyEffects and %zu proxyEffects", __func__, mNonProxyDescList.size(),
mProxyDescList.size());
@@ -274,15 +282,79 @@
}
std::shared_ptr<const effectsConfig::Processings> EffectsFactoryHalAidl::getProcessings() const {
- return mEffectProcessings;
+
+ auto getConfigEffectWithDescriptor =
+ [](const auto& desc) -> std::shared_ptr<const effectsConfig::Effect> {
+ effectsConfig::Effect effect = {.name = desc.common.name, .isProxy = false};
+ if (const auto uuid =
+ ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(desc.common.id.uuid);
+ uuid.ok()) {
+ static_cast<effectsConfig::EffectImpl>(effect).uuid = uuid.value();
+ return std::make_shared<const effectsConfig::Effect>(effect);
+ } else {
+ return nullptr;
+ }
+ };
+
+ auto getConfigProcessingWithAidlProcessing =
+ [&](const auto& aidlProcess, std::vector<effectsConfig::InputStream>& preprocess,
+ std::vector<effectsConfig::OutputStream>& postprocess) {
+ if (aidlProcess.type.getTag() == Processing::Type::streamType) {
+ AudioStreamType aidlType =
+ aidlProcess.type.template get<Processing::Type::streamType>();
+ const auto type =
+ ::aidl::android::aidl2legacy_AudioStreamType_audio_stream_type_t(
+ aidlType);
+ if (!type.ok()) {
+ return;
+ }
+
+ std::vector<std::shared_ptr<const effectsConfig::Effect>> effects;
+ std::transform(aidlProcess.ids.begin(), aidlProcess.ids.end(),
+ std::back_inserter(effects), getConfigEffectWithDescriptor);
+ effectsConfig::OutputStream stream = {.type = type.value(),
+ .effects = std::move(effects)};
+ postprocess.emplace_back(stream);
+ } else if (aidlProcess.type.getTag() == Processing::Type::source) {
+ AudioSource aidlType =
+ aidlProcess.type.template get<Processing::Type::source>();
+ const auto type =
+ ::aidl::android::aidl2legacy_AudioSource_audio_source_t(aidlType);
+ if (!type.ok()) {
+ return;
+ }
+
+ std::vector<std::shared_ptr<const effectsConfig::Effect>> effects;
+ std::transform(aidlProcess.ids.begin(), aidlProcess.ids.end(),
+ std::back_inserter(effects), getConfigEffectWithDescriptor);
+ effectsConfig::InputStream stream = {.type = type.value(),
+ .effects = std::move(effects)};
+ preprocess.emplace_back(stream);
+ }
+ };
+
+ static std::shared_ptr<const effectsConfig::Processings> processings(
+ [&]() -> std::shared_ptr<const effectsConfig::Processings> {
+ std::vector<effectsConfig::InputStream> preprocess;
+ std::vector<effectsConfig::OutputStream> postprocess;
+ for (const auto& processing : mAidlProcessings) {
+ getConfigProcessingWithAidlProcessing(processing, preprocess, postprocess);
+ }
+
+ if (0 == preprocess.size() && 0 == postprocess.size()) {
+ return nullptr;
+ }
+
+ return std::make_shared<const effectsConfig::Processings>(
+ effectsConfig::Processings({.preprocess = std::move(preprocess),
+ .postprocess = std::move(postprocess)}));
+ }());
+
+ return processings;
}
+// Return 0 for AIDL, as the AIDL interface is not aware of the configuration file.
::android::error::Result<size_t> EffectsFactoryHalAidl::getSkippedElements() const {
- if (!mEffectProcessings) {
- return ::android::base::unexpected(BAD_VALUE);
- }
-
- // Only return 0 for AIDL, because the AIDL interface doesn't aware of configuration file
return 0;
}
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
index 70a7012..39beea2 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -21,6 +21,7 @@
#include <mutex>
#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <aidl/android/hardware/audio/effect/Processing.h>
#include <android-base/thread_annotations.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <system/thread_defs.h>
@@ -82,7 +83,7 @@
// total number of effects including proxy effects
const size_t mEffectCount;
// Query result of pre and post processing from effect factory
- const std::shared_ptr<const effectsConfig::Processings> mEffectProcessings;
+ const std::vector<Processing> mAidlProcessings;
std::mutex mLock;
uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0; // Align with HIDL (0 is INVALID_ID)
diff --git a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
index c076ccc..63f895f 100644
--- a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
+++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
@@ -15,6 +15,7 @@
*/
//#define LOG_NDEBUG 0
+#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstring>
@@ -92,6 +93,47 @@
}
}
+TEST(libAudioHalTest, getProcessings) {
+ auto factory = EffectsFactoryHalInterface::create();
+ ASSERT_NE(nullptr, factory);
+
+ const auto &processings = factory->getProcessings();
+ if (processings) {
+ EXPECT_NE(0UL, processings->preprocess.size() + processings->postprocess.size() +
+ processings->deviceprocess.size());
+
+ auto processingChecker = [](const auto& processings) {
+ if (processings.size() != 0) {
+ // any process need at least 1 effect inside
+ std::for_each(processings.begin(), processings.end(), [](const auto& process) {
+ EXPECT_NE(0ul, process.effects.size());
+ // any effect should have a valid name string, and not proxy
+ for (const auto& effect : process.effects) {
+ SCOPED_TRACE("Effect: {" +
+ (effect == nullptr
+ ? "NULL}"
+ : ("{name: " + effect->name + ", isproxy: " +
+ (effect->isProxy ? "true" : "false") + ", sw: " +
+ (effect->libSw ? "non-null" : "null") + ", hw: " +
+ (effect->libHw ? "non-null" : "null") + "}")));
+ EXPECT_NE(nullptr, effect);
+ EXPECT_NE("", effect->name);
+ EXPECT_EQ(false, effect->isProxy);
+ EXPECT_EQ(nullptr, effect->libSw);
+ EXPECT_EQ(nullptr, effect->libHw);
+ }
+ });
+ }
+ };
+
+ processingChecker(processings->preprocess);
+ processingChecker(processings->postprocess);
+ processingChecker(processings->deviceprocess);
+ } else {
+ GTEST_SKIP() << "no processing found, skipping the test";
+ }
+}
+
TEST(libAudioHalTest, getHalVersion) {
auto factory = EffectsFactoryHalInterface::create();
ASSERT_NE(nullptr, factory);