1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifndef LOG_TAG
16 #define LOG_TAG "AudioEffectServer"
17 #endif
18
19 #include <iostream>
20 #include <vector>
21 #include "functional"
22 #include "memory"
23 #include <dlfcn.h>
24 #include "unistd.h"
25 #include "audio_service_log.h"
26 #include "audio_effect_server.h"
27 #include "media_monitor_manager.h"
28 #include "audio_utils.h"
29
30 namespace OHOS {
31 namespace AudioStandard {
32
33 #if (defined(__aarch64__) || defined(__x86_64__))
34 constexpr const char *LD_EFFECT_LIBRARY_PATH[] = {"/sys_prod/lib64/", "/system/lib64/"};
35 #else
36 constexpr const char *LD_EFFECT_LIBRARY_PATH[] = {"/sys_prod/lib/", "/system/lib/"};
37 #endif
38
ResolveLibrary(const std::string & path,std::string & resovledPath)39 bool ResolveLibrary(const std::string &path, std::string &resovledPath)
40 {
41 for (auto *libDir: LD_EFFECT_LIBRARY_PATH) {
42 std::string candidatePath = std::string(libDir) + "/" + path;
43 if (access(candidatePath.c_str(), R_OK) == 0) {
44 resovledPath = std::move(candidatePath);
45 return true;
46 }
47 }
48
49 return false;
50 }
51
LoadLibrary(const std::string & relativePath,std::shared_ptr<AudioEffectLibEntry> & libEntry)52 static bool LoadLibrary(const std::string &relativePath, std::shared_ptr<AudioEffectLibEntry> &libEntry) noexcept
53 {
54 std::string absolutePath;
55 // find library in adsolutePath
56 if (!ResolveLibrary(relativePath, absolutePath)) {
57 AUDIO_ERR_LOG("<log error> find library falied in effect directories: %{public}s",
58 relativePath.c_str());
59 return false;
60 }
61
62 void* handle = dlopen(absolutePath.c_str(), 1);
63 if (!handle) {
64 AUDIO_ERR_LOG("<log error> dlopen lib %{public}s fail", relativePath.c_str());
65 return false;
66 } else {
67 AUDIO_INFO_LOG("<log info> dlopen lib %{public}s successful", relativePath.c_str());
68 }
69 dlerror(); // clean existing errors;
70
71 AudioEffectLibrary *audioEffectLibHandle = static_cast<AudioEffectLibrary *>(dlsym(handle,
72 AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR));
73 if (!audioEffectLibHandle) {
74 AUDIO_ERR_LOG("<log error> dlsym failed: error: %{public}s", dlerror());
75 #ifndef TEST_COVERAGE
76 dlclose(handle);
77 #endif
78 return false;
79 }
80 AUDIO_INFO_LOG("<log info> dlsym lib %{public}s successful", relativePath.c_str());
81
82 libEntry->audioEffectLibHandle = audioEffectLibHandle;
83
84 return true;
85 }
86
LoadLibraries(const std::vector<Library> & libs,std::vector<std::shared_ptr<AudioEffectLibEntry>> & libList)87 static void LoadLibraries(const std::vector<Library> &libs, std::vector<std::shared_ptr<AudioEffectLibEntry>> &libList)
88 {
89 for (Library library: libs) {
90 AUDIO_INFO_LOG("<log info> loading %{public}s : %{public}s", library.name.c_str(), library.path.c_str());
91
92 std::shared_ptr<AudioEffectLibEntry> libEntry = std::make_shared<AudioEffectLibEntry>();
93 libEntry->libraryName = library.name;
94
95 bool loadLibrarySuccess = LoadLibrary(library.path, libEntry);
96 if (!loadLibrarySuccess) {
97 AUDIO_ERR_LOG("<log error> loadLibrary fail, please check logs!");
98
99 // hisysevent for load engine error
100 Trace trace("SYSEVENT FAULT EVENT LOAD_EFFECT_ENGINE_ERROR, ENGINE_TYPE: "
101 + std::to_string(Media::MediaMonitor::AUDIO_EFFECT_PROCESS_ENGINE));
102 std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
103 Media::MediaMonitor::AUDIO, Media::MediaMonitor::LOAD_EFFECT_ENGINE_ERROR,
104 Media::MediaMonitor::FAULT_EVENT);
105 bean->Add("ENGINE_TYPE", Media::MediaMonitor::AUDIO_EFFECT_PROCESS_ENGINE);
106 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
107
108 continue;
109 }
110
111 // Register library load success
112 libList.emplace_back(std::move(libEntry));
113 }
114 }
115
FindLibrary(const std::string & name,const std::vector<std::shared_ptr<AudioEffectLibEntry>> & libList)116 std::shared_ptr<AudioEffectLibEntry> FindLibrary(const std::string &name,
117 const std::vector<std::shared_ptr<AudioEffectLibEntry>> &libList)
118 {
119 for (const std::shared_ptr<AudioEffectLibEntry> &lib : libList) {
120 if (lib->libraryName == name) {
121 return lib;
122 }
123 }
124
125 return nullptr;
126 }
127
LoadEffect(const Effect & effect,const std::vector<std::shared_ptr<AudioEffectLibEntry>> & libList)128 static bool LoadEffect(const Effect &effect, const std::vector<std::shared_ptr<AudioEffectLibEntry>> &libList)
129 {
130 std::shared_ptr<AudioEffectLibEntry> currentLibEntry = FindLibrary(effect.libraryName, libList);
131 if (currentLibEntry == nullptr) {
132 AUDIO_ERR_LOG("<log error> could not find library %{public}s to load effect %{public}s",
133 effect.libraryName.c_str(), effect.name.c_str());
134 return false;
135 }
136 // check effect
137 AudioEffectDescriptor descriptor;
138 descriptor.libraryName = effect.libraryName;
139 descriptor.effectName = effect.name;
140
141 bool ret = currentLibEntry->audioEffectLibHandle->checkEffect(descriptor);
142 if (ret) {
143 currentLibEntry->effectName.push_back(effect.name);
144 } else {
145 AUDIO_ERR_LOG("<log error> the effect %{public}s in lib %{public}s, open check file!",
146 effect.name.c_str(), effect.libraryName.c_str());
147 return false;
148 }
149
150 return true;
151 }
152
CheckEffects(const std::vector<Effect> & effects,const std::vector<std::shared_ptr<AudioEffectLibEntry>> & libList,std::vector<Effect> & successEffectList)153 void CheckEffects(const std::vector<Effect> &effects, const std::vector<std::shared_ptr<AudioEffectLibEntry>> &libList,
154 std::vector<Effect> &successEffectList)
155 {
156 for (Effect effect: effects) {
157 bool ret = LoadEffect(effect, libList);
158 if (!ret) {
159 AUDIO_ERR_LOG("<log error> LoadEffects have failures, please check log!");
160 continue;
161 }
162
163 successEffectList.push_back(effect);
164 }
165 }
166
AudioEffectServer()167 AudioEffectServer::AudioEffectServer()
168 {
169 AUDIO_INFO_LOG("AudioEffectServer ctor");
170 }
171
~AudioEffectServer()172 AudioEffectServer::~AudioEffectServer()
173 {
174 }
175
LoadAudioEffects(const std::vector<Library> & libraries,const std::vector<Effect> & effects,std::vector<Effect> & successEffectList)176 bool AudioEffectServer::LoadAudioEffects(const std::vector<Library> &libraries, const std::vector<Effect> &effects,
177 std::vector<Effect> &successEffectList)
178 {
179 // load library
180 LoadLibraries(libraries, effectLibEntries_);
181
182 // check effects
183 CheckEffects(effects, effectLibEntries_, successEffectList);
184 if (successEffectList.size() > 0) {
185 return true;
186 } else {
187 return false;
188 }
189 }
190
GetEffectEntries()191 std::vector<std::shared_ptr<AudioEffectLibEntry>> &AudioEffectServer::GetEffectEntries()
192 {
193 return effectLibEntries_;
194 }
195
196 } // namespce AudioStandard
197 } // namespace OHOS
198