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 <securec.h>
16#include <string.h>
17#include "effect_core.h"
18#include "effect_host_common.h"
19#include "v1_0/effect_types_vdi.h"
20#include "v1_0/effect_factory.h"
21#include "osal_mem.h"
22#include "parse_effect_config.h"
23#include "audio_uhdf_log.h"
24
25#define AUDIO_EFFECT_PLAFORM_CONFIG HDF_CONFIG_DIR"/audio_effect.json"
26#define AUDIO_EFFECT_PRODUCT_CONFIG HDF_CHIP_PROD_CONFIG_DIR"/audio_effect.json"
27#define HDF_LOG_TAG HDF_AUDIO_EFFECT
28struct ConfigDescriptor *g_cfgDescs = NULL;
29
30static int32_t EffectModelIsSupplyEffectLibs(struct IEffectModel *self, bool *supply)
31{
32    if (self == NULL || supply == NULL) {
33        HDF_LOGE("%{public}s: invailid input params", __func__);
34        return HDF_ERR_INVALID_PARAM;
35    }
36
37    *supply = IsEffectLibExist();
38    return HDF_SUCCESS;
39}
40
41static int32_t EffectModelGetAllEffectDescriptors(struct IEffectModel *self,
42                                                  struct EffectControllerDescriptor *descs, uint32_t *descsLen)
43{
44    HDF_LOGD("enter to %{public}s", __func__);
45    int32_t ret;
46    uint32_t i;
47    uint32_t descNum = 0;
48    struct EffectFactory *factLib = NULL;
49
50    if (self == NULL || descs == NULL || descsLen == NULL) {
51        HDF_LOGE("%{public}s: invailid input params", __func__);
52        return HDF_ERR_INVALID_PARAM;
53    }
54
55    if (g_cfgDescs == NULL) {
56        HDF_LOGE("%{public}s: point is null!", __func__);
57        return HDF_FAILURE;
58    }
59    struct EffectControllerDescriptorVdi *descsVdi = (struct EffectControllerDescriptorVdi *)descs;
60    for (i = 0; i < g_cfgDescs->effectNum; i++) {
61        factLib = GetEffectLibFromList(g_cfgDescs->effectCfgDescs[i].library);
62        if (factLib == NULL) {
63            HDF_LOGE("%{public}s: GetEffectLibFromList fail!", __func__);
64            continue;
65        }
66        ret = factLib->GetDescriptor(factLib, g_cfgDescs->effectCfgDescs[i].effectId, &descsVdi[descNum]);
67        if (ret != HDF_SUCCESS) {
68            HDF_LOGE("%{public}s: GetDescriptor fail!", __func__);
69            continue;
70        }
71        descNum++;
72    }
73    *descsLen = descNum;
74    descs = (struct EffectControllerDescriptor *)descsVdi;
75    HDF_LOGD("%{public}s success", __func__);
76    return HDF_SUCCESS;
77}
78
79static int32_t EffectModelGetEffectDescriptor(struct IEffectModel *self, const char *uuid,
80    struct EffectControllerDescriptor *desc)
81{
82    HDF_LOGD("enter to %{public}s", __func__);
83    uint32_t i;
84    struct EffectFactory *factLib = NULL;
85    if (self == NULL || uuid == NULL || desc == NULL) {
86        HDF_LOGE("%{public}s: invailid input params", __func__);
87        return HDF_ERR_INVALID_PARAM;
88    }
89    struct EffectControllerDescriptorVdi *descVdi = (struct EffectControllerDescriptorVdi *)desc;
90    for (i = 0; i < g_cfgDescs->effectNum; i++) {
91        if (strcmp(uuid, g_cfgDescs->effectCfgDescs[i].effectId) != 0) {
92            continue;
93        }
94
95        factLib = GetEffectLibFromList(g_cfgDescs->effectCfgDescs[i].library);
96        if (factLib == NULL) {
97            HDF_LOGE("%{public}s: GetEffectLibFromList fail!", __func__);
98            return HDF_FAILURE;
99        }
100
101        if (factLib->GetDescriptor(factLib, uuid, descVdi) != HDF_SUCCESS) {
102            HDF_LOGE("%{public}s: GetDescriptor fail!", __func__);
103            return HDF_FAILURE;
104        }
105        HDF_LOGD("%{public}s success", __func__);
106        return HDF_SUCCESS;
107    }
108    desc = (struct EffectControllerDescriptor *)descVdi;
109    HDF_LOGE("%{public}s fail!", __func__);
110    return HDF_FAILURE;
111}
112
113static int32_t EffectModelCreateEffectController(struct IEffectModel *self, const struct EffectInfo *info,
114    struct IEffectControl **contoller, struct ControllerId *contollerId)
115{
116    if (self == NULL || info == NULL || contoller == NULL || contollerId == NULL) {
117        HDF_LOGE("%{public}s: invailid input params", __func__);
118        return HDF_ERR_INVALID_PARAM;
119    }
120
121    struct EffectFactory *lib = NULL;
122    struct ControllerManager *ctrlMgr = NULL;
123    struct IEffectControlVdi *ctrlOps = NULL;
124
125    lib = GetEffectLibFromList(info->libName);
126    CHECK_NULL_PTR_RETURN_VALUE(lib, HDF_FAILURE);
127    CHECK_NULL_PTR_RETURN_VALUE(lib->CreateController, HDF_FAILURE);
128
129    struct EffectInfoVdi *infoVdi = (struct EffectInfoVdi *)info;
130    lib->CreateController(lib, infoVdi, &ctrlOps);
131    CHECK_NULL_PTR_RETURN_VALUE(ctrlOps, HDF_FAILURE);
132
133    /* ctrlMgr mark it and using it in release process */
134    ctrlMgr = (struct ControllerManager *)OsalMemCalloc(sizeof(struct ControllerManager));
135    CHECK_NULL_PTR_RETURN_VALUE(ctrlMgr, HDF_FAILURE);
136
137    ctrlMgr->ctrlOps = ctrlOps;
138    ctrlMgr->effectId = strdup(info->effectId);
139    if (ctrlMgr->effectId == NULL) {
140        HDF_LOGE("%{public}s: strdup failed, info->effectId = %{public}s", __func__, info->effectId);
141        OsalMemFree(ctrlMgr);
142        return HDF_FAILURE;
143    }
144    ctrlMgr->ctrlImpls.EffectProcess = EffectControlEffectProcess;
145    ctrlMgr->ctrlImpls.SendCommand = EffectControlSendCommand;
146    ctrlMgr->ctrlImpls.GetEffectDescriptor = EffectGetOwnDescriptor;
147    ctrlMgr->ctrlImpls.EffectReverse = EffectControlEffectReverse;
148    *contoller = &ctrlMgr->ctrlImpls;
149    if (RegisterControllerToList(ctrlMgr) != HDF_SUCCESS) {
150        HDF_LOGE("%{public}s: register ctroller to list failed.", __func__);
151        OsalMemFree(ctrlMgr->effectId);
152        OsalMemFree(ctrlMgr);
153        *contoller = NULL;
154        return HDF_FAILURE;
155    }
156
157    // free after send reply
158    contollerId->libName = strdup(info->libName);
159    contollerId->effectId = strdup(info->effectId);
160    if (contollerId->libName == NULL || contollerId->effectId == NULL) {
161        HDF_LOGE("%{public}s: strdup failed, info->libName = %{public}s", __func__, info->libName);
162        OsalMemFree(ctrlMgr->effectId);
163        OsalMemFree(ctrlMgr);
164        *contoller = NULL;
165        return HDF_FAILURE;
166    }
167    return HDF_SUCCESS;
168}
169
170int32_t EffectModelDestroyEffectController(struct IEffectModel *self, const struct ControllerId *contollerId)
171{
172    if (self == NULL || contollerId == NULL) {
173        HDF_LOGE("%{public}s: invailid input params", __func__);
174        return HDF_ERR_INVALID_PARAM;
175    }
176    struct EffectFactory *lib = NULL;
177    struct ControllerManager *ctrlMgr = NULL;
178
179    lib = GetEffectLibFromList(contollerId->libName);
180    if (lib == NULL) {
181        HDF_LOGE("%{public}s: not match any lib", __func__);
182        return HDF_FAILURE;
183    }
184
185    ctrlMgr = GetControllerFromList(contollerId->effectId);
186    if (ctrlMgr == NULL) {
187        HDF_LOGE("%{public}s: controller manager not found", __func__);
188        return HDF_FAILURE;
189    }
190
191    if (ctrlMgr->ctrlOps == NULL) {
192        HDF_LOGE("%{public}s: controller has no options", __func__);
193        OsalMemFree(ctrlMgr);
194        ctrlMgr = NULL;
195        return HDF_FAILURE;
196    }
197
198    if (ctrlMgr->effectId != NULL) {
199        OsalMemFree(ctrlMgr->effectId);
200        ctrlMgr->effectId = NULL;
201    }
202
203    /* call the lib destroy method,then free controller manager */
204    lib->DestroyController(lib, ctrlMgr->ctrlOps);
205    OsalMemFree(ctrlMgr);
206    ctrlMgr = NULL;
207
208    return HDF_SUCCESS;
209}
210
211static int32_t RegLibraryInstByName(char *libPath)
212{
213    struct EffectFactory *factLib = NULL;
214    struct EffectFactory *(*GetFactoryLib)(void);
215    void *libHandle = NULL;
216    if (libPath == NULL) {
217        HDF_LOGE("%{public}s: invalid input param", __func__);
218        return HDF_FAILURE;
219    }
220
221    char pathBuf[PATH_MAX] = {'\0'};
222    if (realpath(libPath, pathBuf) == NULL) {
223        HDF_LOGE("%{public}s: path conversion failed", __func__);
224        return HDF_FAILURE;
225    }
226
227    if (strncmp(HDF_LIBRARY_DIR, pathBuf, strlen(HDF_LIBRARY_DIR)) != 0) {
228        HDF_LOGE("%{public}s: The file path is incorrect", __func__);
229        return HDF_FAILURE;
230    }
231
232    libHandle = dlopen(pathBuf, RTLD_LAZY);
233    if (libHandle == NULL) {
234        HDF_LOGE("%{public}s: open so failed, reason:%{public}s", __func__, dlerror());
235        return HDF_FAILURE;
236    }
237
238    GetFactoryLib = dlsym(libHandle, "GetEffectoyFactoryLib");
239    factLib = GetFactoryLib();
240    if (factLib == NULL) {
241        HDF_LOGE("%{public}s: get fact lib failed %{public}s", __func__, dlerror());
242        dlclose(libHandle);
243        return HDF_FAILURE;
244    }
245
246    if (RegisterEffectLibToList(libHandle, factLib) != HDF_SUCCESS) {
247        HDF_LOGE("%{public}s: register lib to list failed", __func__);
248        dlclose(libHandle);
249        return HDF_FAILURE;
250    }
251    return HDF_SUCCESS;
252}
253
254static int32_t RegLibraryInst(struct LibraryConfigDescriptor **libCfgDescs, const uint32_t libNum)
255{
256    int32_t ret;
257    uint32_t i;
258    char path[PATH_MAX];
259    char pathBuf[PATH_MAX];
260    if (libCfgDescs == NULL || libNum == 0 || libNum > HDF_EFFECT_LIB_NUM_MAX) {
261        HDF_LOGE("Invalid parameter!");
262        return HDF_ERR_INVALID_PARAM;
263    }
264
265    for (i = 0; i < libNum; i++) {
266#if (defined(__aarch64__) || defined(__x86_64__))
267ret = snprintf_s(path, PATH_MAX, PATH_MAX, "/vendor/lib64/%s.z.so", (*libCfgDescs)[i].libPath);
268#else
269ret = snprintf_s(path, PATH_MAX, PATH_MAX, "/vendor/lib/%s.z.so", (*libCfgDescs)[i].libPath);
270#endif
271        if (ret < 0) {
272            HDF_LOGE("%{public}s: get libPath failed", __func__);
273            continue;
274        }
275
276        if (realpath(path, pathBuf) == NULL) {
277            HDF_LOGE("%{public}s: realpath is null! [%{public}d]", __func__, errno);
278            continue;
279        }
280
281        if (RegLibraryInstByName(path) != HDF_SUCCESS) {
282            HDF_LOGE("%{public}s: regist library[%{private}s] failed", __func__, path);
283        }
284    }
285    return HDF_SUCCESS;
286}
287
288void ModelInit(void)
289{
290    FILE *file;
291    struct ConfigDescriptor *cfgDesc = NULL;
292    int32_t ret;
293    file = fopen(AUDIO_EFFECT_PRODUCT_CONFIG, "r");
294    if (file == NULL) {
295        ret = AudioEffectGetConfigDescriptor(AUDIO_EFFECT_PLAFORM_CONFIG, &cfgDesc);
296        HDF_LOGI("%{public}s: %{public}s!", __func__, AUDIO_EFFECT_PLAFORM_CONFIG);
297    } else {
298        ret = AudioEffectGetConfigDescriptor(AUDIO_EFFECT_PRODUCT_CONFIG, &cfgDesc);
299        HDF_LOGI("%{public}s: %{public}s!", __func__, AUDIO_EFFECT_PRODUCT_CONFIG);
300        (void)fclose(file);
301    }
302    if (ret != HDF_SUCCESS) {
303        HDF_LOGE("%{public}s: AudioEffectGetConfigDescriptor fail!", __func__);
304        return;
305    }
306
307    if (cfgDesc == NULL || cfgDesc->effectCfgDescs == NULL || cfgDesc->libCfgDescs == NULL) {
308        HDF_LOGE("cfgDesc is null!");
309        return;
310    }
311
312    g_cfgDescs = cfgDesc;
313    if (RegLibraryInst(&(cfgDesc->libCfgDescs), cfgDesc->libNum) != HDF_SUCCESS) {
314        HDF_LOGE("%{public}s: RegLibraryInst failed", __func__);
315        AudioEffectReleaseCfgDesc(cfgDesc);
316        return;
317    }
318
319    HDF_LOGD("%{public}s end!", __func__);
320}
321
322struct IEffectModel *EffectModelImplGetInstance(void)
323{
324    struct EffectModelService *service = (struct EffectModelService *)OsalMemCalloc(sizeof(struct EffectModelService));
325    if (service == NULL) {
326        HDF_LOGE("%{public}s: malloc EffectModelService obj failed!", __func__);
327        return NULL;
328    }
329
330    ModelInit();
331    service->interface.IsSupplyEffectLibs = EffectModelIsSupplyEffectLibs;
332    service->interface.GetAllEffectDescriptors = EffectModelGetAllEffectDescriptors;
333    service->interface.CreateEffectController = EffectModelCreateEffectController;
334    service->interface.DestroyEffectController = EffectModelDestroyEffectController;
335    service->interface.GetEffectDescriptor = EffectModelGetEffectDescriptor;
336
337    return &service->interface;
338}
339
340void EffectModelImplRelease(struct IEffectModel *instance)
341{
342    if (instance == NULL) {
343        return;
344    }
345
346    AudioEffectReleaseCfgDesc(g_cfgDescs);
347    ReleaseLibFromList();
348    struct EffectModelService *service = CONTAINER_OF(instance, struct EffectModelService, interface);
349    if (service == NULL) {
350        return;
351    }
352    OsalMemFree(service);
353    service = NULL;
354}
355