From 665c2a264dc6cf9523e9920a56123833203fd95b Mon Sep 17 00:00:00 2001 From: linyuanpeng Date: Mon, 17 Apr 2023 22:05:39 +0800 Subject: [PATCH] audio effect manager v1.0 Signed-off-by: linyuanpeng --- README.md | 2 +- .../native/audiocommon/include/audio_info.h | 47 ++ services/audio_policy/BUILD.gn | 48 +- .../server/config/audio_effect_config.xml | 58 ++ .../server/include/audio_policy_server.h | 1 + .../server/include/audio_service_dump.h | 4 + .../include/service/audio_policy_service.h | 13 +- .../effect/audio_effect_config_parser.h | 41 ++ .../service/effect/audio_effect_manager.h | 44 ++ .../server/src/audio_policy_server.cpp | 10 +- .../src/service/audio_policy_service.cpp | 32 +- .../src/service/dump/audio_service_dump.cpp | 77 +++ .../effect/audio_effect_config_parser.cpp | 634 ++++++++++++++++++ .../service/effect/audio_effect_manager.cpp | 56 ++ services/audio_service/BUILD.gn | 3 + .../client/include/audio_manager_base.h | 8 + .../client/include/audio_manager_proxy.h | 3 + .../client/src/audio_manager_proxy.cpp | 51 ++ .../server/include/audio_effect_server.h | 115 ++++ .../server/include/audio_server.h | 4 + .../server/src/audio_effect_server.cpp | 193 ++++++ .../server/src/audio_manager_stub.cpp | 54 +- .../audio_service/server/src/audio_server.cpp | 26 +- 23 files changed, 1489 insertions(+), 35 deletions(-) create mode 100644 services/audio_policy/server/config/audio_effect_config.xml create mode 100644 services/audio_policy/server/include/service/effect/audio_effect_config_parser.h create mode 100644 services/audio_policy/server/include/service/effect/audio_effect_manager.h create mode 100644 services/audio_policy/server/src/service/effect/audio_effect_config_parser.cpp create mode 100644 services/audio_policy/server/src/service/effect/audio_effect_manager.cpp create mode 100644 services/audio_service/server/include/audio_effect_server.h create mode 100644 services/audio_service/server/src/audio_effect_server.cpp diff --git a/README.md b/README.md index e524c727bf..5c82c98fa8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Audio - + ## Introduction The audio framework is used to implement audio-related features, including audio playback, audio recording, volume management, and device management. diff --git a/interfaces/inner_api/native/audiocommon/include/audio_info.h b/interfaces/inner_api/native/audiocommon/include/audio_info.h index 9d84c21887..329bf7d2bc 100644 --- a/interfaces/inner_api/native/audiocommon/include/audio_info.h +++ b/interfaces/inner_api/native/audiocommon/include/audio_info.h @@ -957,6 +957,53 @@ enum StateChangeCmdType { CMD_FROM_CLIENT = 0, CMD_FROM_SYSTEM = 1 }; + +// audio effect manager info +constexpr int32_t COUNT_UPPER_LIMIT = 20; +constexpr int32_t COUNT_FIRST_NODE_UPPER_LIMIT = 1; + +struct Library { + std::string name; + std::string path; +}; + +struct Effect { + std::string name; + std::string libraryName; + std::string effectId; +}; + +struct EffectChain { + std::string name; + std::vector apply; +}; + +struct Device { + std::string type; + std::string address; + std::string chain; +}; + +struct Preprocess { + std::string stream; + std::vector mode; + std::vector> device; +}; + +struct Postprocess { + std::string stream; + std::vector mode; + std::vector> device; +}; + +struct OriginalEffectConfig { + float version; + std::vector libraries; + std::vector effects; + std::vector effectChains; + std::vector preprocess; + std::vector postprocess; +}; } // namespace AudioStandard } // namespace OHOS #endif // AUDIO_INFO_H diff --git a/services/audio_policy/BUILD.gn b/services/audio_policy/BUILD.gn index a96081bebe..5944c0d057 100644 --- a/services/audio_policy/BUILD.gn +++ b/services/audio_policy/BUILD.gn @@ -22,6 +22,7 @@ pulseaudio_build_path = "//third_party/pulseaudio/ohosbuild" group("audio_policy_packages") { deps = [ ":audio_dump", + ":audio_effect_config", ":audio_interrupt_policy_config", ":audio_policy_init", ":audio_policy_service", @@ -38,24 +39,25 @@ ohos_prebuilt_etc("audio_policy_init") { config("audio_policy_public_config") { include_dirs = [ - "//foundation/multimedia/audio_framework/services/audio_service/client/include", - "//foundation/multimedia/audio_framework/services/audio_service/common/include", - "//foundation/multimedia/audio_framework/frameworks/native/audiorenderer/include", - "//foundation/multimedia/audio_framework/frameworks/native/audioadapter/include", - "//foundation/multimedia/audio_framework/frameworks/native/audiopolicy/include", - "//foundation/multimedia/audio_framework/frameworks/native/audioutils/include", - "//foundation/multimedia/audio_framework/frameworks/native/bluetoothclient", - "//foundation/multimedia/audio_framework/interfaces/inner_api/native/audiocommon/include", - "//foundation/multimedia/audio_framework/interfaces/inner_api/native/audiomanager/include", - "//foundation/multimedia/audio_framework/services/audio_policy/server/include/service/common", - "//foundation/multimedia/audio_framework/services/audio_policy/server/include/service/config", - "//foundation/multimedia/audio_framework/services/audio_policy/server/include/service/interface", - "//foundation/multimedia/audio_framework/services/audio_policy/server/include/service/listener", - "//foundation/multimedia/audio_framework/services/audio_policy/server/include/service/manager", - "//foundation/multimedia/audio_framework/services/audio_policy/server/include/service", - "//foundation/multimedia/audio_framework/services/audio_policy/common/include", - "//foundation/multimedia/audio_framework/services/audio_policy/server/include", - "//foundation/multimedia/audio_framework/services/audio_policy/client/include", + "${audio_fwk_path}/services/audio_service/client/include", + "${audio_fwk_path}/services/audio_service/common/include", + "${audio_fwk_path}/frameworks/native/audiorenderer/include", + "${audio_fwk_path}/frameworks/native/audioadapter/include", + "${audio_fwk_path}/frameworks/native/audiopolicy/include", + "${audio_fwk_path}/frameworks/native/audioutils/include", + "${audio_fwk_path}/frameworks/native/bluetoothclient", + "${audio_fwk_path}/interfaces/inner_api/native/audiocommon/include", + "${audio_fwk_path}/interfaces/inner_api/native/audiomanager/include", + "${audio_fwk_path}/services/audio_policy/server/include/service/common", + "${audio_fwk_path}/services/audio_policy/server/include/service/config", + "${audio_fwk_path}/services/audio_policy/server/include/service/effect", + "${audio_fwk_path}/services/audio_policy/server/include/service/interface", + "${audio_fwk_path}/services/audio_policy/server/include/service/listener", + "${audio_fwk_path}/services/audio_policy/server/include/service/manager", + "${audio_fwk_path}/services/audio_policy/server/include/service", + "${audio_fwk_path}/services/audio_policy/common/include", + "${audio_fwk_path}/services/audio_policy/server/include", + "${audio_fwk_path}/services/audio_policy/client/include", ] cflags = [ @@ -146,6 +148,8 @@ ohos_shared_library("audio_policy_service") { "server/src/service/config/audio_focus_parser.cpp", "server/src/service/config/audio_tone_parser.cpp", "server/src/service/config/xml_parser.cpp", + "server/src/service/effect/audio_effect_config_parser.cpp", + "server/src/service/effect/audio_effect_manager.cpp", "server/src/service/listener/device_status_listener.cpp", "server/src/service/manager/audio_adapter_manager.cpp", ] @@ -235,6 +239,14 @@ ohos_prebuilt_etc("audio_tone_dtmf_config") { part_name = "multimedia_audio_framework" } +ohos_prebuilt_etc("audio_effect_config") { + source = "server/config/audio_effect_config.xml" + + subsystem_name = "multimedia" + relative_install_dir = "audio" + part_name = "audio_framework" +} + ohos_prebuilt_etc("audio_config.para") { source = "//foundation/multimedia/audio_framework/services/audio_policy/etc/audio_config.para" part_name = "multimedia_audio_framework" diff --git a/services/audio_policy/server/config/audio_effect_config.xml b/services/audio_policy/server/config/audio_effect_config.xml new file mode 100644 index 0000000000..db4472431c --- /dev/null +++ b/services/audio_policy/server/config/audio_effect_config.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/services/audio_policy/server/include/audio_policy_server.h b/services/audio_policy/server/include/audio_policy_server.h index 5fd49b6b7c..2d3a95a6c3 100644 --- a/services/audio_policy/server/include/audio_policy_server.h +++ b/services/audio_policy/server/include/audio_policy_server.h @@ -290,6 +290,7 @@ private: void SubscribeKeyEvents(); void InitKVStore(); void ConnectServiceAdapter(); + void LoadEffectLibrary(); void RegisterBluetoothListener(); void SubscribeAccessibilityConfigObserver(); diff --git a/services/audio_policy/server/include/audio_service_dump.h b/services/audio_policy/server/include/audio_service_dump.h index f2b8c6f490..130ded71ce 100644 --- a/services/audio_policy/server/include/audio_service_dump.h +++ b/services/audio_policy/server/include/audio_service_dump.h @@ -27,6 +27,7 @@ #include "securec.h" #include "audio_log.h" #include "nocopyable.h" +#include "audio_effect_manager.h" namespace OHOS { namespace AudioStandard { @@ -79,6 +80,8 @@ typedef struct { AudioInterrupt audioFocusInfo; std::list> audioFocusInfoList; std::vector groupInfos; + OriginalEffectConfig oriEffectConfig; + std::vector availableEffects; } PolicyData; typedef struct { @@ -119,6 +122,7 @@ private: void DevicesInfoDump(std::string &dumpString); void AudioFocusInfoDump(std::string &dumpString); void GroupInfoDump(std::string& dumpString); + void EffectManagerInfoDump(std::string& dumpString); void DataDump(std::string &dumpString); static const std::string GetStreamName(AudioStreamType streamType); static const std::string GetSourceName(SourceType sourceType); diff --git a/services/audio_policy/server/include/service/audio_policy_service.h b/services/audio_policy/server/include/service/audio_policy_service.h index 8333456668..8e5f03250d 100644 --- a/services/audio_policy/server/include/service/audio_policy_service.h +++ b/services/audio_policy/server/include/service/audio_policy_service.h @@ -37,6 +37,7 @@ #include "iaudio_policy_interface.h" #include "iport_observer.h" #include "parser_factory.h" +#include "audio_effect_manager.h" namespace OHOS { namespace AudioStandard { @@ -162,6 +163,8 @@ public: void OnAudioBalanceChanged(float audioBalance); + void LoadEffectLibrary(); + int32_t SetAudioSessionCallback(AudioSessionCallback *callback); int32_t SetDeviceChangeCallback(const int32_t clientId, const DeviceFlag flag, const sptr &object); @@ -220,11 +223,14 @@ public: std::vector> GetPreferOutputDeviceDescriptors(AudioRendererInfo &rendererInfo, std::string networkId = LOCAL_NETWORK_ID); + void GetEffectManagerInfo(OriginalEffectConfig& oriEffectConfig, std::vector& availableEffects); + private: AudioPolicyService() - : audioPolicyManager_(AudioPolicyManagerFactory::GetAudioPolicyManager()), - configParser_(ParserFactory::GetInstance().CreateParser(*this)), - streamCollector_(AudioStreamCollector::GetAudioStreamCollector()) + :audioPolicyManager_(AudioPolicyManagerFactory::GetAudioPolicyManager()), + configParser_(ParserFactory::GetInstance().CreateParser(*this)), + streamCollector_(AudioStreamCollector::GetAudioStreamCollector()), + audioEffectManager_(AudioEffectManager::GetAudioEffectManager()) { #ifdef ACCESSIBILITY_ENABLE accessibilityConfigListener_ = std::make_shared(*this); @@ -379,6 +385,7 @@ private: std::vector> interruptGroups_; std::unordered_map volumeGroupData_; std::unordered_map interruptGroupData_; + AudioEffectManager& audioEffectManager_; }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_policy/server/include/service/effect/audio_effect_config_parser.h b/services/audio_policy/server/include/service/effect/audio_effect_config_parser.h new file mode 100644 index 0000000000..3c8a168195 --- /dev/null +++ b/services/audio_policy/server/include/service/effect/audio_effect_config_parser.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. +*/ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * 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. + */ +#ifndef AUDIO_EFFECT_CONFIG_PARSER_H +#define AUDIO_EFFECT_CONFIG_PARSER_H + +#include +#include +#include +#include +#include +#include +#include "audio_log.h" +#include "audio_info.h" + +namespace OHOS { +namespace AudioStandard { + +class AudioEffectConfigParser { +public: + explicit AudioEffectConfigParser(); + ~AudioEffectConfigParser(); + int32_t LoadEffectConfig(OriginalEffectConfig &result); +}; +} // namespace AudioStandard +} // namespace OHOS +#endif // AUDIO_EFFECT_CONFIG_PARSER_H \ No newline at end of file diff --git a/services/audio_policy/server/include/service/effect/audio_effect_manager.h b/services/audio_policy/server/include/service/effect/audio_effect_manager.h new file mode 100644 index 0000000000..3fc2360c4b --- /dev/null +++ b/services/audio_policy/server/include/service/effect/audio_effect_manager.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef ST_AUDIO_EFFECT_MANAGER_H +#define ST_AUDIO_EFFECT_MANAGER_H + +#include "audio_log.h" +#include "audio_effect_config_parser.h" + +namespace OHOS { +namespace AudioStandard { +class AudioEffectManager { +public: + explicit AudioEffectManager(); + ~AudioEffectManager(); + static AudioEffectManager& GetAudioEffectManager() + { + static AudioEffectManager audioEffectManager; + return audioEffectManager; + } + void EffectManagerInit(); + void GetOriginalEffectConfig(OriginalEffectConfig &oriEffectConfig); + void GetAvailableEffects(std::vector &availableEffects); + void UpdateAvailableEffects(std::vector &newAvailableEffects); + +private: + OriginalEffectConfig oriEffectConfig_; + std::vector availableEffects_; +}; +} // namespce AudioStandard +} // namespace OHOS +#endif // ST_AUDIO_EFFECT_MANAGER_H \ No newline at end of file diff --git a/services/audio_policy/server/src/audio_policy_server.cpp b/services/audio_policy/server/src/audio_policy_server.cpp index 9a7956ebd1..4a4a85002a 100644 --- a/services/audio_policy/server/src/audio_policy_server.cpp +++ b/services/audio_policy/server/src/audio_policy_server.cpp @@ -91,7 +91,6 @@ void AudioPolicyServer::OnStart() { AUDIO_INFO_LOG("AudioPolicyService OnStart"); mPolicyService.Init(); - AddSystemAbilityListener(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); AddSystemAbilityListener(MULTIMODAL_INPUT_SERVICE_ID); AddSystemAbilityListener(AUDIO_DISTRIBUTED_SERVICE_ID); @@ -135,6 +134,7 @@ void AudioPolicyServer::OnAddSystemAbility(int32_t systemAbilityId, const std::s AUDIO_INFO_LOG("OnAddSystemAbility audio service start"); ConnectServiceAdapter(); RegisterParamCallback(); + LoadEffectLibrary(); break; case BLUETOOTH_HOST_SYS_ABILITY_ID: AUDIO_INFO_LOG("OnAddSystemAbility bluetooth service start"); @@ -245,6 +245,11 @@ void AudioPolicyServer::ConnectServiceAdapter() } } +void AudioPolicyServer::LoadEffectLibrary() +{ + mPolicyService.LoadEffectLibrary(); +} + int32_t AudioPolicyServer::GetMaxVolumeLevel(AudioVolumeType volumeType) { return mPolicyService.GetMaxVolumeLevel(volumeType); @@ -1405,6 +1410,9 @@ void AudioPolicyServer::GetPolicyData(PolicyData &policyData) policyData.audioFocusInfoList = audioFocusInfoList_; GetDeviceInfo(policyData); GetGroupInfo(policyData); + + // Get Audio Effect Manager Information + mPolicyService.GetEffectManagerInfo(policyData.oriEffectConfig, policyData.availableEffects); } void AudioPolicyServer::GetDeviceInfo(PolicyData& policyData) diff --git a/services/audio_policy/server/src/service/audio_policy_service.cpp b/services/audio_policy/server/src/service/audio_policy_service.cpp index 2d8bf1bb87..8660a853b0 100644 --- a/services/audio_policy/server/src/service/audio_policy_service.cpp +++ b/services/audio_policy/server/src/service/audio_policy_service.cpp @@ -57,6 +57,8 @@ bool AudioPolicyService::Init(void) AUDIO_INFO_LOG("AudioPolicyService init"); serviceFlag_.reset(); audioPolicyManager_.Init(); + audioEffectManager_.EffectManagerInit(); + if (!configParser_.LoadConfiguration()) { AUDIO_ERR_LOG("Audio Config Load Configuration failed"); return false; @@ -1525,7 +1527,8 @@ void AudioPolicyService::UpdateDisplayName(sptr deviceDes }; } else { std::vector deviceList; - if (DistributedHardware::DeviceManager::GetInstance().GetTrustedDeviceList(AUDIO_SERVICE_PKG, "", deviceList) == SUCCESS) { + if (DistributedHardware::DeviceManager::GetInstance().GetTrustedDeviceList(AUDIO_SERVICE_PKG, "", deviceList) == + SUCCESS) { for (auto deviceInfo : deviceList) { std::string strNetworkId(deviceInfo.networkId); if (strNetworkId == deviceDescriptor->networkId_) { @@ -1677,6 +1680,33 @@ void AudioPolicyService::OnAudioBalanceChanged(float audioBalance) gsp->SetAudioBalanceValue(audioBalance); } +void AudioPolicyService::LoadEffectLibrary() +{ + // IPC -> audioservice load library + const sptr gsp = GetAudioPolicyServiceProxy(); + if (gsp == nullptr) { + AUDIO_ERR_LOG("Service proxy unavailable: g_adProxy null"); + return; + } + OriginalEffectConfig oriEffectConfig = {}; + audioEffectManager_.GetOriginalEffectConfig(oriEffectConfig); + vector successLoadedEffects; + bool loadSuccess = gsp->LoadAudioEffectLibraries(oriEffectConfig.libraries, + oriEffectConfig.effects, + successLoadedEffects); + if (!loadSuccess) { + AUDIO_ERR_LOG("Load audio effect failed, please check log"); + } + audioEffectManager_.UpdateAvailableEffects(successLoadedEffects); +} + +void AudioPolicyService::GetEffectManagerInfo(OriginalEffectConfig& oriEffectConfig, + std::vector& availableEffects) +{ + audioEffectManager_.GetOriginalEffectConfig(oriEffectConfig); + audioEffectManager_.GetAvailableEffects(availableEffects); +} + void AudioPolicyService::AddAudioDevice(AudioModuleInfo& moduleInfo, InternalDeviceType devType) { // add new device into active device list diff --git a/services/audio_policy/server/src/service/dump/audio_service_dump.cpp b/services/audio_policy/server/src/service/dump/audio_service_dump.cpp index 568c030fb4..5e115f47b1 100644 --- a/services/audio_policy/server/src/service/dump/audio_service_dump.cpp +++ b/services/audio_policy/server/src/service/dump/audio_service_dump.cpp @@ -542,6 +542,82 @@ void AudioServiceDump::DevicesInfoDump(string& dumpString) GetDeviceTypeName(audioData_.policyData.priorityInputDevice).c_str()); } +static void EffectManagerInfoDumpPart(string& dumpString, AudioData &audioData_) +{ + int32_t count; + // xml -- Preprocess + for (Preprocess x : audioData_.policyData.oriEffectConfig.preprocess) { + AppendFormat(dumpString, "preprocess stream = %s \n", x.stream.c_str()); + count = 0; + for (string modeName : x.mode) { + count++; + AppendFormat(dumpString, " modeName%d = %s \n", count, modeName.c_str()); + for (Device deviceInfo : x.device[count - 1]) { + AppendFormat(dumpString, " device type = %s \n", deviceInfo.type.c_str()); + AppendFormat(dumpString, " device address = %s \n", deviceInfo.address.c_str()); + AppendFormat(dumpString, " device chain = %s \n", deviceInfo.chain.c_str()); + } + } + } + + // xml -- Postprocess + for (Postprocess x : audioData_.policyData.oriEffectConfig.postprocess) { + AppendFormat(dumpString, "postprocess stream = %s \n", x.stream.c_str()); + count = 0; + for (string modeName : x.mode) { + count++; + AppendFormat(dumpString, " modeName%d = %s \n", count, modeName.c_str()); + for (Device deviceInfo : x.device[count - 1]) { + AppendFormat(dumpString, " device type = %s \n", deviceInfo.type.c_str()); + AppendFormat(dumpString, " device address = %s \n", deviceInfo.address.c_str()); + AppendFormat(dumpString, " device chain = %s \n", deviceInfo.chain.c_str()); + } + } + } +} + +void AudioServiceDump::EffectManagerInfoDump(string& dumpString) +{ + int count = 0; + dumpString += "\n Effect Manager INFO: \n"; + AppendFormat(dumpString, "XML version:%f \n", audioData_.policyData.oriEffectConfig.version); + // xml -- Library + for (Library x : audioData_.policyData.oriEffectConfig.libraries) { + count++; + AppendFormat(dumpString, "library%d name = %s \n", count, x.name.c_str()); + AppendFormat(dumpString, "library%d path = %s \n", count, x.path.c_str()); + } + // xml -- effect + count = 0; + for (Effect x : audioData_.policyData.oriEffectConfig.effects) { + count++; + AppendFormat(dumpString, "effect%d name = %s \n", count, x.name.c_str()); + AppendFormat(dumpString, "effect%d libraryName = %s \n", count, x.libraryName.c_str()); + AppendFormat(dumpString, "effect%d effectId = %s \n", count, x.effectId.c_str()); + } + + // xml -- effectChain + for (EffectChain x : audioData_.policyData.oriEffectConfig.effectChains) { + AppendFormat(dumpString, "effectChain name = %s \n", x.name.c_str()); + count = 0; + for (string effectUnit : x.apply) { + count++; + AppendFormat(dumpString, " effectUnit%d = %s \n", count, effectUnit.c_str()); + } + } + + EffectManagerInfoDumpPart(dumpString, audioData_); + + // successful lib + count = 0; + for (Effect x : audioData_.policyData.availableEffects) { + count++; + AppendFormat(dumpString, "available Effect%d name = %s \n", count, x.name.c_str()); + AppendFormat(dumpString, "available Effect%d libraryName = %s \n", count, x.libraryName.c_str()); + AppendFormat(dumpString, "available Effect%d effectId = %s \n", count, x.effectId.c_str()); + } +} + void AudioServiceDump::DataDump(string &dumpString) { PlaybackStreamDump(dumpString); @@ -553,6 +629,7 @@ void AudioServiceDump::DataDump(string &dumpString) StreamVolumesDump(dumpString); AudioFocusInfoDump(dumpString); GroupInfoDump(dumpString); + EffectManagerInfoDump(dumpString); } void AudioServiceDump::AudioDataDump(PolicyData &policyData, string &dumpString) diff --git a/services/audio_policy/server/src/service/effect/audio_effect_config_parser.cpp b/services/audio_policy/server/src/service/effect/audio_effect_config_parser.cpp new file mode 100644 index 0000000000..0798c52b0f --- /dev/null +++ b/services/audio_policy/server/src/service/effect/audio_effect_config_parser.cpp @@ -0,0 +1,634 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * 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 "audio_effect_config_parser.h" +#include +#include + +namespace OHOS { +namespace AudioStandard { +static constexpr char AUDIO_EFFECT_CONFIG_FILE[] = "system/etc/audio/audio_effect_config.xml"; +static const std::string EFFECT_CONFIG_NAME[5] = {"libraries", "effects", "effectChains", "preprocess", "postprocess"}; +static constexpr int32_t FILE_CONTENT_ERROR = -2; +static constexpr int32_t FILE_PARSE_ERROR = -3; +static constexpr int32_t INDEX_LIBRARIES = 0; +static constexpr int32_t INDEX_EFFECS = 1; +static constexpr int32_t INDEX_EFFECTCHAINE = 2; +static constexpr int32_t INDEX_PREPROCESS = 3; +static constexpr int32_t INDEX_POSTPROCESS = 4; +static constexpr int32_t INDEX_EXCEPTION = 5; +static constexpr int32_t NODE_SIZE = 6; + +AudioEffectConfigParser::AudioEffectConfigParser() +{ + AUDIO_INFO_LOG("AudioEffectConfigParser created"); +} + +AudioEffectConfigParser::~AudioEffectConfigParser() +{ +} + +static int32_t LoadConfigCheck(xmlDoc* doc, xmlNode* currNode) +{ + if (xmlStrcmp(currNode->name, reinterpret_cast("audio_effects_conf"))) { + AUDIO_ERR_LOG("Missing tag - audio_effects_conf: %{public}s", AUDIO_EFFECT_CONFIG_FILE); + xmlFreeDoc(doc); + xmlCleanupParser(); + return FILE_CONTENT_ERROR; + } + + if (currNode->xmlChildrenNode) { + return 0; + } else { + AUDIO_ERR_LOG("Missing node - audio_effects_conf: %s", AUDIO_EFFECT_CONFIG_FILE); + xmlFreeDoc(doc); + xmlCleanupParser(); + return FILE_CONTENT_ERROR; + } +} + +static void LoadConfigVersion(OriginalEffectConfig &result, xmlNode* currNode) +{ + if (!xmlHasProp(currNode, reinterpret_cast("version"))) { + AUDIO_ERR_LOG("missing information: audio_effects_conf node has no version attribute"); + return; + } + + float pVersion = atof(reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("version")))); + result.version = pVersion; +} + +static void LoadLibrary(OriginalEffectConfig &result, xmlNode* secondNode) +{ + xmlNode *currNode = secondNode; + int32_t countLibrary = 0; + while (currNode != nullptr) { + if (countLibrary >= COUNT_UPPER_LIMIT) { + AUDIO_ERR_LOG("the number of library nodes exceeds limit: %{public}d", COUNT_UPPER_LIMIT); + return; + } + if (currNode->type != XML_ELEMENT_NODE) { + currNode = currNode->next; + continue; + } + if (!xmlStrcmp(currNode->name, reinterpret_cast("library"))) { + if (!xmlHasProp(currNode, reinterpret_cast("name"))) { + AUDIO_ERR_LOG("missing information: library has no name attribute"); + } else if (!xmlHasProp(currNode, reinterpret_cast("path"))) { + AUDIO_ERR_LOG("missing information: library has no path attribute"); + } else { + std::string pLibName = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("name"))); + std::string pLibPath = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("path"))); + Library tmp = {pLibName, pLibPath}; + result.libraries.push_back(tmp); + } + } else { + AUDIO_ERR_LOG("wrong name: %{public}s, should be library", currNode->name); + } + countLibrary++; + currNode = currNode->next; + } + if (countLibrary == 0) { + AUDIO_ERR_LOG("missing information: libraries have no child library"); + } +} + +static void LoadEffectConfigLibraries(OriginalEffectConfig &result, const xmlNode* currNode, + int32_t (&countFirstNode)[NODE_SIZE]) +{ + if (countFirstNode[INDEX_LIBRARIES] >= COUNT_FIRST_NODE_UPPER_LIMIT) { + if (countFirstNode[INDEX_LIBRARIES] == COUNT_FIRST_NODE_UPPER_LIMIT) { + countFirstNode[INDEX_LIBRARIES]++; + AUDIO_ERR_LOG("the number of libraries nodes exceeds limit: %{public}d", COUNT_FIRST_NODE_UPPER_LIMIT); + } + } else if (currNode->xmlChildrenNode) { + LoadLibrary(result, currNode->xmlChildrenNode); + countFirstNode[INDEX_LIBRARIES]++; + } else { + AUDIO_ERR_LOG("missing information: libraries have no child library"); + countFirstNode[INDEX_LIBRARIES]++; + } +} + +static void LoadEffect(OriginalEffectConfig &result, xmlNode* secondNode) +{ + xmlNode *currNode = secondNode; + int32_t countEffect = 0; + while (currNode != nullptr) { + if (countEffect >= COUNT_UPPER_LIMIT) { + AUDIO_ERR_LOG("the number of effect nodes exceeds limit: %{public}d", COUNT_UPPER_LIMIT); + return; + } + if (currNode->type != XML_ELEMENT_NODE) { + currNode = currNode->next; + continue; + } + if (!xmlStrcmp(currNode->name, reinterpret_cast("effect"))) { + if (!xmlHasProp(currNode, reinterpret_cast("name"))) { + AUDIO_ERR_LOG("missing information: effect has no name attribute"); + } else if (!xmlHasProp(currNode, reinterpret_cast("library"))) { + AUDIO_ERR_LOG("missing information: effect has no library attribute"); + } else if (!xmlHasProp(currNode, reinterpret_cast("effect_id"))) { + AUDIO_ERR_LOG("missing information: effect has no effect_id attribute"); + } else { + std::string pEffectName = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("name"))); + std::string pEffectLib = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("library"))); + std::string pEffectID = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("effect_id"))); + Effect tmp = {pEffectName, pEffectLib, pEffectID}; + result.effects.push_back(tmp); + } + } else { + AUDIO_ERR_LOG("wrong name: %{public}s, should be effect", currNode->name); + } + countEffect++; + currNode = currNode->next; + } + if (countEffect == 0) { + AUDIO_ERR_LOG("missing information: effects have no child effect"); + } +} + +static void LoadEffectConfigEffects(OriginalEffectConfig &result, const xmlNode* currNode, + int32_t (&countFirstNode)[NODE_SIZE]) +{ + if (countFirstNode[INDEX_EFFECS] >= COUNT_FIRST_NODE_UPPER_LIMIT) { + if (countFirstNode[INDEX_EFFECS] == COUNT_FIRST_NODE_UPPER_LIMIT) { + countFirstNode[INDEX_EFFECS]++; + AUDIO_ERR_LOG("the number of effects nodes exceeds limit: %{public}d", COUNT_FIRST_NODE_UPPER_LIMIT); + } + } else if (currNode->xmlChildrenNode) { + LoadEffect(result, currNode->xmlChildrenNode); + countFirstNode[INDEX_EFFECS]++; + } else { + AUDIO_ERR_LOG("missing information: effects have no child effect"); + countFirstNode[INDEX_EFFECS]++; + } +} + +static void LoadApply(OriginalEffectConfig &result, const xmlNode* thirdNode, const int32_t segInx) +{ + if (!thirdNode->xmlChildrenNode) { + AUDIO_ERR_LOG("missing information: effectChain has no child apply"); + return; + } + int32_t countApply = 0; + xmlNode *currNode = thirdNode->xmlChildrenNode; + while (currNode != nullptr) { + if (countApply >= COUNT_UPPER_LIMIT) { + AUDIO_ERR_LOG("the number of apply nodes exceeds limit: %{public}d", COUNT_UPPER_LIMIT); + return; + } + if (currNode->type != XML_ELEMENT_NODE) { + currNode = currNode->next; + continue; + } + if (!xmlStrcmp(currNode->name, reinterpret_cast("apply"))) { + if (!xmlHasProp(currNode, reinterpret_cast("effect"))) { + AUDIO_ERR_LOG("missing information: apply has no effect attribute"); + } else { + std::string ppValue = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("effect"))); + result.effectChains[segInx].apply.push_back(ppValue); + } + } else { + AUDIO_ERR_LOG("wrong name: %{public}s, should be apply", currNode->name); + } + countApply++; + currNode = currNode->next; + } + if (countApply == 0) { + AUDIO_ERR_LOG("missing information: effectChain has no child apply"); + } +} + +static void LoadEffectChain(OriginalEffectConfig &result, xmlNode* secondNode) +{ + xmlNode *currNode = secondNode; + int32_t countEffectChain = 0; + int32_t segInx = 0; + std::vector apply; + while (currNode != nullptr) { + if (countEffectChain >= COUNT_UPPER_LIMIT) { + AUDIO_ERR_LOG("the number of effectChain nodes exceeds limit: %{public}d", COUNT_UPPER_LIMIT); + return; + } + if (currNode->type != XML_ELEMENT_NODE) { + currNode = currNode->next; + continue; + } + if (!xmlStrcmp(currNode->name, reinterpret_cast("effectChain"))) { + if (!xmlHasProp(currNode, reinterpret_cast("name"))) { + AUDIO_ERR_LOG("missing information: effectChain has no name attribute"); + } else { + std::string peffectChainName = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("name"))); + EffectChain tmp = {peffectChainName, apply}; + result.effectChains.push_back(tmp); + LoadApply(result, currNode, segInx); + segInx++; + } + } else { + AUDIO_ERR_LOG("wrong name: %{public}s, should be effectChain", currNode->name); + } + countEffectChain++; + currNode = currNode->next; + } + if (countEffectChain == 0) { + AUDIO_ERR_LOG("missing information: effectChains have no child effectChain"); + } +} + +static void LoadEffectConfigEffectChains(OriginalEffectConfig &result, const xmlNode* currNode, + int32_t (&countFirstNode)[NODE_SIZE]) +{ + if (countFirstNode[INDEX_EFFECTCHAINE] >= COUNT_FIRST_NODE_UPPER_LIMIT) { + if (countFirstNode[INDEX_EFFECTCHAINE] == COUNT_FIRST_NODE_UPPER_LIMIT) { + countFirstNode[INDEX_EFFECTCHAINE]++; + AUDIO_ERR_LOG("the number of effectChains nodes exceeds limit: %{public}d", COUNT_FIRST_NODE_UPPER_LIMIT); + } + } else if (currNode->xmlChildrenNode) { + LoadEffectChain(result, currNode->xmlChildrenNode); + countFirstNode[INDEX_EFFECTCHAINE]++; + } else { + AUDIO_ERR_LOG("missing information: effectChains have no child effectChain"); + countFirstNode[INDEX_EFFECTCHAINE]++; + } +} + +static void LoadPreDevice(OriginalEffectConfig &result, const xmlNode* fourthNode, + const int32_t modeNum, const int32_t streamNum) +{ + if (!fourthNode->xmlChildrenNode) { + AUDIO_ERR_LOG("missing information: streamAE_mode has no child devicePort"); + return; + } + int32_t countDevice = 0; + xmlNode *currNode = fourthNode->xmlChildrenNode; + while (currNode != nullptr) { + if (countDevice >= COUNT_UPPER_LIMIT) { + AUDIO_ERR_LOG("the number of devicePort nodes exceeds limit: %{public}d", COUNT_UPPER_LIMIT); + return; + } + if (currNode->type != XML_ELEMENT_NODE) { + currNode = currNode->next; + continue; + } + if (!xmlStrcmp(currNode->name, reinterpret_cast("devicePort"))) { + if (!xmlHasProp(currNode, reinterpret_cast("type"))) { + AUDIO_ERR_LOG("missing information: devicePort has no type attribute"); + } else if (!xmlHasProp(currNode, reinterpret_cast("address"))) { + AUDIO_ERR_LOG("missing information: devicePort has no address attribute"); + } else if (!xmlHasProp(currNode, reinterpret_cast("effectChain"))) { + AUDIO_ERR_LOG("missing information: devicePort has no effectChain attribute"); + } else { + std::string pDevType = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("type"))); + std::string pDevAddress = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("address"))); + std::string pChain = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("effectChain"))); + Device tmpdev = {pDevType, pDevAddress, pChain}; + result.preprocess[streamNum].device[modeNum].push_back(tmpdev); + } + } else { + AUDIO_ERR_LOG("wrong name: %{public}s, should be devicePort", currNode->name); + } + countDevice++; + currNode = currNode->next; + } + if (countDevice == 0) { + AUDIO_ERR_LOG("missing information: streamAE_mode has no child devicePort"); + } +} + +static void LoadPreMode(OriginalEffectConfig &result, const xmlNode* thirdNode, const int32_t streamNum) +{ + if (!thirdNode->xmlChildrenNode) { + AUDIO_ERR_LOG("missing information: stream has no child streamAE_mode"); + return; + } + int32_t countMode = 0; + int32_t modeNum = 0; + xmlNode *currNode = thirdNode->xmlChildrenNode; + while (currNode != nullptr) { + if (countMode >= COUNT_UPPER_LIMIT) { + AUDIO_ERR_LOG("the number of streamAE_mode nodes exceeds limit: %{public}d", COUNT_UPPER_LIMIT); + return; + } + if (currNode->type != XML_ELEMENT_NODE) { + currNode = currNode->next; + continue; + } + if (!xmlStrcmp(currNode->name, reinterpret_cast("streamAE_mode"))) { + if (!xmlHasProp(currNode, reinterpret_cast("mode"))) { + AUDIO_ERR_LOG("missing information: streamAE_mode has no mode attribute"); + } else { + std::string pStreamAEMode = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("mode"))); + result.preprocess[streamNum].mode.push_back(pStreamAEMode); + result.preprocess[streamNum].device.push_back({}); + LoadPreDevice(result, currNode, modeNum, streamNum); + modeNum++; + } + } else { + AUDIO_ERR_LOG("wrong name: %{public}s, should be streamAE_mode", currNode->name); + } + countMode++; + currNode = currNode->next; + } + if (countMode == 0) { + AUDIO_ERR_LOG("missing information: stream has no child streamAE_mode"); + } +} + +static void LoadPreProcess(OriginalEffectConfig &result, xmlNode* secondNode) +{ + std::string stream; + std::vector mode; + std::vector> device; + Preprocess tmp = {stream, mode, device}; + xmlNode *currNode = secondNode; + int32_t countPreprocess = 0; + int32_t streamNum = 0; + while (currNode != nullptr) { + if (countPreprocess >= COUNT_UPPER_LIMIT) { + AUDIO_ERR_LOG("the number of stream nodes exceeds limit: %{public}d", COUNT_UPPER_LIMIT); + return; + } + if (currNode->type != XML_ELEMENT_NODE) { + currNode = currNode->next; + continue; + } + if (!xmlStrcmp(currNode->name, reinterpret_cast("stream"))) { + if (!xmlHasProp(currNode, reinterpret_cast("scene"))) { + AUDIO_ERR_LOG("missing information: stream has no scene attribute"); + } else { + std::string pStreamType = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("scene"))); + tmp.stream = pStreamType; + result.preprocess.push_back(tmp); + LoadPreMode(result, currNode, streamNum); + streamNum++; + } + } else { + AUDIO_ERR_LOG("wrong name: %{public}s, should be stream", currNode->name); + } + countPreprocess++; + currNode = currNode->next; + } + if (countPreprocess == 0) { + AUDIO_ERR_LOG("missing information: preprocess has no child stream"); + } +} + +static void LoadEffectConfigPreProcess(OriginalEffectConfig &result, const xmlNode* currNode, + int32_t (&countFirstNode)[NODE_SIZE]) +{ + if (countFirstNode[INDEX_PREPROCESS] >= COUNT_FIRST_NODE_UPPER_LIMIT) { + if (countFirstNode[INDEX_PREPROCESS] == COUNT_FIRST_NODE_UPPER_LIMIT) { + countFirstNode[INDEX_PREPROCESS]++; + AUDIO_ERR_LOG("the number of preprocess nodes exceeds limit: %{public}d", COUNT_FIRST_NODE_UPPER_LIMIT); + } + } else if (currNode->xmlChildrenNode) { + LoadPreProcess(result, currNode->xmlChildrenNode); + countFirstNode[INDEX_PREPROCESS]++; + } else { + AUDIO_ERR_LOG("missing information: preprocess has no child stream"); + countFirstNode[INDEX_PREPROCESS]++; + } +} + +static void LoadPostDevice(OriginalEffectConfig &result, const xmlNode* fourthNode, + const int32_t modeNum, const int32_t streamNum) +{ + if (!fourthNode->xmlChildrenNode) { + AUDIO_ERR_LOG("missing information: streamAE_mode has no child devicePort"); + return; + } + int32_t countDevice = 0; + xmlNode *currNode = fourthNode->xmlChildrenNode; + while (currNode != nullptr) { + if (countDevice >= COUNT_UPPER_LIMIT) { + AUDIO_ERR_LOG("the number of devicePort nodes exceeds limit: %{public}d", COUNT_UPPER_LIMIT); + return; + } + if (currNode->type != XML_ELEMENT_NODE) { + currNode = currNode->next; + continue; + } + if (!xmlStrcmp(currNode->name, reinterpret_cast("devicePort"))) { + if (!xmlHasProp(currNode, reinterpret_cast("type"))) { + AUDIO_ERR_LOG("missing information: devicePort has no type attribute"); + } else if (!xmlHasProp(currNode, reinterpret_cast("address"))) { + AUDIO_ERR_LOG("missing information: devicePort has no address attribute"); + } else if (!xmlHasProp(currNode, reinterpret_cast("effectChain"))) { + AUDIO_ERR_LOG("missing information: devicePort has no effectChain attribute"); + } else { + std::string pDevType = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("type"))); + std::string pDevAddress = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("address"))); + std::string pChain = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("effectChain"))); + Device tmpdev = {pDevType, pDevAddress, pChain}; + result.postprocess[streamNum].device[modeNum].push_back(tmpdev); + } + } else { + AUDIO_ERR_LOG("wrong name: %{public}s, should be devicePort", currNode->name); + } + countDevice++; + currNode = currNode->next; + } + if (countDevice == 0) { + AUDIO_ERR_LOG("missing information: streamAE_mode has no child devicePort"); + } +} + +static void LoadPostMode(OriginalEffectConfig &result, const xmlNode* thirdNode, const int32_t streamNum) +{ + if (!thirdNode->xmlChildrenNode) { + AUDIO_ERR_LOG("missing information: stream has no child streamAE_mode"); + return; + } + int32_t countMode = 0; + int32_t modeNum = 0; + xmlNode *currNode = thirdNode->xmlChildrenNode; + while (currNode != nullptr) { + if (countMode >= COUNT_UPPER_LIMIT) { + AUDIO_ERR_LOG("the number of streamAE_mode nodes exceeds limit: %{public}d", COUNT_UPPER_LIMIT); + return; + } + if (currNode->type != XML_ELEMENT_NODE) { + currNode = currNode->next; + continue; + } + if (!xmlStrcmp(currNode->name, reinterpret_cast("streamAE_mode"))) { + if (!xmlHasProp(currNode, reinterpret_cast("mode"))) { + AUDIO_ERR_LOG("missing information: streamAE_mode has no mode attribute"); + } else { + std::string pStreamAEMode = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("mode"))); + result.postprocess[streamNum].mode.push_back(pStreamAEMode); + result.postprocess[streamNum].device.push_back({}); + LoadPostDevice(result, currNode, modeNum, streamNum); + modeNum++; + } + } else { + AUDIO_ERR_LOG("wrong name: %{public}s, should be streamAE_mode", currNode->name); + } + countMode++; + currNode = currNode->next; + } + if (countMode == 0) { + AUDIO_ERR_LOG("missing information: stream has no child streamAE_mode"); + } +} + +static void LoadPostProcess(OriginalEffectConfig &result, xmlNode* secondNode) +{ + std::string stream; + std::vector mode; + std::vector> device; + Postprocess tmp = {stream, mode, device}; + xmlNode *currNode = secondNode; + int32_t countPostprocess = 0; + int32_t streamNum = 0; + while (currNode != nullptr) { + if (countPostprocess >= COUNT_UPPER_LIMIT) { + AUDIO_ERR_LOG("the number of stream nodes exceeds limit: %{public}d", COUNT_UPPER_LIMIT); + return; + } + if (currNode->type != XML_ELEMENT_NODE) { + currNode = currNode->next; + continue; + } + if (!xmlStrcmp(currNode->name, reinterpret_cast("stream"))) { + if (!xmlHasProp(currNode, reinterpret_cast("scene"))) { + AUDIO_ERR_LOG("missing information: stream has no scene attribute"); + } else { + std::string pStreamType = reinterpret_cast + (xmlGetProp(currNode, reinterpret_cast("scene"))); + tmp.stream = pStreamType; + result.postprocess.push_back(tmp); + LoadPostMode(result, currNode, streamNum); + streamNum++; + } + } else { + AUDIO_ERR_LOG("wrong name: %{public}s, should be stream", currNode->name); + } + countPostprocess++; + currNode = currNode->next; + } + if (countPostprocess == 0) { + AUDIO_ERR_LOG("missing information: postprocess has no child stream"); + } +} + +static void LoadEffectConfigPostProcess(OriginalEffectConfig &result, const xmlNode* currNode, + int32_t (&countFirstNode)[NODE_SIZE]) +{ + if (countFirstNode[INDEX_POSTPROCESS] >= COUNT_FIRST_NODE_UPPER_LIMIT) { + if (countFirstNode[INDEX_POSTPROCESS] == COUNT_FIRST_NODE_UPPER_LIMIT) { + countFirstNode[INDEX_POSTPROCESS]++; + AUDIO_ERR_LOG("the number of postprocess nodes exceeds limit: %{public}d", COUNT_FIRST_NODE_UPPER_LIMIT); + } + } else if (currNode->xmlChildrenNode) { + LoadPostProcess(result, currNode->xmlChildrenNode); + countFirstNode[INDEX_POSTPROCESS]++; + } else { + AUDIO_ERR_LOG("missing information: postprocess has no child stream"); + countFirstNode[INDEX_POSTPROCESS]++; + } +} + +static void LoadEffectConfigException(OriginalEffectConfig &result, const xmlNode* currNode, + int32_t (&countFirstNode)[NODE_SIZE]) +{ + if (countFirstNode[INDEX_EXCEPTION] >= COUNT_UPPER_LIMIT) { + if (countFirstNode[INDEX_EXCEPTION] == COUNT_UPPER_LIMIT) { + countFirstNode[INDEX_EXCEPTION]++; + AUDIO_ERR_LOG("the number of nodes with wrong name exceeds limit: %{public}d", COUNT_UPPER_LIMIT); + } + } else { + AUDIO_ERR_LOG("wrong name: %{public}s", currNode->name); + countFirstNode[INDEX_EXCEPTION]++; + } +} + +int32_t AudioEffectConfigParser::LoadEffectConfig(OriginalEffectConfig &result) +{ + int32_t countFirstNode[NODE_SIZE] = {0}; + int32_t i = 0; + xmlDoc *doc = nullptr; + xmlNode *rootElement = nullptr; + AUDIO_INFO_LOG("AudioEffectParser::LoadConfig"); + if ((doc = xmlReadFile(AUDIO_EFFECT_CONFIG_FILE, nullptr, (1<<5) | (1<<6))) == nullptr) { // 5, 6: arguments + AUDIO_ERR_LOG("error: could not parse file %{public}s", AUDIO_EFFECT_CONFIG_FILE); + return FILE_PARSE_ERROR; + } + + rootElement = xmlDocGetRootElement(doc); + xmlNode *currNode = rootElement; + + if (LoadConfigCheck(doc, currNode) == 0) { + LoadConfigVersion(result, currNode); + currNode = currNode->xmlChildrenNode; + } else { + return FILE_CONTENT_ERROR; + } + + while (currNode != nullptr) { + if (currNode->type != XML_ELEMENT_NODE) { + currNode = currNode->next; + continue; + } + + if (!xmlStrcmp(currNode->name, reinterpret_cast("libraries"))) { + LoadEffectConfigLibraries(result, currNode, countFirstNode); + } else if (!xmlStrcmp(currNode->name, reinterpret_cast("effects"))) { + LoadEffectConfigEffects(result, currNode, countFirstNode); + } else if (!xmlStrcmp(currNode->name, reinterpret_cast("effectChains"))) { + LoadEffectConfigEffectChains(result, currNode, countFirstNode); + } else if (!xmlStrcmp(currNode->name, reinterpret_cast("preprocess"))) { + LoadEffectConfigPreProcess(result, currNode, countFirstNode); + } else if (!xmlStrcmp(currNode->name, reinterpret_cast("postprocess"))) { + LoadEffectConfigPostProcess(result, currNode, countFirstNode); + } else { + LoadEffectConfigException(result, currNode, countFirstNode); + } + + currNode = currNode->next; + } + + for (i = 0; i < 5; i++) { // 5: the number of modules + if (countFirstNode[i] == 0) { + AUDIO_ERR_LOG("missing information: %{public}s", EFFECT_CONFIG_NAME[i].c_str()); + } + } + + if (doc) { + xmlFreeDoc(doc); + xmlCleanupParser(); + } + + return 0; +} +} // namespace AudioStandard +} // namespace OHOS \ No newline at end of file diff --git a/services/audio_policy/server/src/service/effect/audio_effect_manager.cpp b/services/audio_policy/server/src/service/effect/audio_effect_manager.cpp new file mode 100644 index 0000000000..85e3853b6c --- /dev/null +++ b/services/audio_policy/server/src/service/effect/audio_effect_manager.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. + * 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 "audio_effect_manager.h" + +namespace OHOS { +namespace AudioStandard { +AudioEffectManager::AudioEffectManager() +{ + AUDIO_INFO_LOG("AudioEffectManager ctor"); +} + +AudioEffectManager::~AudioEffectManager() +{ +} + +void AudioEffectManager::EffectManagerInit() +{ + // load XML + std::unique_ptr effectConfigParser = std::make_unique(); + int32_t ret = effectConfigParser->LoadEffectConfig(oriEffectConfig_); + if (ret != 0) { + AUDIO_ERR_LOG("AudioEffectManager->effectConfigParser failed: %{public}d", ret); + return; + } +} + +void AudioEffectManager::GetAvailableEffects(std::vector &availableEffects) +{ + availableEffects = availableEffects_; +} + +void AudioEffectManager::GetOriginalEffectConfig(OriginalEffectConfig &oriEffectConfig) +{ + oriEffectConfig = oriEffectConfig_; +} + +void AudioEffectManager::UpdateAvailableEffects(std::vector &newAvailableEffects) +{ + availableEffects_ = newAvailableEffects; +} +} // namespce AudioStandard +} // namespace OHOS + \ No newline at end of file diff --git a/services/audio_service/BUILD.gn b/services/audio_service/BUILD.gn index d06e88c5e3..865639c045 100644 --- a/services/audio_service/BUILD.gn +++ b/services/audio_service/BUILD.gn @@ -134,6 +134,7 @@ ohos_shared_library("audio_client") { "$pulseaudio_dir/include", "$pulseaudio_build_path/include", "//third_party/bounds_checking_function/include", + "${audio_fwk_path}/services/audio_service/server/include", ] include_dirs += [ multimedia_audio_framework_pulse_audio ] @@ -181,6 +182,7 @@ config("audio_service_config") { "${fwk_native_hdiadapter_path}/source/common", "${fwk_native_hdiadapter_path}/source/primary", "//drivers/peripheral/audio/interfaces/include", + "${audio_fwk_path}/services/audio_policy/server/include/service/effect", ] if (target_cpu == "arm") { @@ -233,6 +235,7 @@ ohos_shared_library("audio_service") { install_enable = true sources = [ + "server/src/audio_effect_server.cpp", "server/src/audio_manager_listener_proxy.cpp", "server/src/audio_manager_stub.cpp", "server/src/audio_server.cpp", diff --git a/services/audio_service/client/include/audio_manager_base.h b/services/audio_service/client/include/audio_manager_base.h index 38ad57de33..59870554fc 100644 --- a/services/audio_service/client/include/audio_manager_base.h +++ b/services/audio_service/client/include/audio_manager_base.h @@ -177,6 +177,13 @@ public: * @return Returns AudioProcess client. */ virtual sptr CreateAudioProcess(const AudioProcessConfig &config) = 0; + /** + * use effect manager information to load effect libraries in audio_server + * + * @return true/false. + */ + virtual bool LoadAudioEffectLibraries(std::vector libraries, std::vector effects, + std::vector &successEffects) = 0; enum { GET_MAX_VOLUME = 0, @@ -199,6 +206,7 @@ public: SET_AUDIO_MONO_STATE = 17, SET_AUDIO_BALANCE_VALUE = 18, CREATE_AUDIOPROCESS = 19, + LOAD_AUDIO_EFFECT_LIBRARIES = 20, }; public: diff --git a/services/audio_service/client/include/audio_manager_proxy.h b/services/audio_service/client/include/audio_manager_proxy.h index ae1b9cfa48..c6a52e0a09 100644 --- a/services/audio_service/client/include/audio_manager_proxy.h +++ b/services/audio_service/client/include/audio_manager_proxy.h @@ -26,6 +26,7 @@ class AudioManagerProxy : public IRemoteProxy { public: explicit AudioManagerProxy(const sptr &impl); virtual ~AudioManagerProxy() = default; + int32_t SetMicrophoneMute(bool isMute) override; bool IsMicrophoneMute() override; int32_t SetVoiceVolume(float volume) override; @@ -46,6 +47,8 @@ public: void SetAudioMonoState(bool audioMono) override; void SetAudioBalanceValue(float audioBalance) override; sptr CreateAudioProcess(const AudioProcessConfig &config) override; + bool LoadAudioEffectLibraries(const std::vector libraries, const std::vector effects, + std::vector &successEffects) override; private: static inline BrokerDelegator delegator_; }; diff --git a/services/audio_service/client/src/audio_manager_proxy.cpp b/services/audio_service/client/src/audio_manager_proxy.cpp index 29ad9d1a29..5dcfdd6fc6 100644 --- a/services/audio_service/client/src/audio_manager_proxy.cpp +++ b/services/audio_service/client/src/audio_manager_proxy.cpp @@ -425,5 +425,56 @@ sptr AudioManagerProxy::CreateAudioProcess(const AudioProcessConf sptr process = reply.ReadRemoteObject(); return process; } + +bool AudioManagerProxy::LoadAudioEffectLibraries(const vector libraries, const vector effects, + vector &successEffects) +{ + int32_t error, i; + + MessageParcel dataParcel, replyParcel; + MessageOption option; + if (!dataParcel.WriteInterfaceToken(GetDescriptor())) { + AUDIO_ERR_LOG("AudioManagerProxy: WriteInterfaceToken failed"); + return false; + } + + int32_t countLib = libraries.size(); + int32_t countEff = effects.size(); + + dataParcel.WriteInt32(countLib); + dataParcel.WriteInt32(countEff); + + for (Library x : libraries) { + dataParcel.WriteString(x.name); + dataParcel.WriteString(x.path); + } + + for (Effect x : effects) { + dataParcel.WriteString(x.name); + dataParcel.WriteString(x.libraryName); + dataParcel.WriteString(x.effectId); + } + + error = Remote()->SendRequest(LOAD_AUDIO_EFFECT_LIBRARIES, dataParcel, replyParcel, option); + if (error != ERR_NONE) { + AUDIO_ERR_LOG("LoadAudioEffectLibraries failed, error: %{public}d", error); + return false; + } + + int32_t successEffSize = replyParcel.ReadInt32(); + if ((successEffSize < 0) || (successEffSize > COUNT_UPPER_LIMIT)) { + AUDIO_ERR_LOG("LOAD_AUDIO_EFFECT_LIBRARIES read replyParcel failed"); + return false; + } + + for (i = 0; i < successEffSize; i++) { + string effectName = replyParcel.ReadString(); + string libName = replyParcel.ReadString(); + string effectId = replyParcel.ReadString(); + successEffects.push_back({effectName, libName, effectId}); + } + + return true; +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/include/audio_effect_server.h b/services/audio_service/server/include/audio_effect_server.h new file mode 100644 index 0000000000..9b738e7ef0 --- /dev/null +++ b/services/audio_service/server/include/audio_effect_server.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include "audio_info.h" + +#ifndef ST_AUDIO_EFFECT_SERVER_H +#define ST_AUDIO_EFFECT_SERVER_H + +#define AUDIO_EFFECT_LIBRARY_INFO_SYM AELI +#define AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR "AELI" +#define EFFECT_STRING_LEN_MAX 64 + +namespace OHOS { +namespace AudioStandard { + +typedef struct EffectInterfaceS **EffectHandleT; + +typedef struct AudioBufferS { + size_t frameCount; // number of frames in buffer + union { + void *raw; // raw pointer to start of buffer + float *f32; // pointer to float 32 bit data at start of buffer + int32_t *s32; // pointer to signed 32 bit data at start of buffer + int16_t *s16; // pointer to signed 16 bit data at start of buffer + uint8_t *u8; // pointer to unsigned 8 bit data at start of buffer + }; +} AudioBufferT; + +// for initial version +typedef struct EffectDescriptorS { + std::string type; + std::string id; + uint32_t apiVersion; + uint32_t flags; + uint16_t cpuLoad; + uint16_t memoryUsage; + char name[EFFECT_STRING_LEN_MAX]; + char implementor[EFFECT_STRING_LEN_MAX]; +} EffectDescriptorT; + +struct EffectInterfaceS { + int32_t (*Process)(EffectHandleT self, AudioBufferT *inBuffer, AudioBufferT *outBuffer); + + int32_t (*Command)(EffectHandleT self, uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t *replySize, + void *pReplyData); + + int32_t (*GetDescriptor)(EffectHandleT self, EffectDescriptorT *pDescriptor); + + int32_t (*ProcessReverse)(EffectHandleT self, AudioBufferT *inBuffer, AudioBufferT *outBuffer); +}; + +// for initial version +typedef struct AudioEffectLibraryS { + uint32_t tag; + uint32_t version; + const char *name; + const char *implementor; + + int32_t (*CreateEffect)(const std::string *id, int32_t sessionId, int32_t ioId, EffectHandleT *pHandle); + + int32_t (*ReleaseEffect)(EffectHandleT handle); + + int32_t (*GetDescriptor)(const std::string *id, EffectDescriptorT *pDescriptor); +} AudioEffectLibraryT; + +typedef struct ListNodeS { + void *object; + struct ListNodeS *next; +} ListNodeT; + +typedef struct LibEntryS { + AudioEffectLibraryT *desc; + std::string name; + std::string path; + void *handle; + std::vector> effects; +} LibEntryT; + +class AudioEffectServer { +public: + explicit AudioEffectServer(); + ~AudioEffectServer(); + + bool LoadAudioEffects(const std::vector libraries, const std::vector effects, + std::vector& successEffectList); + + std::vector>& GetAvailableEffects(); + +private: + std::vector> effectLibraryList; + std::vector> effectLibraryFailedList; + std::vector> effectSkippedEffects; +}; + +} // namespce AudioStandard +} // namespace OHOS +#endif \ No newline at end of file diff --git a/services/audio_service/server/include/audio_server.h b/services/audio_service/server/include/audio_server.h index 6c5fbe089b..1625ecaa9a 100644 --- a/services/audio_service/server/include/audio_server.h +++ b/services/audio_service/server/include/audio_server.h @@ -29,6 +29,7 @@ #include "audio_server_death_recipient.h" #include "audio_system_manager.h" #include "i_audio_renderer_sink.h" +#include "audio_effect_server.h" namespace OHOS { namespace AudioStandard { @@ -42,6 +43,8 @@ public: void OnStart() override; void OnStop() override; + bool LoadAudioEffectLibraries(std::vector libraries, std::vector effects, + std::vector& successEffectList) override; int32_t SetMicrophoneMute(bool isMute) override; bool IsMicrophoneMute() override; int32_t SetVoiceVolume(float volume) override; @@ -87,6 +90,7 @@ private: AudioScene audioScene_ = AUDIO_SCENE_DEFAULT; std::shared_ptr callback_; bool isGetProcessEnabled_ = false; + std::unique_ptr audioEffectServer_; }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/src/audio_effect_server.cpp b/services/audio_service/server/src/audio_effect_server.cpp new file mode 100644 index 0000000000..1c9f9bee01 --- /dev/null +++ b/services/audio_service/server/src/audio_effect_server.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include "functional" +#include "memory" +#include +#include "unistd.h" +#include "audio_effect_server.h" +#include "audio_log.h" +#include "audio_effect_server.h" + +# define AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR "AELI" +# define EFFECT_STRING_LEN_MAX 64 + +namespace OHOS { +namespace AudioStandard { + +constexpr const char *LD_EFFECT_LIBRARY_PATH[] = {"/system/lib/"}; + +struct LoadEffectResult { + bool success = false; + LibEntryT *lib = nullptr; + std::unique_ptr effectDesc; +}; + +bool ResolveLibrary(const std::string &path, std::string &resovledPath) +{ + for (auto *libDir: LD_EFFECT_LIBRARY_PATH) { + std::string candidatePath = std::string(libDir) + "/" + path; + if (access(candidatePath.c_str(), R_OK) == 0) { + resovledPath = std::move(candidatePath); + return true; + } + } + + return false; +} + +static bool LoadLibrary(const std::string relativePath, std::unique_ptr& libEntry) noexcept +{ + std::string absolutePath; + // find library in adsolutePath + if (!ResolveLibrary(relativePath, absolutePath)) { + AUDIO_ERR_LOG(" find library falied in effect directories: %{public}s", + relativePath.c_str()); + libEntry->path = relativePath; + return false; + } + + // load hundle + libEntry->path = absolutePath; + + void* handle = dlopen(absolutePath.c_str(), 1); + if (!handle) { + AUDIO_ERR_LOG(" Open lib Fail"); + return false; + } else { + AUDIO_INFO_LOG(" dlopen lib successful"); + } + + AudioEffectLibraryT *description = static_cast(dlsym(handle, + AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR)); + const char* error = dlerror(); + if (!error) { + AUDIO_ERR_LOG(" dlsym failed: error: %{public}s, %{public}p", error, description); + } else { + AUDIO_INFO_LOG(" dlsym lib successful"); + } + + libEntry->handle = handle; + libEntry->desc = description; + + return true; +} + +void LoadLibraries(const std::vector &libs, + std::vector> &libList, + std::vector> &glibFailedList) +{ + for (Library library: libs) { + AUDIO_INFO_LOG(" loading %{public}s : %{public}s", library.name.c_str(), library.path.c_str()); + + std::unique_ptr libEntry = std::make_unique(); + libEntry->name = library.name; + + bool loadLibrarySuccess = LoadLibrary(library.path, libEntry); + if (!loadLibrarySuccess) { + // Register library load failure + glibFailedList.emplace_back(std::move(libEntry)); + continue; + } + + // Register library load success + libList.emplace_back(std::move(libEntry)); + } +} + +LibEntryT *FindLibrary(const std::string name, std::vector> &libList) +{ + for (const std::unique_ptr& lib : libList) { + if (lib->name == name) { + return lib.get(); + } + } + + return nullptr; +} + +LoadEffectResult LoadEffect(const Effect &effect, const std::string &name, + std::vector> &libList) +{ + LoadEffectResult result; + + result.lib = FindLibrary(effect.libraryName, libList); + if (result.lib == nullptr) { + AUDIO_ERR_LOG(" could not find library %{public}s to load effect %{public}s", + effect.libraryName.c_str(), effect.name.c_str()); + result.success = false; + return result; + } + + result.effectDesc = std::make_unique(); + + result.success = true; + return result; +} + +void LoadEffects(const std::vector &effects, + std::vector> &libList, + std::vector> &gSkippedEffectList, + std::vector &successEffectList) +{ + for (Effect effect: effects) { + LoadEffectResult effectLoadResult = LoadEffect(effect, effect.name, libList); + if (!effectLoadResult.success) { + AUDIO_ERR_LOG(" LoadEffects have failures!"); + if (effectLoadResult.effectDesc != nullptr) { + gSkippedEffectList.emplace_back(std::move(effectLoadResult.effectDesc)); + } + continue; + } + + effectLoadResult.lib->effects.emplace_back(std::move(effectLoadResult.effectDesc)); + successEffectList.push_back(effect); + } +} + +AudioEffectServer::AudioEffectServer() +{ + AUDIO_INFO_LOG("AudioEffectServer ctor"); +} + +AudioEffectServer::~AudioEffectServer() +{ +} + +bool AudioEffectServer::LoadAudioEffects(const std::vector libraries, const std::vector effects, + std::vector& successEffectList) +{ + // load library + AUDIO_INFO_LOG(" load library"); + LoadLibraries(libraries, effectLibraryList, effectLibraryFailedList); + + // load effect + AUDIO_INFO_LOG(" load effect"); + LoadEffects(effects, effectLibraryList, effectSkippedEffects, successEffectList); + if (successEffectList.size()>0) { + return true; + } else { + return false; + } +} + +std::vector>& AudioEffectServer::GetAvailableEffects() +{ + return effectLibraryList; +} + +} // namespce AudioStandard +} // namespace OHOS \ No newline at end of file diff --git a/services/audio_service/server/src/audio_manager_stub.cpp b/services/audio_service/server/src/audio_manager_stub.cpp index d840ca1fb5..a698e61bd4 100644 --- a/services/audio_service/server/src/audio_manager_stub.cpp +++ b/services/audio_service/server/src/audio_manager_stub.cpp @@ -17,11 +17,39 @@ #include "audio_system_manager.h" #include "audio_log.h" #include "i_audio_process.h" +#include "audio_effect_server.h" using namespace std; namespace OHOS { namespace AudioStandard { +static void LoadEffectLibrariesReadData(vector& libList, vector& effectList, MessageParcel &data, + int32_t countLib, int32_t countEff) +{ + int32_t i; + for (i = 0; i < countLib; i++) { + string libName = data.ReadString(); + string libPath = data.ReadString(); + libList.push_back({libName, libPath}); + } + for (i = 0; i < countEff; i++) { + string effectName = data.ReadString(); + string libName = data.ReadString(); + string effectId = data.ReadString(); + effectList.push_back({effectName, libName, effectId}); + } +} + +static void LoadEffectLibrariesWriteReply(vector& successEffectList, MessageParcel &reply) +{ + reply.WriteInt32(successEffectList.size()); + for (Effect effect: successEffectList) { + reply.WriteString(effect.name); + reply.WriteString(effect.libraryName); + reply.WriteString(effect.effectId); + } +} + int AudioManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { AUDIO_DEBUG_LOG("OnRemoteRequest, cmd = %{public}u", code); @@ -168,16 +196,26 @@ int AudioManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Messag SetAudioBalanceValue(audioBalanceValue); return AUDIO_OK; } - case CREATE_AUDIOPROCESS: { - AUDIO_INFO_LOG("CREATE_AUDIOPROCESS AudioManagerStub"); - AudioProcessConfig config; - IAudioProcess::ReadConfigFromParcel(config, data); - sptr process = CreateAudioProcess(config); - if (process == nullptr) { - AUDIO_ERR_LOG("CREATE_AUDIOPROCESS AudioManagerStub CreateAudioProcess failed"); + case LOAD_AUDIO_EFFECT_LIBRARIES: { + vector libList = {}; + vector effectList = {}; + int32_t countLib = data.ReadInt32(); + int32_t countEff = data.ReadInt32(); + if ((countLib < 0) || (countLib > COUNT_UPPER_LIMIT) || (countEff < 0) || (countEff > COUNT_UPPER_LIMIT)) { + AUDIO_ERR_LOG("LOAD_AUDIO_EFFECT_LIBRARIES read data failed"); return AUDIO_ERR; } - reply.WriteRemoteObject(process); + LoadEffectLibrariesReadData(libList, effectList, data, countLib, countEff); + if (countLib > 0) { + //load lib and reply success list + vector successEffectList = {}; + bool loadSuccess = LoadAudioEffectLibraries(libList, effectList, successEffectList); + if (!loadSuccess) { + AUDIO_ERR_LOG("Load audio effect libraries failed, please check log"); + return AUDIO_ERR; + } + LoadEffectLibrariesWriteReply(successEffectList, reply); + } return AUDIO_OK; } default: { diff --git a/services/audio_service/server/src/audio_server.cpp b/services/audio_service/server/src/audio_server.cpp index f7b842f3e0..717f6178b1 100644 --- a/services/audio_service/server/src/audio_server.cpp +++ b/services/audio_service/server/src/audio_server.cpp @@ -69,11 +69,15 @@ void *AudioServer::paDaemonThread(void *arg) #endif AudioServer::AudioServer(int32_t systemAbilityId, bool runOnCreate) - : SystemAbility(systemAbilityId, runOnCreate) -{} + : SystemAbility(systemAbilityId, runOnCreate), + audioEffectServer_(std::make_unique()) +{ +} void AudioServer::OnDump() -{} +{ + audioEffectServer_ = nullptr; +} void AudioServer::OnStart() { @@ -279,6 +283,22 @@ uint64_t AudioServer::GetTransactionId(DeviceType deviceType, DeviceRole deviceR return transactionId; } +bool AudioServer::LoadAudioEffectLibraries(const std::vector libraries, const std::vector effects, + std::vector& successEffectList) +{ + int32_t audio_policy_server_id = 1041; + int32_t audio_policy_server_Uid = 1005; + if (IPCSkeleton::GetCallingUid() != audio_policy_server_id + && IPCSkeleton::GetCallingUid() != audio_policy_server_Uid) { + return false; + } + bool loadSuccess = audioEffectServer_->LoadAudioEffects(libraries, effects, successEffectList); + if (!loadSuccess) { + AUDIO_ERR_LOG("Load audio effect failed, please check log"); + } + return loadSuccess; +} + int32_t AudioServer::SetMicrophoneMute(bool isMute) { int32_t audio_policy_server_id = 1041; -- Gitee