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