1 /*
2 * Copyright (c) 2022-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
16 #include "distributed_audio_client.h"
17
18 #include <securec.h>
19
20 #include <v1_0/audio_types.h>
21
22 #include "audio_types.h"
23 #include "daudio_constants.h"
24 #include "daudio_errorcode.h"
25 #include "daudio_log.h"
26
27 #undef DH_LOG_TAG
28 #define DH_LOG_TAG "DAudioAudioClient"
29
30 namespace OHOS {
31 namespace DistributedHardware {
32 using OHOS::HDI::DistributedAudio::Audio::V1_0::IAudioAdapter;
33 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioAdapterDescriptor;
34
InitDescriptorPort(const AudioAdapterDescriptor & desc,::AudioAdapterDescriptor & descInternal)35 static int32_t InitDescriptorPort(const AudioAdapterDescriptor &desc, ::AudioAdapterDescriptor &descInternal)
36 {
37 DHLOGI("Init audio adapter descriptor port.");
38 ::AudioPort *audioPorts = (::AudioPort *)malloc(desc.ports.size() * sizeof(AudioPort));
39 if (audioPorts == nullptr) {
40 DHLOGE("Audio ports is nullptr.");
41 return ERR_DH_AUDIO_HDI_NULLPTR;
42 }
43 descInternal.ports = audioPorts;
44
45 bool isSuccess = true;
46 uint32_t cpyPortNum = 0;
47 constexpr uint32_t maxPortNameLen = 1000;
48 for (auto port : desc.ports) {
49 if (port.portName.length() >= maxPortNameLen) {
50 DHLOGE("Audio port name length is too long.");
51 continue;
52 }
53 char* portName = reinterpret_cast<char *>(calloc(port.portName.length() + STR_TERM_LEN, sizeof(char)));
54 if (portName == nullptr) {
55 DHLOGE("Calloc failed.");
56 isSuccess = false;
57 break;
58 }
59 if (strcpy_s(portName, port.portName.length() + STR_TERM_LEN, port.portName.c_str()) != EOK) {
60 DHLOGD("Strcpy_s port name failed.");
61 free(portName);
62 continue;
63 }
64 audioPorts->dir = static_cast<::AudioPortDirection>(port.dir);
65 audioPorts->portId = port.portId;
66 audioPorts->portName = portName;
67 audioPorts++;
68 cpyPortNum++;
69 }
70 if (isSuccess) {
71 return DH_SUCCESS;
72 }
73
74 for (uint32_t i = 0; i < cpyPortNum; i++) {
75 if (descInternal.ports[i].portName != nullptr) {
76 free(const_cast<char *>(descInternal.ports[i].portName));
77 }
78 }
79 free(descInternal.ports);
80 descInternal.ports = nullptr;
81 return ERR_DH_AUDIO_HDI_CALL_FAILED;
82 }
83
InitAudioAdapterDescriptor(AudioManagerContext * context,std::vector<AudioAdapterDescriptor> & descriptors)84 static int32_t InitAudioAdapterDescriptor(AudioManagerContext *context,
85 std::vector<AudioAdapterDescriptor> &descriptors)
86 {
87 DHLOGI("Init audio adapters descriptor, size is: %zu.", descriptors.size());
88 constexpr uint32_t maxAdapterNameLen = 1000;
89 constexpr uint32_t maxPortNum = 100;
90 constexpr uint32_t minPortNum = 1;
91 for (auto desc : descriptors) {
92 if (desc.ports.size() < minPortNum || desc.ports.size() > maxPortNum) {
93 DHLOGE("The descriptor ports size: %zu.", desc.ports.size());
94 continue;
95 }
96 if (desc.adapterName.length() >= maxAdapterNameLen) {
97 DHLOGE("Audio adapter name length is too long.");
98 continue;
99 }
100 char* adapterName = reinterpret_cast<char *>(calloc(desc.adapterName.length() + STR_TERM_LEN, sizeof(char)));
101 if (adapterName == nullptr) {
102 DHLOGE("Calloc failed.");
103 return ERR_DH_AUDIO_HDI_NULLPTR;
104 }
105 if (strcpy_s(adapterName, desc.adapterName.length() + STR_TERM_LEN, desc.adapterName.c_str()) != EOK) {
106 DHLOGD("Strcpy_s adapter name failed.");
107 free(adapterName);
108 continue;
109 }
110
111 ::AudioAdapterDescriptor descInternal = {
112 .adapterName = adapterName,
113 .portNum = desc.ports.size(),
114 };
115 int32_t ret = InitDescriptorPort(desc, descInternal);
116 if (ret != DH_SUCCESS) {
117 DHLOGE("Init audio adapter descriptor port fail.");
118 free(adapterName);
119 descInternal.adapterName = nullptr;
120 return ret;
121 }
122 context->descriptors_.push_back(descInternal);
123 }
124 return DH_SUCCESS;
125 }
126
GetAllAdaptersInternal(struct AudioManager * manager,struct::AudioAdapterDescriptor ** descs,int32_t * size)127 static int32_t GetAllAdaptersInternal(struct AudioManager *manager, struct ::AudioAdapterDescriptor **descs,
128 int32_t *size)
129 {
130 DHLOGI("Get all adapters.");
131 if (manager == nullptr || descs == nullptr || size == nullptr) {
132 DHLOGE("The parameter is empty.");
133 return ERR_DH_AUDIO_HDI_INVALID_PARAM;
134 }
135
136 AudioManagerContext *context = reinterpret_cast<AudioManagerContext *>(manager);
137 std::lock_guard<std::mutex> lock(context->mtx_);
138
139 std::vector<AudioAdapterDescriptor> descriptors;
140 if (context->proxy_ == nullptr) {
141 DHLOGE("The context or proxy for the context is nullptr.");
142 return ERR_DH_AUDIO_HDI_NULLPTR;
143 }
144 int32_t ret = context->proxy_->GetAllAdapters(descriptors);
145 if (ret != DH_SUCCESS) {
146 *descs = nullptr;
147 *size = 0;
148 DHLOGE("Failed to get all adapters.");
149 return ret;
150 }
151 context->ClearDescriptors();
152 ret = InitAudioAdapterDescriptor(context, descriptors);
153 if (ret != DH_SUCCESS) {
154 return ret;
155 }
156 *descs = context->descriptors_.data();
157 *size = context->descriptors_.size();
158 return DH_SUCCESS;
159 }
160
LoadAdapterInternal(struct AudioManager * manager,const struct::AudioAdapterDescriptor * desc,struct AudioAdapter ** adapter)161 static int32_t LoadAdapterInternal(struct AudioManager *manager, const struct ::AudioAdapterDescriptor *desc,
162 struct AudioAdapter **adapter)
163 {
164 DHLOGI("Load adapter.");
165 if (manager == nullptr || desc == nullptr || desc->adapterName == nullptr || adapter == nullptr) {
166 DHLOGE("The parameter is empty.");
167 return ERR_DH_AUDIO_HDI_INVALID_PARAM;
168 }
169 AudioManagerContext *context = reinterpret_cast<AudioManagerContext *>(manager);
170 std::string adpName = desc->adapterName;
171 {
172 std::lock_guard<std::mutex> lock(context->mtx_);
173 if (context->adapters_.find(adpName) != context->adapters_.end()) {
174 DHLOGD("Adapter already has been load.");
175 *adapter = &(context->adapters_[adpName]->instance_);
176 return DH_SUCCESS;
177 }
178 }
179
180 AudioAdapterDescriptor descriptor = {
181 .adapterName = desc->adapterName,
182 };
183 sptr<IAudioAdapter> adapterProxy = nullptr;
184 if (context->proxy_ == nullptr) {
185 DHLOGE("The context or proxy for the context is nullptr.");
186 return ERR_DH_AUDIO_HDI_NULLPTR;
187 }
188 int32_t ret = context->proxy_->LoadAdapter(descriptor, adapterProxy);
189 if (ret != DH_SUCCESS) {
190 DHLOGE("Failed to load the adapter.");
191 *adapter = nullptr;
192 return ret;
193 }
194
195 auto adapterContext = std::make_unique<AudioAdapterContext>();
196 adapterContext->proxy_ = adapterProxy;
197 *adapter = &adapterContext->instance_;
198 adapterContext->adapterName_ = descriptor.adapterName;
199 {
200 std::lock_guard<std::mutex> lock(context->mtx_);
201 context->adapters_.insert(std::make_pair(adpName, std::move(adapterContext)));
202 }
203 return DH_SUCCESS;
204 }
205
UnloadAdapterInternal(struct AudioManager * manager,struct AudioAdapter * adapter)206 static void UnloadAdapterInternal(struct AudioManager *manager, struct AudioAdapter *adapter)
207 {
208 DHLOGI("Unload adapter.");
209 if (manager == nullptr || adapter == nullptr) {
210 DHLOGE("Param is nullptr.");
211 return;
212 }
213
214 AudioManagerContext *context = reinterpret_cast<AudioManagerContext *>(manager);
215 AudioAdapterContext *adapterContext = reinterpret_cast<AudioAdapterContext *>(adapter);
216 if (context->proxy_ == nullptr) {
217 DHLOGE("The context or proxy for the context is nullptr.");
218 return;
219 }
220
221 std::lock_guard<std::mutex> lock(context->mtx_);
222 for (auto it = context->adapters_.begin(); it != context->adapters_.end(); it++) {
223 if ((it->second).get() == adapterContext) {
224 int32_t ret = context->proxy_->UnloadAdapter(adapterContext->adapterName_);
225 if (ret != DH_SUCCESS) {
226 DHLOGE("Failed to unload adapter.");
227 return;
228 }
229 context->adapters_.erase(it);
230 break;
231 }
232 }
233 DHLOGI("Unload adapter success.");
234 }
235
ClearDescriptors()236 void AudioManagerContext::ClearDescriptors()
237 {
238 DHLOGI("Clear descriptors enter.");
239 for (auto &desc : descriptors_) {
240 if (desc.adapterName != nullptr) {
241 free(const_cast<char *>(desc.adapterName));
242 }
243 for (uint32_t i = 0; i < desc.portNum; i++) {
244 if (desc.ports[i].portName != nullptr) {
245 free(const_cast<char *>(desc.ports[i].portName));
246 }
247 }
248 free(desc.ports);
249 }
250 descriptors_.clear();
251 DHLOGI("Clear descriptors end.");
252 }
253
AudioManagerContext()254 AudioManagerContext::AudioManagerContext()
255 {
256 instance_.GetAllAdapters = GetAllAdaptersInternal;
257 instance_.LoadAdapter = LoadAdapterInternal;
258 instance_.UnloadAdapter = UnloadAdapterInternal;
259
260 instance_.ReleaseAudioManagerObject = nullptr;
261 }
262
~AudioManagerContext()263 AudioManagerContext::~AudioManagerContext()
264 {
265 adapters_.clear();
266 ClearDescriptors();
267 }
268
269 AudioManagerContext g_AudioManagerContext;
270
AudioManagerInit()271 static bool AudioManagerInit()
272 {
273 std::lock_guard<std::mutex> lock(g_AudioManagerContext.mtx_);
274
275 sptr<IAudioManager> audioMgr = IAudioManager::Get("daudio_primary_service", false);
276 if (audioMgr == nullptr) {
277 return false;
278 }
279 g_AudioManagerContext.proxy_ = audioMgr;
280 return true;
281 }
282 } // DistributedHardware
283 } // OHOS
284
285 #ifdef __cplusplus
286 extern "C" {
287 #endif
288
GetAudioManagerFuncs(void)289 struct AudioManager *GetAudioManagerFuncs(void)
290 {
291 if (OHOS::DistributedHardware::AudioManagerInit()) {
292 return &OHOS::DistributedHardware::g_AudioManagerContext.instance_;
293 } else {
294 return nullptr;
295 }
296 }
297
298 #ifdef __cplusplus
299 }
300 #endif
301