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