• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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