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 
16 #include <ctype.h>
17 #include <errno.h>
18 #include <limits.h>
19 #include <stddef.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "cJSON.h"
25 #include "osal_mem.h"
26 #include "securec.h"
27 
28 #include "parse_effect_config.h"
29 #include "audio_uhdf_log.h"
30 
31 #define HDF_EFFECT_NUM_MAX 32
32 #define HDF_EFFECT_CONFIG_SIZE_MAX ((HDF_EFFECT_NUM_MAX) * 1024)
33 #define HDF_EFFECT_NAME_LEN 64
34 #define HDF_LOG_TAG HDF_AUDIO_EFFECT
35 
GetAudioEffectConfig(const char * fpath)36 static char *GetAudioEffectConfig(const char *fpath)
37 {
38     char *pJsonStr = NULL;
39     if (fpath == NULL) {
40         HDF_LOGE("%{public}s: fpath is null!", __func__);
41         return NULL;
42     }
43     char pathBuf[PATH_MAX] = {'\0'};
44     if (realpath(fpath, pathBuf) == NULL) {
45         HDF_LOGE("%{public}s: realpath is null! [%{public}d]", __func__, errno);
46         return NULL;
47     }
48 
49     FILE *fp = fopen(pathBuf, "r");
50     if (fp == NULL) {
51         HDF_LOGE("%{public}s: can not open config file! [%{public}d]", __func__, errno);
52         return NULL;
53     }
54     if (fseek(fp, 0, SEEK_END) != HDF_SUCCESS) {
55         HDF_LOGE("%{public}s: fseek fail! [%{public}d]", __func__, errno);
56         (void)fclose(fp);
57         return NULL;
58     }
59     int32_t jsonStrSize = ftell(fp);
60     if (jsonStrSize <= 0) {
61         HDF_LOGE("%{public}s: ftell fail! [%{public}d]", __func__, errno);
62         (void)fclose(fp);
63         return NULL;
64     }
65     rewind(fp);
66     if (jsonStrSize > HDF_EFFECT_CONFIG_SIZE_MAX) {
67         HDF_LOGE("%{public}s: The configuration file is too large to load!", __func__);
68         (void)fclose(fp);
69         return NULL;
70     }
71     pJsonStr = (char *)OsalMemCalloc((uint32_t)jsonStrSize + 1);
72     if (pJsonStr == NULL) {
73         HDF_LOGE("%{public}s: alloc pJsonStr failed!", __func__);
74         (void)fclose(fp);
75         return NULL;
76     }
77     if (fread(pJsonStr, jsonStrSize, 1, fp) != 1) {
78         HDF_LOGE("%{public}s: read to file fail! [%{public}d]", __func__, errno);
79         OsalMemFree((void *)pJsonStr);
80         (void)fclose(fp);
81         return NULL;
82     }
83     (void)fclose(fp);
84     return pJsonStr;
85 }
86 
GetAudioEffectConfigToJsonObj(const char * fpath)87 cJSON *GetAudioEffectConfigToJsonObj(const char *fpath)
88 {
89     char *pJsonStr = GetAudioEffectConfig(fpath);
90     if (pJsonStr == NULL) {
91         HDF_LOGE("%{public}s: get audio effect config failed!", __func__);
92         return NULL;
93     }
94     cJSON *cJsonObj = cJSON_Parse(pJsonStr);
95     if (cJsonObj == NULL) {
96         HDF_LOGE("%{public}s: cJSON_Parse failed!", __func__);
97         OsalMemFree((void *)pJsonStr);
98         return NULL;
99     }
100     OsalMemFree((void *)pJsonStr);
101     return cJsonObj;
102 }
103 
AudioEffectGetAndCheckName(const cJSON * cJSONObj,const char * name)104 static char *AudioEffectGetAndCheckName(const cJSON *cJSONObj, const char *name)
105 {
106     if (cJSONObj == NULL || name == NULL) {
107         HDF_LOGE("%{public}s: invalid parameter!", __func__);
108         return NULL;
109     }
110 
111     cJSON *cJSONName = cJSON_GetObjectItem(cJSONObj, name);
112     if (cJSONName == NULL || cJSONName->valuestring == NULL) {
113         HDF_LOGE("%{public}s: cJSONName or cJSONName->valuestring is null!", __func__);
114         return NULL;
115     }
116 
117     char *effectValue = cJSONName->valuestring;
118     if (strlen(effectValue) == 0) {
119         HDF_LOGE("%{public}s: effectValue is null!", __func__);
120         return NULL;
121     }
122 
123     if (strcmp(name, "effectId")) {
124         if (!isalpha(*effectValue)) { // Names must begin with a letter
125             HDF_LOGE("%{public}s: effectValue is illegal!", __func__);
126             return NULL;
127         }
128         effectValue++;
129     }
130 
131     while (*effectValue != '\0') {
132         if (*effectValue == '_' || (strcmp(name, "effectId") == 0 && *effectValue == '-')) {
133             effectValue++;
134             continue;
135         }
136 
137         if (!isalnum(*effectValue++)) {
138             HDF_LOGE("%{public}s: effectValue is illegal!, %{public}c", __func__, *effectValue);
139             return NULL;
140         }
141     }
142     return cJSONName->valuestring;
143 }
144 
AudioEffectParseItem(const cJSON * cJSONObj,const char * item,const char ** dest)145 static int32_t AudioEffectParseItem(const cJSON *cJSONObj, const char *item, const char **dest)
146 {
147     if (cJSONObj == NULL || item == NULL || dest == NULL) {
148         HDF_LOGE("%{public}s: invalid parameter!", __func__);
149         return HDF_ERR_INVALID_PARAM;
150     }
151 
152     const char *itemName = AudioEffectGetAndCheckName(cJSONObj, item);
153     if (itemName == NULL) {
154         HDF_LOGE("%{public}s: get %{public}s fail!", __func__, item);
155         return HDF_FAILURE;
156     }
157 
158     *dest = (char *)OsalMemCalloc(HDF_EFFECT_NAME_LEN * sizeof(char));
159     if (*dest == NULL) {
160         HDF_LOGE("%{public}s: out of memory! Item is %{public}s", __func__, item);
161         return HDF_ERR_MALLOC_FAIL;
162     }
163 
164     if (memcpy_s((void *)(*dest), HDF_EFFECT_NAME_LEN, itemName, strlen(itemName)) != EOK) {
165         HDF_LOGE("%{public}s: memcpy_s effect name fail! Item is %{public}s", __func__, item);
166         OsalMemFree((void *)(*dest));
167         *dest = NULL;
168         return HDF_FAILURE;
169     }
170     return HDF_SUCCESS;
171 }
172 
AudioEffectParseEffect(const cJSON * effectObj,struct EffectConfigDescriptor * effectDesc)173 static int32_t AudioEffectParseEffect(const cJSON *effectObj, struct EffectConfigDescriptor *effectDesc)
174 {
175     if (effectObj == NULL || effectDesc == NULL) {
176         HDF_LOGE("%{public}s: invalid parameter!", __func__);
177         return HDF_ERR_INVALID_PARAM;
178     }
179 
180     if (AudioEffectParseItem(effectObj, "name", &(effectDesc->name)) != HDF_SUCCESS) {
181         HDF_LOGE("%{public}s: parse item %{public}s fail!", __func__, "name");
182         return HDF_FAILURE;
183     }
184 
185     if (AudioEffectParseItem(effectObj, "library", &(effectDesc->library)) != HDF_SUCCESS) {
186         HDF_LOGE("%{public}s: parse item %{public}s fail!", __func__, "library");
187         OsalMemFree((void *)effectDesc->name);
188         return HDF_FAILURE;
189     }
190 
191     if (AudioEffectParseItem(effectObj, "effectId", &(effectDesc->effectId)) != HDF_SUCCESS) {
192         HDF_LOGE("%{public}s: parse item %{public}s fail!", __func__, "library");
193         OsalMemFree((void *)effectDesc->name);
194         OsalMemFree((void *)effectDesc->library);
195         return HDF_FAILURE;
196     }
197 
198     return HDF_SUCCESS;
199 }
200 
AudioEffectReleaseDescs(struct EffectConfigDescriptor * effectDescs,int32_t effectNum)201 static void AudioEffectReleaseDescs(struct EffectConfigDescriptor *effectDescs, int32_t effectNum)
202 {
203     int32_t i = 0;
204 
205     if (effectDescs == NULL || effectNum <= 0 || effectNum > HDF_EFFECT_NUM_MAX) {
206         HDF_LOGE("%{public}s: effectDescs is null or effectNum is invalid!", __func__);
207         return;
208     }
209 
210     for (i = 0; i < effectNum; i++) {
211         OsalMemFree((void *)effectDescs[i].name);
212         OsalMemFree((void *)effectDescs[i].library);
213         OsalMemFree((void *)effectDescs[i].effectId);
214     }
215 }
216 
AudioEffectGetEffectCfgDescs(cJSON * cJsonObj,const char * item,struct ConfigDescriptor * cfgDesc)217 static int32_t AudioEffectGetEffectCfgDescs(cJSON *cJsonObj, const char *item, struct ConfigDescriptor *cfgDesc)
218 {
219     HDF_LOGD("enter to %{public}s", __func__);
220     uint32_t effectNum;
221     uint32_t i;
222     cJSON *effectObj = NULL;
223     struct EffectConfigDescriptor *effectDescs = NULL;
224     int32_t ret;
225 
226     if (cJsonObj == NULL || item == NULL || cfgDesc == NULL) {
227         HDF_LOGE("%{public}s: invalid parameter!", __func__);
228         return HDF_ERR_INVALID_PARAM;
229     }
230     cJSON *effectsObj = cJSON_GetObjectItem(cJsonObj, item);
231     if (effectsObj == NULL) {
232         HDF_LOGE("%{public}s: get effects failed!", __func__);
233         return HDF_FAILURE;
234     }
235 
236     effectNum = (uint32_t)cJSON_GetArraySize(effectsObj);
237     if (effectNum == 0 || effectNum > HDF_EFFECT_NUM_MAX) {
238         HDF_LOGE("%{public}s: effectNum invalid, effectNum = %{public}d!", __func__, effectNum);
239         return HDF_FAILURE;
240     }
241     effectDescs = (struct EffectConfigDescriptor *)OsalMemCalloc(effectNum * sizeof(struct EffectConfigDescriptor));
242     if (effectDescs == NULL) {
243         HDF_LOGE("%{public}s: alloc effectDescs failed", __func__);
244         return HDF_ERR_MALLOC_FAIL;
245     }
246 
247     for (i = 0; i < effectNum; i++) {
248         effectObj = cJSON_GetArrayItem(effectsObj, i);
249         if (effectObj == NULL) {
250             HDF_LOGE("%{public}s get effect item fail!", __func__);
251             AudioEffectReleaseDescs(effectDescs, i);
252             OsalMemFree((void *)effectDescs);
253             return HDF_FAILURE;
254         }
255         ret = AudioEffectParseEffect(effectObj, &effectDescs[i]);
256         if (ret != HDF_SUCCESS) {
257             HDF_LOGE("%{public}s: parse effect[%{public}d] failed, ret = %{public}d", __func__, i, ret);
258             AudioEffectReleaseDescs(effectDescs, i);
259             OsalMemFree((void *)effectDescs);
260             return HDF_FAILURE;
261         }
262     }
263     cfgDesc->effectNum = effectNum;
264     cfgDesc->effectCfgDescs = effectDescs;
265     HDF_LOGD("%{public}s success", __func__);
266     return HDF_SUCCESS;
267 }
268 
AudioEffectParseLibrary(const cJSON * libObj,struct LibraryConfigDescriptor * libDesc)269 static int32_t AudioEffectParseLibrary(const cJSON *libObj, struct LibraryConfigDescriptor *libDesc)
270 {
271     if (libObj == NULL || libDesc == NULL) {
272         HDF_LOGE("%{public}s: invalid parameter!", __func__);
273         return HDF_ERR_INVALID_PARAM;
274     }
275 
276     if (AudioEffectParseItem(libObj, "name", &(libDesc->libName)) != HDF_SUCCESS) {
277         HDF_LOGE("%{public}s: parse item %{public}s fail!", __func__, "name");
278         return HDF_FAILURE;
279     }
280 
281     if (AudioEffectParseItem(libObj, "path", &(libDesc->libPath)) != HDF_SUCCESS) {
282         HDF_LOGE("%{public}s: parse item %{public}s fail!", __func__, "path");
283         OsalMemFree((void *)libDesc->libName);
284         return HDF_FAILURE;
285     }
286 
287     return HDF_SUCCESS;
288 }
289 
AudioEffectLibraryReleaseDescs(struct LibraryConfigDescriptor * libDescs,int32_t libNum)290 static void AudioEffectLibraryReleaseDescs(struct LibraryConfigDescriptor *libDescs, int32_t libNum)
291 {
292     int32_t i = 0;
293 
294     if (libDescs == NULL || libNum <= 0 || libNum > HDF_EFFECT_LIB_NUM_MAX) {
295         HDF_LOGE("%{public}s: libDescs is null or libNum is invalid!", __func__);
296         return;
297     }
298 
299     for (i = 0; i < libNum; i++) {
300         OsalMemFree((void *)libDescs[i].libName);
301         OsalMemFree((void *)libDescs[i].libPath);
302     }
303 }
304 
AudioEffectGetLibraryCfgDescs(cJSON * cJsonObj,const char * item,struct ConfigDescriptor * cfgDesc)305 static int32_t AudioEffectGetLibraryCfgDescs(cJSON *cJsonObj, const char *item, struct ConfigDescriptor *cfgDesc)
306 {
307     HDF_LOGD("enter to %{public}s", __func__);
308     int32_t ret;
309     uint32_t i;
310     uint32_t libNum;
311     cJSON *libObj = NULL;
312     struct LibraryConfigDescriptor *libDescs = NULL;
313     if (cJsonObj == NULL || item == NULL || cfgDesc == NULL) {
314         HDF_LOGE("%{public}s: invalid parameter!", __func__);
315         return HDF_ERR_INVALID_PARAM;
316     }
317     cJSON *libsObj = cJSON_GetObjectItem(cJsonObj, item);
318     if (libsObj == NULL) {
319         HDF_LOGE("%{public}s: get libs failed!", __func__);
320         return HDF_FAILURE;
321     }
322 
323     libNum = (uint32_t)cJSON_GetArraySize(libsObj);
324     if (libNum == 0 || libNum > HDF_EFFECT_NUM_MAX) {
325         HDF_LOGE("%{public}s: libNum invalid, libNum = %{public}d!", __func__, libNum);
326         return HDF_FAILURE;
327     }
328     libDescs = (struct LibraryConfigDescriptor *)OsalMemCalloc(libNum * sizeof(struct LibraryConfigDescriptor));
329     if (libDescs == NULL) {
330         HDF_LOGE("%{public}s: malloc libDescs failed", __func__);
331         return HDF_ERR_MALLOC_FAIL;
332     }
333 
334     for (i = 0; i < libNum; i++) {
335         libObj = cJSON_GetArrayItem(libsObj, i);
336         if (libObj == NULL) {
337             HDF_LOGE("%{public}s get library item fail!", __func__);
338             AudioEffectLibraryReleaseDescs(libDescs, i);
339             OsalMemFree((void *)libDescs);
340             return HDF_FAILURE;
341         }
342         ret = AudioEffectParseLibrary(libObj, &libDescs[i]);
343         if (ret != HDF_SUCCESS) {
344             HDF_LOGE("%{public}s: parse library[%{public}d] failed, ret = %{public}d", __func__, i, ret);
345             AudioEffectLibraryReleaseDescs(libDescs, i);
346             OsalMemFree((void *)libDescs);
347             return HDF_FAILURE;
348         }
349     }
350     cfgDesc->libNum = libNum;
351     cfgDesc->libCfgDescs = libDescs;
352     HDF_LOGD("%{public}s success", __func__);
353     return HDF_SUCCESS;
354 }
355 
AudioEffectReleaseCfgDesc(struct ConfigDescriptor * cfgDesc)356 void AudioEffectReleaseCfgDesc(struct ConfigDescriptor *cfgDesc)
357 {
358     if (cfgDesc == NULL) {
359         return;
360     }
361 
362     if (cfgDesc->libCfgDescs != NULL) {
363         AudioEffectLibraryReleaseDescs(cfgDesc->libCfgDescs, cfgDesc->libNum);
364         OsalMemFree((void *)cfgDesc->libCfgDescs);
365     }
366 
367     if (cfgDesc->effectCfgDescs != NULL) {
368         AudioEffectReleaseDescs(cfgDesc->effectCfgDescs, cfgDesc->effectNum);
369         OsalMemFree((void *)cfgDesc->effectCfgDescs);
370     }
371 
372     OsalMemFree((void *)cfgDesc);
373     cfgDesc = NULL;
374 }
375 
AudioEffectGetConfigDescriptor(const char * path,struct ConfigDescriptor ** cfgDesc)376 int32_t AudioEffectGetConfigDescriptor(const char *path, struct ConfigDescriptor **cfgDesc)
377 {
378     if (path == NULL || cfgDesc == NULL) {
379         HDF_LOGE("%{public}s: invalid parameter!", __func__);
380         return HDF_ERR_INVALID_PARAM;
381     }
382 
383     cJSON *cJsonObj = GetAudioEffectConfigToJsonObj(path);
384     if (cJsonObj == NULL) {
385         HDF_LOGE("%{public}s: get cJsonObj failed!", __func__);
386         return HDF_FAILURE;
387     }
388 
389     *cfgDesc = (struct ConfigDescriptor *)OsalMemCalloc(sizeof(struct ConfigDescriptor));
390     if (*cfgDesc == NULL) {
391         HDF_LOGE("%{public}s: alloc libDescs failed", __func__);
392         cJSON_Delete(cJsonObj);
393         cJsonObj = NULL;
394         return HDF_ERR_MALLOC_FAIL;
395     }
396 
397     if (AudioEffectGetLibraryCfgDescs(cJsonObj, "libraries", *cfgDesc) != HDF_SUCCESS) {
398         HDF_LOGE("%{public}s: get library config failed", __func__);
399         AudioEffectReleaseCfgDesc(*cfgDesc);
400         cJSON_Delete(cJsonObj);
401         cJsonObj = NULL;
402         return HDF_FAILURE;
403     }
404 
405     if (AudioEffectGetEffectCfgDescs(cJsonObj, "effects", *cfgDesc) != HDF_SUCCESS) {
406         HDF_LOGE("%{public}s: get effect config failed", __func__);
407         AudioEffectReleaseCfgDesc(*cfgDesc);
408         cJSON_Delete(cJsonObj);
409         cJsonObj = NULL;
410         return HDF_FAILURE;
411     }
412 
413     cJSON_Delete(cJsonObj);
414     cJsonObj = NULL;
415     HDF_LOGD("%{public}s success", __func__);
416     return HDF_SUCCESS;
417 }
418