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 "audio_manager_vdi.h"
16
17 #include <dlfcn.h>
18 #include <malloc.h>
19 #include "osal_mem.h"
20 #include <hdf_base.h>
21 #include "audio_uhdf_log.h"
22 #include "audio_adapter_vdi.h"
23 #include "v2_0/iaudio_adapter.h"
24
25 #define HDF_LOG_TAG HDF_AUDIO_PRIMARY_IMPL
26
27 typedef struct IAudioManagerVdi* (*AudioManagerCreateIfInstanceVdi)(void);
28
29 struct AudioManagerPrivVdi {
30 struct IAudioManager interface;
31 void *handle;
32 AudioManagerCreateIfInstanceVdi managerFuncs;
33 struct IAudioManagerVdi *vdiManager;
34 struct AudioAdapterDescriptor descs[AUDIO_VDI_ADAPTER_NUM_MAX];
35 uint32_t descsCount;
36 struct AudioAdapterDescriptorVdi *vdiDescs;
37 uint32_t vdiDescsCount;
38 };
39
AudioManagerReleasePort(struct AudioPort ** ports,uint32_t portsLen)40 static void AudioManagerReleasePort(struct AudioPort **ports, uint32_t portsLen)
41 {
42 CHECK_NULL_PTR_RETURN(ports);
43
44 if (portsLen == 0 || portsLen > AUDIO_VDI_PORT_NUM_MAX) {
45 AUDIO_FUNC_LOGE("audio vdiManager portsLen is invalid");
46 return;
47 }
48
49 struct AudioPort *portsTmp = *ports;
50 for (uint32_t i = 0; i < portsLen; i++) {
51 OsalMemFree((void *)portsTmp[i].portName);
52 }
53 OsalMemFree((void *)portsTmp);
54 *ports = NULL;
55 }
56
AudioManagerReleaseVdiPort(struct AudioPortVdi ** vdiPorts,uint32_t portsLen)57 static void AudioManagerReleaseVdiPort(struct AudioPortVdi **vdiPorts, uint32_t portsLen)
58 {
59 CHECK_NULL_PTR_RETURN(vdiPorts);
60
61 if (portsLen == 0 || portsLen > AUDIO_VDI_PORT_NUM_MAX) {
62 AUDIO_FUNC_LOGE("audio vdiManager portsLen is invalid");
63 return;
64 }
65
66 struct AudioPortVdi *portsTmp = *vdiPorts;
67 for (uint32_t i = 0; i < portsLen; i++) {
68 OsalMemFree((void *)portsTmp[i].portName);
69 }
70 OsalMemFree((void *)portsTmp);
71 *vdiPorts = NULL;
72 }
73
AudioManagerReleaseDesc(struct AudioAdapterDescriptor * desc)74 static void AudioManagerReleaseDesc(struct AudioAdapterDescriptor *desc)
75 {
76 OsalMemFree((void *)desc->adapterName);
77 desc->adapterName = NULL;
78 if (desc->ports != NULL) {
79 AudioManagerReleasePort(&desc->ports, desc->portsLen);
80 desc->portsLen = 0;
81 }
82 }
83
AudioManagerReleaseVdiDesc(struct AudioAdapterDescriptorVdi * vdiDesc)84 static void AudioManagerReleaseVdiDesc(struct AudioAdapterDescriptorVdi *vdiDesc)
85 {
86 OsalMemFree((void *)vdiDesc->adapterName);
87 vdiDesc->adapterName = NULL;
88 if (vdiDesc->ports != NULL) {
89 AudioManagerReleaseVdiPort(&vdiDesc->ports, vdiDesc->portsLen);
90 vdiDesc->portsLen = 0;
91 }
92 #if defined CONFIG_USE_JEMALLOC_DFX_INTF
93 int err = mallopt(M_FLUSH_THREAD_CACHE, 0);
94 if (err != HDF_SUCCESS) {
95 AUDIO_FUNC_LOGE("%{public}s :release cache error, m_purge = %{public}d", __func__, err);
96 }
97 #endif
98 }
99
AudioManagerReleaseDescs(struct AudioAdapterDescriptor * descs,uint32_t descsCount)100 static void AudioManagerReleaseDescs(struct AudioAdapterDescriptor *descs, uint32_t descsCount)
101 {
102 if (descsCount == 0 || descsCount > AUDIO_VDI_PORT_NUM_MAX) {
103 AUDIO_FUNC_LOGE("audio vdiManager descsCount is invalid");
104 return;
105 }
106
107 for (uint32_t i = 0; i < descsCount; i++) {
108 AudioManagerReleaseDesc(&descs[i]);
109 }
110 }
111
AudioManagerPortToVdiPort(const struct AudioAdapterDescriptor * desc,struct AudioAdapterDescriptorVdi * vdiDesc)112 static int32_t AudioManagerPortToVdiPort(const struct AudioAdapterDescriptor *desc,
113 struct AudioAdapterDescriptorVdi *vdiDesc)
114 {
115 if (desc->portsLen == 0 || desc->portsLen > AUDIO_VDI_PORT_NUM_MAX) {
116 AUDIO_FUNC_LOGE("audio desc portsLen is invalid");
117 return HDF_ERR_NOT_SUPPORT;
118 }
119
120 struct AudioPortVdi *vdiPorts = (struct AudioPortVdi *)OsalMemCalloc(sizeof(*vdiPorts) * desc->portsLen);
121 if (vdiPorts == NULL) {
122 AUDIO_FUNC_LOGE("OsalMemCalloc AudioPortVdi fail");
123 return HDF_ERR_MALLOC_FAIL;
124 }
125
126 for (uint32_t i = 0; i < desc->portsLen; i++) {
127 vdiPorts[i].portName = strdup(desc->ports[i].portName);
128 vdiPorts[i].portId = desc->ports[i].portId;
129 vdiPorts[i].dir = (enum AudioPortDirectionVdi)desc->ports[i].dir;
130 }
131
132 vdiDesc->ports = vdiPorts;
133 vdiDesc->portsLen = desc->portsLen;
134
135 return HDF_SUCCESS;
136 }
137
AudioManagerVdiPortToPort(struct AudioAdapterDescriptorVdi * vdiDesc,struct AudioAdapterDescriptor * desc)138 static int32_t AudioManagerVdiPortToPort(struct AudioAdapterDescriptorVdi *vdiDesc, struct AudioAdapterDescriptor *desc)
139 {
140 if (vdiDesc->portsLen == 0 || vdiDesc->portsLen > AUDIO_VDI_PORT_NUM_MAX) {
141 AUDIO_FUNC_LOGE("audio vdiDesc portsLen is invalid");
142 return HDF_ERR_NOT_SUPPORT;
143 }
144
145 /* audio stub free ports */
146 struct AudioPort *ports = (struct AudioPort *)OsalMemCalloc(sizeof(*ports) * vdiDesc->portsLen);
147 if (ports == NULL) {
148 AUDIO_FUNC_LOGE("OsalMemCalloc AudioPort fail");
149 return HDF_ERR_MALLOC_FAIL;
150 }
151
152 for (uint32_t i = 0; i < vdiDesc->portsLen; i++) {
153 ports[i].portName = strdup(vdiDesc->ports[i].portName);
154 ports[i].portId = vdiDesc->ports[i].portId;
155 ports[i].dir = (enum AudioPortDirection)vdiDesc->ports[i].dir;
156 }
157
158 desc->ports = ports;
159 desc->portsLen = vdiDesc->portsLen;
160
161 return HDF_SUCCESS;
162 }
163
AudioManagerDescToVdiDesc(const struct AudioAdapterDescriptor * desc,struct AudioAdapterDescriptorVdi * vdiDesc)164 static int32_t AudioManagerDescToVdiDesc(const struct AudioAdapterDescriptor *desc,
165 struct AudioAdapterDescriptorVdi *vdiDesc)
166 {
167 int32_t ret = AudioManagerPortToVdiPort(desc, vdiDesc);
168 if (ret != HDF_SUCCESS) {
169 AUDIO_FUNC_LOGE("audio vdiManager vdiPort fail");
170 return HDF_FAILURE;
171 }
172
173 vdiDesc->adapterName = strdup(desc->adapterName);
174 AUDIO_FUNC_LOGI("audio vdiManager load adapterName=%{public}s", vdiDesc->adapterName);
175
176 return HDF_SUCCESS;
177 }
178
AudioManagerVdiDescsToDescs(struct AudioAdapterDescriptorVdi * vdiDescs,uint32_t vdiDescsCount,struct AudioAdapterDescriptor * descs,uint32_t * descsCount)179 static int32_t AudioManagerVdiDescsToDescs(struct AudioAdapterDescriptorVdi *vdiDescs, uint32_t vdiDescsCount,
180 struct AudioAdapterDescriptor *descs, uint32_t *descsCount)
181 {
182 if (vdiDescsCount == 0 || vdiDescsCount > AUDIO_VDI_ADAPTER_NUM_MAX) {
183 AUDIO_FUNC_LOGE("audio vdiDescsCount=%{public}d is error", vdiDescsCount);
184 return HDF_ERR_NOT_SUPPORT;
185 }
186
187 uint32_t count = (*descsCount <= (uint32_t)vdiDescsCount) ? (*descsCount) : (uint32_t)vdiDescsCount;
188 AUDIO_FUNC_LOGI("audio vdiManager all adapter count=%{public}u, vdiCount=%{public}d", count, vdiDescsCount);
189
190 for (uint32_t i = 0; i < count; i++) {
191 int32_t ret = AudioManagerVdiPortToPort(&vdiDescs[i], &descs[i]);
192 if (ret != HDF_SUCCESS) {
193 AUDIO_FUNC_LOGE("audio vdiManager port fail");
194 return HDF_FAILURE;
195 }
196 descs[i].adapterName = strdup(vdiDescs[i].adapterName); // audio stub free adapterName
197 AUDIO_FUNC_LOGI("audio vdiManager get adapterName=%{public}s", descs[i].adapterName);
198 }
199
200 *descsCount = count;
201 return HDF_SUCCESS;
202 }
203
AudioManagerPrivVdiGetAllAdapters(struct AudioManagerPrivVdi * priv,struct AudioAdapterDescriptor * descs,uint32_t * descsLen)204 int32_t AudioManagerPrivVdiGetAllAdapters(struct AudioManagerPrivVdi *priv,
205 struct AudioAdapterDescriptor *descs, uint32_t *descsLen)
206 {
207 int32_t ret;
208 priv->vdiDescs = (struct AudioAdapterDescriptorVdi *)OsalMemCalloc(
209 sizeof(struct AudioAdapterDescriptorVdi) * (*descsLen));
210 CHECK_NULL_PTR_RETURN_VALUE(priv->vdiDescs, HDF_ERR_NOT_SUPPORT);
211
212 priv->vdiDescsCount = *descsLen;
213 ret = priv->vdiManager->GetAllAdapters(priv->vdiManager, priv->vdiDescs, &priv->vdiDescsCount);
214 if (ret != HDF_SUCCESS) {
215 AUDIO_FUNC_LOGE("audio vdiManager call GetAllAdapters fail, ret=%{public}d", ret);
216 free(priv->vdiDescs);
217 priv->vdiDescs = NULL;
218 priv->vdiDescsCount = 0;
219 return HDF_FAILURE;
220 }
221
222 ret = AudioManagerVdiDescsToDescs(priv->vdiDescs, priv->vdiDescsCount, descs, descsLen);
223 if (ret != HDF_SUCCESS) {
224 AUDIO_FUNC_LOGE("audio vdiManager DescsVdi To Descs fail, ret=%{public}d", ret);
225 AudioManagerReleaseDescs(descs, *descsLen);
226 free(priv->vdiDescs);
227 priv->vdiDescs = NULL;
228 priv->vdiDescsCount = 0;
229 return HDF_FAILURE;
230 }
231
232 priv->descsCount = AUDIO_VDI_ADAPTER_NUM_MAX;
233 ret = AudioManagerVdiDescsToDescs(priv->vdiDescs, priv->vdiDescsCount, priv->descs, &priv->descsCount);
234 if (ret != HDF_SUCCESS) {
235 AUDIO_FUNC_LOGE("audio vdiManager DescsVdi To Descs fail, ret=%{public}d", ret);
236 AudioManagerReleaseDescs(descs, *descsLen);
237 AudioManagerReleaseDescs(priv->descs, priv->descsCount);
238 priv->descsCount = 0;
239 free(priv->vdiDescs);
240 priv->vdiDescs = NULL;
241 priv->vdiDescsCount = 0;
242 return HDF_FAILURE;
243 }
244 return HDF_SUCCESS;
245 }
246
AudioManagerVendorGetAllAdapters(struct IAudioManager * manager,struct AudioAdapterDescriptor * descs,uint32_t * descsLen)247 int32_t AudioManagerVendorGetAllAdapters(struct IAudioManager *manager,
248 struct AudioAdapterDescriptor *descs, uint32_t *descsLen)
249 {
250 AUDIO_FUNC_LOGD("enter to %{public}s", __func__);
251 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_ERR_INVALID_PARAM);
252 CHECK_NULL_PTR_RETURN_VALUE(descs, HDF_ERR_INVALID_PARAM);
253 CHECK_NULL_PTR_RETURN_VALUE(descsLen, HDF_ERR_INVALID_PARAM);
254
255 struct AudioManagerPrivVdi *priv = (struct AudioManagerPrivVdi *)manager;
256 if (priv->vdiManager == NULL) {
257 AUDIO_FUNC_LOGE("audio vdiManager is null");
258 return HDF_ERR_INVALID_PARAM;
259 }
260
261 if (*descsLen > AUDIO_VDI_ADAPTER_NUM_MAX) {
262 AUDIO_FUNC_LOGE("audio adapter num demanded too large");
263 return HDF_ERR_INVALID_PARAM;
264 }
265
266 if (priv->vdiDescsCount != 0 && priv->vdiDescs != NULL && priv->vdiDescsCount >= *descsLen) {
267 int32_t ret = AudioManagerVdiDescsToDescs(priv->vdiDescs, priv->vdiDescsCount, descs, descsLen);
268 if (ret != HDF_SUCCESS) {
269 AUDIO_FUNC_LOGE("audio vdiManager DescsVdi To Descs fail, ret=%{public}d", ret);
270 AudioManagerReleaseDescs(descs, *descsLen);
271 return HDF_FAILURE;
272 }
273 return HDF_SUCCESS;
274 }
275
276 if (priv->vdiDescs != NULL) {
277 free(priv->vdiDescs);
278 priv->vdiDescs = NULL;
279 }
280
281 return AudioManagerPrivVdiGetAllAdapters(priv, descs, descsLen);
282 }
283
AudioManagerVendorFindAdapterPos(struct IAudioManager * manager,const char * adapterName)284 static uint32_t AudioManagerVendorFindAdapterPos(struct IAudioManager *manager, const char *adapterName)
285 {
286 CHECK_NULL_PTR_RETURN_VALUE(adapterName, AUDIO_VDI_ADAPTER_NUM_MAX);
287 struct AudioManagerPrivVdi *priv = (struct AudioManagerPrivVdi *)manager;
288 CHECK_NULL_PTR_RETURN_VALUE(priv->vdiManager, AUDIO_VDI_ADAPTER_NUM_MAX);
289
290 for (uint32_t descIndex = 0; descIndex < priv->descsCount; descIndex++) {
291 if (strcmp(adapterName, priv->descs[descIndex].adapterName) == 0) {
292 return descIndex;
293 }
294 }
295
296 AUDIO_FUNC_LOGI("can not find adapterName(%{public}s) pos", adapterName);
297 return AUDIO_VDI_ADAPTER_NUM_MAX;
298 }
299
AudioManagerVendorLoadAdapter(struct IAudioManager * manager,const struct AudioAdapterDescriptor * desc,struct IAudioAdapter ** adapter)300 int32_t AudioManagerVendorLoadAdapter(struct IAudioManager *manager, const struct AudioAdapterDescriptor *desc,
301 struct IAudioAdapter **adapter)
302 {
303 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_ERR_INVALID_PARAM);
304 CHECK_NULL_PTR_RETURN_VALUE(desc, HDF_ERR_INVALID_PARAM);
305 CHECK_NULL_PTR_RETURN_VALUE(adapter, HDF_ERR_INVALID_PARAM);
306
307 struct AudioManagerPrivVdi *priv = (struct AudioManagerPrivVdi *)manager;
308 CHECK_NULL_PTR_RETURN_VALUE(priv->vdiManager, HDF_ERR_INVALID_PARAM);
309 CHECK_NULL_PTR_RETURN_VALUE(priv->vdiManager->LoadAdapter, HDF_ERR_INVALID_PARAM);
310
311 uint32_t descIndex = AudioManagerVendorFindAdapterPos(manager, desc->adapterName);
312 if (descIndex >= AUDIO_VDI_ADAPTER_NUM_MAX) {
313 AUDIO_FUNC_LOGE("audio vdiManager find adapter pos");
314 return HDF_FAILURE;
315 }
316
317 uint32_t count = AudioGetAdapterRefCntVdi(descIndex);
318 if (count > 0 && count != UINT_MAX) {
319 return AudioIncreaseAdapterRefVdi(descIndex, adapter);
320 }
321
322 struct AudioAdapterDescriptorVdi vdiDesc;
323 int32_t ret = AudioManagerDescToVdiDesc(desc, &vdiDesc);
324 if (ret != HDF_SUCCESS) {
325 AudioManagerReleaseVdiDesc(&vdiDesc);
326 AUDIO_FUNC_LOGE("audio vdiManager desc To vdiDesc fail, ret=%{public}d", ret);
327 return HDF_FAILURE;
328 }
329
330 struct IAudioAdapterVdi *vdiAdapter = NULL;
331 ret = priv->vdiManager->LoadAdapter(priv->vdiManager, &vdiDesc, &vdiAdapter);
332 AudioManagerReleaseVdiDesc(&vdiDesc);
333 if (ret != HDF_SUCCESS) {
334 AUDIO_FUNC_LOGE("audio vdiManager call LoadAdapter fail, ret=%{public}d", ret);
335 return HDF_FAILURE;
336 }
337
338 *adapter = AudioCreateAdapterVdi(descIndex, vdiAdapter);
339 if (*adapter == NULL) {
340 AUDIO_FUNC_LOGE("audio vdiManager create adapter fail");
341 priv->vdiManager->UnloadAdapter(priv->vdiManager, vdiAdapter);
342 return HDF_FAILURE;
343 }
344
345 AUDIO_FUNC_LOGD("audio vdiManager load vdiAdapter success");
346 return HDF_SUCCESS;
347 }
348
AudioManagerVendorUnloadAdapter(struct IAudioManager * manager,const char * adapterName)349 static int32_t AudioManagerVendorUnloadAdapter(struct IAudioManager *manager, const char *adapterName)
350 {
351 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_ERR_INVALID_PARAM);
352 CHECK_NULL_PTR_RETURN_VALUE(adapterName, HDF_ERR_INVALID_PARAM);
353
354 struct AudioManagerPrivVdi *priv = (struct AudioManagerPrivVdi *)manager;
355 CHECK_NULL_PTR_RETURN_VALUE(priv->vdiManager, HDF_ERR_INVALID_PARAM);
356 CHECK_NULL_PTR_RETURN_VALUE(priv->vdiManager->UnloadAdapter, HDF_ERR_INVALID_PARAM);
357
358 uint32_t descIndex = AudioManagerVendorFindAdapterPos(manager, adapterName);
359 if (descIndex >= AUDIO_VDI_ADAPTER_NUM_MAX) {
360 AUDIO_FUNC_LOGE("AudioManagerVendorUnloadAdapter descIndex error");
361 return HDF_ERR_INVALID_PARAM;
362 }
363
364 struct IAudioAdapterVdi *vdiAdapter = AudioGetVdiAdapterByDescIndexVdi(descIndex);
365 if (vdiAdapter == NULL) {
366 AUDIO_FUNC_LOGW("audio vdiManager vdiAdapter had unloaded, index=%{public}d", descIndex);
367 return HDF_SUCCESS;
368 }
369
370 uint32_t count = AudioGetAdapterRefCntVdi(descIndex);
371 if (count > 1 && count != UINT_MAX) {
372 AudioDecreaseAdapterRefVdi(descIndex);
373 return HDF_SUCCESS;
374 }
375
376 priv->vdiManager->UnloadAdapter(priv->vdiManager, vdiAdapter);
377
378 AudioReleaseAdapterVdi(descIndex);
379 AUDIO_FUNC_LOGD("audio vdiManager unload vdiAdapter success");
380 return HDF_SUCCESS;
381 }
382
ReleaseAudioManagerVendorObject(struct IAudioManager * manager)383 int32_t ReleaseAudioManagerVendorObject(struct IAudioManager *manager)
384 {
385 uint32_t descIndex;
386
387 if (manager == NULL) {
388 AUDIO_FUNC_LOGI("auido manager had released");
389 return HDF_SUCCESS;
390 }
391
392 struct AudioManagerPrivVdi *priv = (struct AudioManagerPrivVdi *)manager;
393 if (priv->handle != NULL) {
394 dlclose(priv->handle);
395 priv->handle = NULL;
396 }
397
398 for (descIndex = 0; descIndex < priv->descsCount; descIndex++) {
399 AudioEnforceClearAdapterRefCntVdi(descIndex);
400 int32_t ret = AudioManagerVendorUnloadAdapter(manager, priv->descs[descIndex].adapterName);
401 if (ret != HDF_SUCCESS) {
402 AUDIO_FUNC_LOGW("audio unload adapter error, ret=%{pulbic}d, adaptername=%{pulbic}s", ret,
403 priv->descs[descIndex].adapterName);
404 }
405 }
406
407 AudioManagerReleaseDescs(priv->descs, priv->descsCount);
408 OsalMemFree((void *)priv);
409 return HDF_SUCCESS;
410 }
411
AudioManagerLoadVendorLib(struct AudioManagerPrivVdi * priv)412 static int32_t AudioManagerLoadVendorLib(struct AudioManagerPrivVdi *priv)
413 {
414 char *error = NULL;
415 const char *hdiAudioVendorLibPath = HDF_LIBRARY_FULL_PATH("libaudio_primary_impl");
416
417 priv->handle = dlopen(hdiAudioVendorLibPath, RTLD_LAZY);
418 if (priv->handle == NULL) {
419 error = dlerror();
420 AUDIO_FUNC_LOGE("audio vdiManager load path%{public}s, dlopen err=%{public}s", hdiAudioVendorLibPath, error);
421 return HDF_FAILURE;
422 }
423
424 (void)dlerror(); // clear existing error
425
426 priv->managerFuncs = dlsym(priv->handle, "AudioManagerCreateIfInstance");
427 if (priv->managerFuncs == NULL) {
428 error = dlerror();
429 AUDIO_FUNC_LOGE("dlsym AudioManagerCreateIfInstance err=%{public}s", error);
430 dlclose(priv->handle);
431 priv->handle = NULL;
432 return HDF_FAILURE;
433 }
434
435 AUDIO_FUNC_LOGD("audio load vendor lib success");
436 return HDF_SUCCESS;
437 }
438
AudioManagerCreateIfInstance(void)439 struct IAudioManager *AudioManagerCreateIfInstance(void)
440 {
441 AUDIO_FUNC_LOGD("audio vdiManager create instance");
442
443 struct AudioManagerPrivVdi *priv = (struct AudioManagerPrivVdi *)OsalMemCalloc(sizeof(*priv));
444 if (priv == NULL) {
445 AUDIO_FUNC_LOGE("OsalMemCalloc AudioManagerPrivVdi failed");
446 return NULL;
447 }
448
449 int32_t ret = AudioManagerLoadVendorLib(priv);
450 if (ret != HDF_SUCCESS) {
451 AUDIO_FUNC_LOGE("audio load lib failed ret=%{pulbic}d", ret);
452 OsalMemFree((void *)priv);
453 return NULL;
454 }
455
456 priv->vdiManager = (struct IAudioManagerVdi *)priv->managerFuncs();
457 if (priv->vdiManager == NULL) {
458 AUDIO_FUNC_LOGE("audio call vdi manager func failed");
459 OsalMemFree((void *)priv);
460 return NULL;
461 }
462
463 priv->interface.GetAllAdapters = AudioManagerVendorGetAllAdapters;
464 priv->interface.LoadAdapter = AudioManagerVendorLoadAdapter;
465 priv->interface.UnloadAdapter = AudioManagerVendorUnloadAdapter;
466 priv->interface.ReleaseAudioManagerObject = ReleaseAudioManagerVendorObject;
467
468 return &(priv->interface);
469 }
470
AudioManagerDestroyIfInstance(struct IAudioManager * manager)471 int32_t AudioManagerDestroyIfInstance(struct IAudioManager *manager)
472 {
473 return ReleaseAudioManagerVendorObject(manager);
474 }