Loading media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h +5 −0 Original line number Diff line number Diff line Loading @@ -288,6 +288,11 @@ aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOut 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> Loading media/libaudioclient/include/media/AidlConversion.h +0 −5 Original line number Diff line number Diff line Loading @@ -72,11 +72,6 @@ status_t legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt( 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); Loading media/libaudiohal/impl/EffectsFactoryHalAidl.cpp +79 −7 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ using ::aidl::android::aidl_utils::statusTFromBinderStatus; 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; Loading Loading @@ -96,7 +98,13 @@ EffectsFactoryHalAidl::EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFa 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()); Loading Loading @@ -274,15 +282,79 @@ bool EffectsFactoryHalAidl::isProxyEffect(const AudioUuid& uuid) const { } 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; } ::android::error::Result<size_t> EffectsFactoryHalAidl::getSkippedElements() const { if (!mEffectProcessings) { return ::android::base::unexpected(BAD_VALUE); return std::make_shared<const effectsConfig::Processings>( effectsConfig::Processings({.preprocess = std::move(preprocess), .postprocess = std::move(postprocess)})); }()); return processings; } // Only return 0 for AIDL, because the AIDL interface doesn't aware of configuration file // Return 0 for AIDL, as the AIDL interface is not aware of the configuration file. ::android::error::Result<size_t> EffectsFactoryHalAidl::getSkippedElements() const { return 0; } Loading media/libaudiohal/impl/EffectsFactoryHalAidl.h +2 −1 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -82,7 +83,7 @@ class EffectsFactoryHalAidl final : public EffectsFactoryHalInterface { // 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) Loading media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp +42 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ //#define LOG_NDEBUG 0 #include <algorithm> #include <cstddef> #include <cstdint> #include <cstring> Loading Loading @@ -92,6 +93,47 @@ TEST(libAudioHalTest, createEffect) { } } 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); Loading Loading
media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h +5 −0 Original line number Diff line number Diff line Loading @@ -288,6 +288,11 @@ aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOut 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> Loading
media/libaudioclient/include/media/AidlConversion.h +0 −5 Original line number Diff line number Diff line Loading @@ -72,11 +72,6 @@ status_t legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt( 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); Loading
media/libaudiohal/impl/EffectsFactoryHalAidl.cpp +79 −7 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ using ::aidl::android::aidl_utils::statusTFromBinderStatus; 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; Loading Loading @@ -96,7 +98,13 @@ EffectsFactoryHalAidl::EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFa 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()); Loading Loading @@ -274,15 +282,79 @@ bool EffectsFactoryHalAidl::isProxyEffect(const AudioUuid& uuid) const { } 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; } ::android::error::Result<size_t> EffectsFactoryHalAidl::getSkippedElements() const { if (!mEffectProcessings) { return ::android::base::unexpected(BAD_VALUE); return std::make_shared<const effectsConfig::Processings>( effectsConfig::Processings({.preprocess = std::move(preprocess), .postprocess = std::move(postprocess)})); }()); return processings; } // Only return 0 for AIDL, because the AIDL interface doesn't aware of configuration file // Return 0 for AIDL, as the AIDL interface is not aware of the configuration file. ::android::error::Result<size_t> EffectsFactoryHalAidl::getSkippedElements() const { return 0; } Loading
media/libaudiohal/impl/EffectsFactoryHalAidl.h +2 −1 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -82,7 +83,7 @@ class EffectsFactoryHalAidl final : public EffectsFactoryHalInterface { // 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) Loading
media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp +42 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ //#define LOG_NDEBUG 0 #include <algorithm> #include <cstddef> #include <cstdint> #include <cstring> Loading Loading @@ -92,6 +93,47 @@ TEST(libAudioHalTest, createEffect) { } } 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); Loading