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