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 
29 namespace OHOS {
30 namespace AudioStandard {
31 
32 #if (defined(__aarch64__) || defined(__x86_64__))
33     constexpr const char *LD_EFFECT_LIBRARY_PATH[] = {"/sys_prod/lib64/", "/system/lib64/"};
34 #else
35     constexpr const char *LD_EFFECT_LIBRARY_PATH[] = {"/sys_prod/lib/", "/system/lib/"};
36 #endif
37 
ResolveLibrary(const std::string & path,std::string & resovledPath)38 bool ResolveLibrary(const std::string &path, std::string &resovledPath)
39 {
40     for (auto *libDir: LD_EFFECT_LIBRARY_PATH) {
41         std::string candidatePath = std::string(libDir) + "/" + path;
42         if (access(candidatePath.c_str(), R_OK) == 0) {
43             resovledPath = std::move(candidatePath);
44             return true;
45         }
46     }
47 
48     return false;
49 }
50 
LoadLibrary(const std::string & relativePath,std::shared_ptr<AudioEffectLibEntry> & libEntry)51 static bool LoadLibrary(const std::string &relativePath, std::shared_ptr<AudioEffectLibEntry> &libEntry) noexcept
52 {
53     std::string absolutePath;
54     // find library in adsolutePath
55     if (!ResolveLibrary(relativePath, absolutePath)) {
56         AUDIO_ERR_LOG("<log error> find library falied in effect directories: %{public}s",
57             relativePath.c_str());
58         return false;
59     }
60 
61     void* handle = dlopen(absolutePath.c_str(), 1);
62     if (!handle) {
63         AUDIO_ERR_LOG("<log error> dlopen lib %{public}s Fail", relativePath.c_str());
64         return false;
65     } else {
66         AUDIO_INFO_LOG("<log info> dlopen lib %{public}s successful", relativePath.c_str());
67     }
68     dlerror(); // clean existing errors;
69 
70     AudioEffectLibrary *audioEffectLibHandle = static_cast<AudioEffectLibrary *>(dlsym(handle,
71         AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR));
72     if (!audioEffectLibHandle) {
73         AUDIO_ERR_LOG("<log error> dlsym failed: error: %{public}s", dlerror());
74 #ifndef TEST_COVERAGE
75         dlclose(handle);
76 #endif
77         return false;
78     }
79     AUDIO_INFO_LOG("<log info> dlsym lib %{public}s successful", relativePath.c_str());
80 
81     libEntry->audioEffectLibHandle = audioEffectLibHandle;
82 
83     return true;
84 }
85 
LoadLibraries(const std::vector<Library> & libs,std::vector<std::shared_ptr<AudioEffectLibEntry>> & libList)86 static void LoadLibraries(const std::vector<Library> &libs, std::vector<std::shared_ptr<AudioEffectLibEntry>> &libList)
87 {
88     for (Library library: libs) {
89         AUDIO_INFO_LOG("<log info> loading %{public}s : %{public}s", library.name.c_str(), library.path.c_str());
90 
91         std::shared_ptr<AudioEffectLibEntry> libEntry = std::make_shared<AudioEffectLibEntry>();
92         libEntry->libraryName = library.name;
93 
94         bool loadLibrarySuccess = LoadLibrary(library.path, libEntry);
95         if (!loadLibrarySuccess) {
96             AUDIO_ERR_LOG("<log error> loadLibrary fail, please check logs!");
97 
98             // hisysevent for load engine error
99             std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
100                 Media::MediaMonitor::AUDIO, Media::MediaMonitor::LOAD_EFFECT_ENGINE_ERROR,
101                 Media::MediaMonitor::FAULT_EVENT);
102             bean->Add("ENGINE_TYPE", Media::MediaMonitor::AUDIO_EFFECT_PROCESS_ENGINE);
103             Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
104 
105             continue;
106         }
107 
108         // Register library load success
109         libList.emplace_back(std::move(libEntry));
110     }
111 }
112 
FindLibrary(const std::string & name,const std::vector<std::shared_ptr<AudioEffectLibEntry>> & libList)113 std::shared_ptr<AudioEffectLibEntry> FindLibrary(const std::string &name,
114     const std::vector<std::shared_ptr<AudioEffectLibEntry>> &libList)
115 {
116     for (const std::shared_ptr<AudioEffectLibEntry> &lib : libList) {
117         if (lib->libraryName == name) {
118             return lib;
119         }
120     }
121 
122     return nullptr;
123 }
124 
LoadEffect(const Effect & effect,const std::vector<std::shared_ptr<AudioEffectLibEntry>> & libList)125 static bool LoadEffect(const Effect &effect, const std::vector<std::shared_ptr<AudioEffectLibEntry>> &libList)
126 {
127     std::shared_ptr<AudioEffectLibEntry> currentLibEntry = FindLibrary(effect.libraryName, libList);
128     if (currentLibEntry == nullptr) {
129         AUDIO_ERR_LOG("<log error> could not find library %{public}s to load effect %{public}s",
130                       effect.libraryName.c_str(), effect.name.c_str());
131         return false;
132     }
133     // check effect
134     AudioEffectDescriptor descriptor;
135     descriptor.libraryName = effect.libraryName;
136     descriptor.effectName = effect.name;
137 
138     bool ret = currentLibEntry->audioEffectLibHandle->checkEffect(descriptor);
139     if (ret) {
140         currentLibEntry->effectName.push_back(effect.name);
141     } else {
142         AUDIO_ERR_LOG("<log error> the effect %{public}s in lib %{public}s, open check file!",
143             effect.name.c_str(), effect.libraryName.c_str());
144         return false;
145     }
146 
147     return true;
148 }
149 
CheckEffects(const std::vector<Effect> & effects,const std::vector<std::shared_ptr<AudioEffectLibEntry>> & libList,std::vector<Effect> & successEffectList)150 void CheckEffects(const std::vector<Effect> &effects, const std::vector<std::shared_ptr<AudioEffectLibEntry>> &libList,
151     std::vector<Effect> &successEffectList)
152 {
153     for (Effect effect: effects) {
154         bool ret = LoadEffect(effect, libList);
155         if (!ret) {
156             AUDIO_ERR_LOG("<log error> LoadEffects have failures, please check log!");
157             continue;
158         }
159 
160         successEffectList.push_back(effect);
161     }
162 }
163 
AudioEffectServer()164 AudioEffectServer::AudioEffectServer()
165 {
166     AUDIO_INFO_LOG("AudioEffectServer ctor");
167 }
168 
~AudioEffectServer()169 AudioEffectServer::~AudioEffectServer()
170 {
171 }
172 
LoadAudioEffects(const std::vector<Library> & libraries,const std::vector<Effect> & effects,std::vector<Effect> & successEffectList)173 bool AudioEffectServer::LoadAudioEffects(const std::vector<Library> &libraries, const std::vector<Effect> &effects,
174                                          std::vector<Effect> &successEffectList)
175 {
176     // load library
177     LoadLibraries(libraries, effectLibEntries_);
178 
179     // check effects
180     CheckEffects(effects, effectLibEntries_, successEffectList);
181     if (successEffectList.size() > 0) {
182         return true;
183     } else {
184         return false;
185     }
186 }
187 
GetEffectEntries()188 std::vector<std::shared_ptr<AudioEffectLibEntry>> &AudioEffectServer::GetEffectEntries()
189 {
190     return effectLibEntries_;
191 }
192 
193 } // namespce AudioStandard
194 } // namespace OHOS
195