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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioEffectConfigParser"
17 #endif
18
19 #include "audio_effect_config_parser.h"
20 #include <libxml/tree.h>
21 #ifdef USE_CONFIG_POLICY
22 #include "config_policy_utils.h"
23 #endif
24 #include "media_monitor_manager.h"
25
26 namespace OHOS {
27 namespace AudioStandard {
28 #ifdef USE_CONFIG_POLICY
29 static constexpr char AUDIO_EFFECT_CONFIG_FILE[] = "etc/audio/audio_effect_config.xml";
30 #else
31 static constexpr char AUDIO_EFFECT_CONFIG_FILE[] = "system/etc/audio/audio_effect_config.xml";
32 #endif
33 static const std::string EFFECT_CONFIG_NAME[5] = {"libraries", "effects", "effectChains", "preProcess", "postProcess"};
34 static constexpr int32_t FILE_CONTENT_ERROR = -2;
35 static constexpr int32_t FILE_PARSE_ERROR = -3;
36 static constexpr int32_t INDEX_LIBRARIES = 0;
37 static constexpr int32_t INDEX_EFFECS = 1;
38 static constexpr int32_t INDEX_EFFECTCHAINE = 2;
39 static constexpr int32_t INDEX_PREPROCESS = 3;
40 static constexpr int32_t INDEX_POSTPROCESS = 4;
41 static constexpr int32_t INDEX_EXCEPTION = 5;
42 static constexpr int32_t NODE_SIZE = 6;
43 static constexpr int32_t MODULE_SIZE = 5;
44 static constexpr uint32_t XML_PARSE_NOERROR = 1 << 5;
45 static constexpr uint32_t XML_PARSE_NOWARNING = 1 << 6;
46
AudioEffectConfigParser()47 AudioEffectConfigParser::AudioEffectConfigParser()
48 {
49 AUDIO_INFO_LOG("AudioEffectConfigParser created");
50 }
51
~AudioEffectConfigParser()52 AudioEffectConfigParser::~AudioEffectConfigParser()
53 {
54 }
55
ParseEffectConfigFile(xmlDoc * & doc)56 static int32_t ParseEffectConfigFile(xmlDoc* &doc)
57 {
58 #ifdef USE_CONFIG_POLICY
59 CfgFiles *cfgFiles = GetCfgFiles(AUDIO_EFFECT_CONFIG_FILE);
60 if (cfgFiles == nullptr) {
61 AUDIO_ERR_LOG("Not found audio_effect_config.xml!");
62 std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
63 Media::MediaMonitor::AUDIO, Media::MediaMonitor::LOAD_CONFIG_ERROR,
64 Media::MediaMonitor::FAULT_EVENT);
65 bean->Add("CATEGORY", Media::MediaMonitor::AUDIO_EFFECT_CONFIG);
66 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
67 return FILE_PARSE_ERROR;
68 }
69
70 for (int32_t i = MAX_CFG_POLICY_DIRS_CNT - 1; i >= 0; i--) {
71 if (cfgFiles->paths[i] && *(cfgFiles->paths[i]) != '\0') {
72 AUDIO_INFO_LOG("effect config file path:%{public}s", cfgFiles->paths[i]);
73 doc = xmlReadFile(cfgFiles->paths[i], nullptr, XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
74 break;
75 }
76 }
77 FreeCfgFiles(cfgFiles);
78 #else
79 AUDIO_INFO_LOG("use default audio effect config file path: %{public}s", AUDIO_EFFECT_CONFIG_FILE);
80 doc = xmlReadFile(AUDIO_EFFECT_CONFIG_FILE, nullptr, XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
81 #endif
82 if (doc == nullptr) {
83 std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
84 Media::MediaMonitor::AUDIO, Media::MediaMonitor::LOAD_CONFIG_ERROR,
85 Media::MediaMonitor::FAULT_EVENT);
86 bean->Add("CATEGORY", Media::MediaMonitor::AUDIO_EFFECT_CONFIG);
87 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
88 }
89 CHECK_AND_RETURN_RET_LOG(doc != nullptr, FILE_PARSE_ERROR, "load audio effect config fail");
90 return 0;
91 }
92
LoadConfigCheck(xmlDoc * doc,xmlNode * currNode)93 static int32_t LoadConfigCheck(xmlDoc *doc, xmlNode *currNode)
94 {
95 CHECK_AND_RETURN_RET_LOG(currNode != nullptr, FILE_PARSE_ERROR, "error: could not parse file");
96 if (xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("audio_effects_conf"))) {
97 AUDIO_ERR_LOG("Missing tag - audio_effects_conf");
98 xmlFreeDoc(doc);
99 return FILE_CONTENT_ERROR;
100 }
101
102 if (currNode->xmlChildrenNode) {
103 return 0;
104 } else {
105 AUDIO_ERR_LOG("Missing node - audio_effects_conf");
106 xmlFreeDoc(doc);
107 return FILE_CONTENT_ERROR;
108 }
109 }
110
LoadConfigVersion(OriginalEffectConfig & result,xmlNode * currNode)111 static void LoadConfigVersion(OriginalEffectConfig &result, xmlNode *currNode)
112 {
113 bool ret = xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("version"));
114 CHECK_AND_RETURN_LOG(ret, "missing information: audio_effects_conf node has no version attribute");
115
116 result.version = reinterpret_cast<char *>(xmlGetProp(currNode, reinterpret_cast<const xmlChar *>("version")));
117 }
118
LoadLibrary(OriginalEffectConfig & result,xmlNode * secondNode)119 static void LoadLibrary(OriginalEffectConfig &result, xmlNode *secondNode)
120 {
121 xmlNode *currNode = secondNode;
122 int32_t countLibrary = 0;
123 while (currNode != nullptr) {
124 CHECK_AND_RETURN_LOG(countLibrary < AUDIO_EFFECT_COUNT_UPPER_LIMIT,
125 "the number of library nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
126 if (currNode->type != XML_ELEMENT_NODE) {
127 currNode = currNode->next;
128 continue;
129 }
130 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("library"))) {
131 if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("name"))) {
132 AUDIO_ERR_LOG("missing information: library has no name attribute");
133 } else if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("path"))) {
134 AUDIO_ERR_LOG("missing information: library has no path attribute");
135 } else {
136 std::string pLibName = reinterpret_cast<char*>
137 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("name")));
138 std::string pLibPath = reinterpret_cast<char*>
139 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("path")));
140 Library tmp = {pLibName, pLibPath};
141 result.libraries.push_back(tmp);
142 }
143 } else {
144 AUDIO_WARNING_LOG("wrong name: %{public}s, should be library", currNode->name);
145 }
146 countLibrary++;
147 currNode = currNode->next;
148 }
149 if (countLibrary == 0) {
150 AUDIO_WARNING_LOG("missing information: libraries have no child library");
151 }
152 }
153
LoadEffectConfigLibraries(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countFirstNode)[NODE_SIZE])154 static void LoadEffectConfigLibraries(OriginalEffectConfig &result, const xmlNode *currNode,
155 int32_t (&countFirstNode)[NODE_SIZE])
156 {
157 if (countFirstNode[INDEX_LIBRARIES] >= AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
158 if (countFirstNode[INDEX_LIBRARIES] == AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
159 countFirstNode[INDEX_LIBRARIES]++;
160 AUDIO_WARNING_LOG("the number of libraries nodes exceeds limit: %{public}d",
161 AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT);
162 }
163 } else if (currNode->xmlChildrenNode) {
164 LoadLibrary(result, currNode->xmlChildrenNode);
165 countFirstNode[INDEX_LIBRARIES]++;
166 } else {
167 AUDIO_WARNING_LOG("missing information: libraries have no child library");
168 countFirstNode[INDEX_LIBRARIES]++;
169 }
170 }
171
LoadEffectProperty(OriginalEffectConfig & result,const xmlNode * thirdNode,const int32_t effectIdx)172 static void LoadEffectProperty(OriginalEffectConfig &result, const xmlNode *thirdNode, const int32_t effectIdx)
173 {
174 CHECK_AND_RETURN_LOG(thirdNode->xmlChildrenNode, "effect '%{public}s' does not support effectProperty settings.",
175 result.effects[effectIdx].name.c_str());
176 int32_t countProperty = 0;
177 xmlNode *currNode = thirdNode->xmlChildrenNode;
178 while (currNode != nullptr) {
179 CHECK_AND_RETURN_LOG(countProperty < AUDIO_EFFECT_COUNT_UPPER_LIMIT,
180 "the number of effectProperty nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
181 if (currNode->type != XML_ELEMENT_NODE) {
182 currNode = currNode->next;
183 continue;
184 }
185 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("effectProperty"))) {
186 if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("mode"))) {
187 AUDIO_WARNING_LOG("missing information: EFFECTPROPERTY has no MODE attribute");
188 } else {
189 std::string pMode = reinterpret_cast<char*>
190 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("mode")));
191 result.effects[effectIdx].effectProperty.push_back(pMode);
192 }
193 } else {
194 AUDIO_WARNING_LOG("wrong name: %{public}s, should be effectProperty", currNode->name);
195 }
196 countProperty++;
197 currNode = currNode->next;
198 }
199 if (countProperty == 0) {
200 AUDIO_WARNING_LOG("effect '%{public}s' does not support effectProperty settings.",
201 result.effects[effectIdx].name.c_str());
202 }
203 }
204
LoadEffect(OriginalEffectConfig & result,xmlNode * secondNode)205 static void LoadEffect(OriginalEffectConfig &result, xmlNode *secondNode)
206 {
207 xmlNode *currNode = secondNode;
208 int32_t countEffect = 0;
209 std::vector<std::string> effectProperty = {};
210 int32_t effectIdx = 0;
211 while (currNode != nullptr) {
212 CHECK_AND_RETURN_LOG(countEffect < AUDIO_EFFECT_COUNT_UPPER_LIMIT,
213 "the number of effect nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
214 if (currNode->type != XML_ELEMENT_NODE) {
215 currNode = currNode->next;
216 continue;
217 }
218 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("effect"))) {
219 if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("name"))) {
220 AUDIO_ERR_LOG("missing information: effect has no name attribute");
221 } else if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("library"))) {
222 AUDIO_ERR_LOG("missing information: effect has no library attribute");
223 } else {
224 std::string pEffectName = reinterpret_cast<char*>
225 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("name")));
226 std::string pEffectLib = reinterpret_cast<char*>
227 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("library")));
228 Effect tmp = {pEffectName, pEffectLib, effectProperty};
229 result.effects.push_back(tmp);
230 LoadEffectProperty(result, currNode, effectIdx);
231 effectIdx++;
232 }
233 } else {
234 AUDIO_WARNING_LOG("wrong name: %{public}s, should be effect", currNode->name);
235 }
236 countEffect++;
237 currNode = currNode->next;
238 }
239 if (countEffect == 0) {
240 AUDIO_WARNING_LOG("missing information: effects have no child effect");
241 }
242 }
243
LoadEffectConfigEffects(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countFirstNode)[NODE_SIZE])244 static void LoadEffectConfigEffects(OriginalEffectConfig &result, const xmlNode *currNode,
245 int32_t (&countFirstNode)[NODE_SIZE])
246 {
247 if (countFirstNode[INDEX_EFFECS] >= AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
248 if (countFirstNode[INDEX_EFFECS] == AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
249 countFirstNode[INDEX_EFFECS]++;
250 AUDIO_WARNING_LOG("the number of effects nodes exceeds limit: %{public}d",
251 AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT);
252 }
253 } else if (currNode->xmlChildrenNode) {
254 LoadEffect(result, currNode->xmlChildrenNode);
255 countFirstNode[INDEX_EFFECS]++;
256 } else {
257 AUDIO_WARNING_LOG("missing information: effects have no child effect");
258 countFirstNode[INDEX_EFFECS]++;
259 }
260 }
261
LoadApply(OriginalEffectConfig & result,const xmlNode * thirdNode,const int32_t segInx)262 static void LoadApply(OriginalEffectConfig &result, const xmlNode *thirdNode, const int32_t segInx)
263 {
264 CHECK_AND_RETURN_LOG(thirdNode->xmlChildrenNode, "missing information: effectChain has no child apply");
265 int32_t countApply = 0;
266 xmlNode *currNode = thirdNode->xmlChildrenNode;
267 while (currNode != nullptr) {
268 CHECK_AND_RETURN_LOG(countApply < AUDIO_EFFECT_COUNT_UPPER_LIMIT,
269 "the number of apply nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
270 if (currNode->type != XML_ELEMENT_NODE) {
271 currNode = currNode->next;
272 continue;
273 }
274 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("apply"))) {
275 if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("effect"))) {
276 AUDIO_WARNING_LOG("missing information: apply has no effect attribute");
277 } else {
278 std::string ppValue = reinterpret_cast<char*>
279 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("effect")));
280 result.effectChains[segInx].apply.push_back(ppValue);
281 }
282 } else {
283 AUDIO_WARNING_LOG("wrong name: %{public}s, should be apply", currNode->name);
284 }
285 countApply++;
286 currNode = currNode->next;
287 }
288 if (countApply == 0) {
289 AUDIO_WARNING_LOG("missing information: effectChain has no child apply");
290 }
291 }
292
LoadEffectChain(OriginalEffectConfig & result,xmlNode * secondNode)293 static void LoadEffectChain(OriginalEffectConfig &result, xmlNode *secondNode)
294 {
295 xmlNode *currNode = secondNode;
296 int32_t countEffectChain = 0;
297 int32_t segInx = 0;
298 std::vector<std::string> apply;
299 while (currNode != nullptr) {
300 CHECK_AND_RETURN_LOG(countEffectChain < AUDIO_EFFECT_COUNT_UPPER_LIMIT,
301 "the number of effectChain nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
302 if (currNode->type != XML_ELEMENT_NODE) {
303 currNode = currNode->next;
304 continue;
305 }
306 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("effectChain"))) {
307 std::string label = "";
308 if (xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("label"))) {
309 label = reinterpret_cast<char*>(xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("label")));
310 }
311 if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("name"))) {
312 AUDIO_WARNING_LOG("missing information: effectChain has no name attribute");
313 } else {
314 std::string peffectChainName = reinterpret_cast<char*>
315 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("name")));
316 EffectChain tmp = {peffectChainName, apply, label};
317 result.effectChains.push_back(tmp);
318 LoadApply(result, currNode, segInx);
319 segInx++;
320 }
321 } else {
322 AUDIO_WARNING_LOG("wrong name: %{public}s, should be effectChain", currNode->name);
323 }
324 countEffectChain++;
325 currNode = currNode->next;
326 }
327 if (countEffectChain == 0) {
328 AUDIO_WARNING_LOG("missing information: effectChains have no child effectChain");
329 }
330 }
331
LoadEffectConfigEffectChains(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countFirstNode)[NODE_SIZE])332 static void LoadEffectConfigEffectChains(OriginalEffectConfig &result, const xmlNode *currNode,
333 int32_t (&countFirstNode)[NODE_SIZE])
334 {
335 if (countFirstNode[INDEX_EFFECTCHAINE] >= AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
336 if (countFirstNode[INDEX_EFFECTCHAINE] == AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
337 countFirstNode[INDEX_EFFECTCHAINE]++;
338 AUDIO_WARNING_LOG("the number of effectChains nodes exceeds limit: %{public}d",
339 AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT);
340 }
341 } else if (currNode->xmlChildrenNode) {
342 LoadEffectChain(result, currNode->xmlChildrenNode);
343 countFirstNode[INDEX_EFFECTCHAINE]++;
344 } else {
345 AUDIO_WARNING_LOG("missing information: effectChains have no child effectChain");
346 countFirstNode[INDEX_EFFECTCHAINE]++;
347 }
348 }
349
LoadPreDevice(std::vector<Device> & devices,const xmlNode * fifthNode)350 static void LoadPreDevice(std::vector<Device> &devices, const xmlNode *fifthNode)
351 {
352 CHECK_AND_RETURN_LOG(fifthNode->xmlChildrenNode, "missing information: streamEffectMode has no child devicePort");
353 int32_t countDevice = 0;
354 xmlNode *currNode = fifthNode->xmlChildrenNode;
355 while (currNode != nullptr) {
356 CHECK_AND_RETURN_LOG(countDevice < AUDIO_EFFECT_COUNT_UPPER_LIMIT,
357 "the number of devicePort nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
358 if (currNode->type != XML_ELEMENT_NODE) {
359 currNode = currNode->next;
360 continue;
361 }
362 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("devicePort"))) {
363 if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("type"))) {
364 AUDIO_ERR_LOG("missing information: devicePort has no type attribute");
365 } else if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("effectChain"))) {
366 AUDIO_ERR_LOG("missing information: devicePort has no effectChain attribute");
367 } else {
368 std::string pDevType = reinterpret_cast<char*>
369 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("type")));
370 std::string pChain = reinterpret_cast<char*>
371 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("effectChain")));
372 Device tmpdev = {pDevType, pChain};
373 devices.push_back(tmpdev);
374 }
375 } else {
376 AUDIO_WARNING_LOG("wrong name: %{public}s, should be devicePort", currNode->name);
377 }
378 countDevice++;
379 currNode = currNode->next;
380 }
381 if (countDevice == 0) {
382 AUDIO_WARNING_LOG("missing information: streamEffectMode has no child devicePort");
383 }
384 }
385
LoadPreMode(PreStreamScene & scene,const xmlNode * fourthNode)386 static void LoadPreMode(PreStreamScene &scene, const xmlNode *fourthNode)
387 {
388 CHECK_AND_RETURN_LOG(fourthNode->xmlChildrenNode,
389 "missing information: stream has no child streamEffectMode");
390 int32_t countMode = 0;
391 int32_t modeNum = 0;
392 xmlNode *currNode = fourthNode->xmlChildrenNode;
393 while (currNode != nullptr) {
394 CHECK_AND_RETURN_LOG(countMode < AUDIO_EFFECT_COUNT_UPPER_LIMIT,
395 "the number of streamEffectMode nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
396 if (currNode->type != XML_ELEMENT_NODE) {
397 currNode = currNode->next;
398 continue;
399 }
400 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("streamEffectMode"))) {
401 if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("mode"))) {
402 AUDIO_WARNING_LOG("missing information: streamEffectMode has no mode attribute");
403 } else {
404 std::string pStreamAEMode = reinterpret_cast<char*>
405 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("mode")));
406 scene.mode.push_back(pStreamAEMode);
407 scene.device.push_back({});
408 LoadPreDevice(scene.device[modeNum], currNode);
409 modeNum++;
410 }
411 } else {
412 AUDIO_WARNING_LOG("wrong name: %{public}s, should be streamEffectMode", currNode->name);
413 }
414 countMode++;
415 currNode = currNode->next;
416 }
417 if (countMode == 0) {
418 AUDIO_WARNING_LOG("missing information: stream has no child streamEffectMode");
419 }
420 }
421
LoadPreStreamScenes(std::vector<PreStreamScene> & scenes,xmlNode * thirdNode)422 static void LoadPreStreamScenes(std::vector<PreStreamScene> &scenes, xmlNode *thirdNode)
423 {
424 std::string stream;
425 std::vector<std::string> mode;
426 std::vector<std::vector<Device>> device;
427 PreStreamScene tmp = {stream, mode, device};
428 xmlNode *currNode = thirdNode;
429 int32_t countPreprocess = 0;
430 int32_t streamNum = 0;
431 while (currNode != nullptr) {
432 CHECK_AND_RETURN_LOG(countPreprocess < AUDIO_EFFECT_COUNT_UPPER_LIMIT,
433 "the number of stream nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
434 if (currNode->type != XML_ELEMENT_NODE) {
435 currNode = currNode->next;
436 continue;
437 }
438 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("stream"))) {
439 if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("scene"))) {
440 AUDIO_WARNING_LOG("missing information: stream has no scene attribute");
441 } else {
442 std::string pStreamType = reinterpret_cast<char*>
443 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("scene")));
444 tmp.stream = pStreamType;
445 scenes.push_back(tmp);
446 LoadPreMode(scenes[streamNum], currNode);
447 streamNum++;
448 }
449 } else {
450 AUDIO_WARNING_LOG("wrong name: %{public}s, should be stream", currNode->name);
451 }
452 countPreprocess++;
453 currNode = currNode->next;
454 }
455 if (countPreprocess == 0) {
456 AUDIO_WARNING_LOG("missing information: preProcess has no child stream");
457 }
458 }
459
LoadPreStreamScenesCheck(std::vector<PreStreamScene> & scenes,const xmlNode * currNode,int32_t & nodeCounter)460 static void LoadPreStreamScenesCheck(std::vector<PreStreamScene> &scenes, const xmlNode *currNode,
461 int32_t &nodeCounter)
462 {
463 if (nodeCounter >= AUDIO_EFFECT_COUNT_PRE_SECOND_NODE_UPPER_LIMIT) {
464 if (nodeCounter == AUDIO_EFFECT_COUNT_PRE_SECOND_NODE_UPPER_LIMIT) {
465 nodeCounter++;
466 AUDIO_WARNING_LOG("the number of preprocessStreams nodes exceeds limit: %{public}d",
467 AUDIO_EFFECT_COUNT_PRE_SECOND_NODE_UPPER_LIMIT);
468 }
469 } else if (currNode->xmlChildrenNode) {
470 LoadPreStreamScenes(scenes, currNode->xmlChildrenNode);
471 nodeCounter++;
472 } else {
473 AUDIO_WARNING_LOG("missing information: preprocessStreams has no child stream");
474 nodeCounter++;
475 }
476 }
477
LoadPreprocessExceptionCheck(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countPreSecondNode)[NODE_SIZE_PRE])478 static void LoadPreprocessExceptionCheck(OriginalEffectConfig &result, const xmlNode *currNode,
479 int32_t (&countPreSecondNode)[NODE_SIZE_PRE])
480 {
481 if (countPreSecondNode[INDEX_PRE_EXCEPTION] >= AUDIO_EFFECT_COUNT_PRE_SECOND_NODE_UPPER_LIMIT) {
482 if (countPreSecondNode[INDEX_PRE_EXCEPTION] == AUDIO_EFFECT_COUNT_PRE_SECOND_NODE_UPPER_LIMIT) {
483 countPreSecondNode[INDEX_PRE_EXCEPTION]++;
484 AUDIO_ERR_LOG("the number of postprocess nodes with wrong name exceeds limit: %{public}d",
485 AUDIO_EFFECT_COUNT_PRE_SECOND_NODE_UPPER_LIMIT);
486 }
487 } else {
488 AUDIO_WARNING_LOG("wrong name: %{public}s", currNode->name);
489 countPreSecondNode[INDEX_PRE_EXCEPTION]++;
490 }
491 }
492
LoadPreProcessCfg(OriginalEffectConfig & result,xmlNode * secondNode)493 static void LoadPreProcessCfg(OriginalEffectConfig &result, xmlNode *secondNode)
494 {
495 int32_t countPreSecondNode[NODE_SIZE_PRE] = {0};
496 xmlNode *currNode = secondNode;
497 while (currNode != nullptr) {
498 if (currNode->type != XML_ELEMENT_NODE) {
499 currNode = currNode->next;
500 continue;
501 }
502
503 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("defaultScene"))) {
504 LoadPreStreamScenesCheck(result.preProcess.defaultScenes, currNode,
505 countPreSecondNode[INDEX_PRE_DEFAULT_SCENE]);
506 } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("priorScene"))) {
507 LoadPreStreamScenesCheck(result.preProcess.priorScenes, currNode,
508 countPreSecondNode[INDEX_PRE_PRIOR_SCENE]);
509 } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("normalScene"))) {
510 int32_t maxExtraNum = 0;
511 if (xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("maxExtSceneNumber"))) {
512 maxExtraNum = atoi(reinterpret_cast<char*>(xmlGetProp(currNode,
513 reinterpret_cast<const xmlChar*>("maxExtSceneNumber"))));
514 }
515 result.preProcess.maxExtSceneNum = static_cast<uint32_t>(maxExtraNum);
516 LoadPreStreamScenesCheck(result.preProcess.normalScenes, currNode,
517 countPreSecondNode[INDEX_PRE_NORMAL_SCENE]);
518 } else {
519 LoadPreprocessExceptionCheck(result, currNode, countPreSecondNode);
520 }
521 currNode = currNode->next;
522 }
523 }
524
LoadEffectConfigPreProcessCfg(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countFirstNode)[NODE_SIZE])525 static void LoadEffectConfigPreProcessCfg(OriginalEffectConfig &result,
526 const xmlNode *currNode, int32_t (&countFirstNode)[NODE_SIZE])
527 {
528 if (countFirstNode[INDEX_PREPROCESS] >= AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
529 if (countFirstNode[INDEX_PREPROCESS] == AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
530 countFirstNode[INDEX_PREPROCESS]++;
531 AUDIO_WARNING_LOG("the number of preProcess nodes exceeds limit: %{public}d",
532 AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT);
533 }
534 } else if (currNode->xmlChildrenNode) {
535 LoadPreProcessCfg(result, currNode->xmlChildrenNode);
536 countFirstNode[INDEX_PREPROCESS]++;
537 } else {
538 AUDIO_WARNING_LOG("missing information: preProcess has no child stream");
539 countFirstNode[INDEX_PREPROCESS]++;
540 }
541 }
542
LoadStreamUsageMapping(OriginalEffectConfig & result,xmlNode * thirdNode)543 static void LoadStreamUsageMapping(OriginalEffectConfig &result, xmlNode *thirdNode)
544 {
545 SceneMappingItem tmp;
546 xmlNode *currNode = thirdNode;
547 int32_t countUsage = 0;
548 while (currNode != nullptr) {
549 CHECK_AND_RETURN_LOG(countUsage < AUDIO_EFFECT_COUNT_STREAM_USAGE_UPPER_LIMIT,
550 "streamUsage map item exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_STREAM_USAGE_UPPER_LIMIT);
551 if (currNode->type != XML_ELEMENT_NODE) {
552 currNode = currNode->next;
553 continue;
554 }
555 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("streamUsage"))) {
556 if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("name")) ||
557 !xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("scene"))) {
558 AUDIO_WARNING_LOG("missing information: streamUsage misses attribute");
559 } else {
560 tmp.name = reinterpret_cast<char*>(
561 xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("name")));
562 tmp.sceneType = reinterpret_cast<char*>(
563 xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("scene")));
564 result.postProcess.sceneMap.push_back(tmp);
565 }
566 } else {
567 AUDIO_WARNING_LOG("wrong name: %{public}s, should be streamUsage", currNode->name);
568 }
569 countUsage++;
570 currNode = currNode->next;
571 }
572 if (countUsage == 0) {
573 AUDIO_WARNING_LOG("missing information: sceneMap has no child streamUsage");
574 }
575 }
576
LoadPostDevice(std::vector<Device> & devices,const xmlNode * fifthNode)577 static void LoadPostDevice(std::vector<Device> &devices, const xmlNode *fifthNode)
578 {
579 CHECK_AND_RETURN_LOG(fifthNode->xmlChildrenNode, "missing information: streamEffectMode has no child devicePort");
580 int32_t countDevice = 0;
581 xmlNode *currNode = fifthNode->xmlChildrenNode;
582 while (currNode != nullptr) {
583 CHECK_AND_RETURN_LOG(countDevice < AUDIO_EFFECT_COUNT_UPPER_LIMIT,
584 "the number of devicePort nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
585 if (currNode->type != XML_ELEMENT_NODE) {
586 currNode = currNode->next;
587 continue;
588 }
589 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("devicePort"))) {
590 if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("type"))) {
591 AUDIO_WARNING_LOG("missing information: devicePort has no type attribute");
592 } else if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("effectChain"))) {
593 AUDIO_WARNING_LOG("missing information: devicePort has no effectChain attribute");
594 } else {
595 std::string pDevType = reinterpret_cast<char*>
596 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("type")));
597 std::string pChain = reinterpret_cast<char*>
598 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("effectChain")));
599 Device tmpdev = {pDevType, pChain};
600 devices.push_back(tmpdev);
601 }
602 } else {
603 AUDIO_WARNING_LOG("wrong name: %{public}s, should be devicePort", currNode->name);
604 }
605 countDevice++;
606 currNode = currNode->next;
607 }
608 if (countDevice == 0) {
609 AUDIO_WARNING_LOG("missing information: streamEffectMode has no child devicePort");
610 }
611 }
612
LoadPostMode(PostStreamScene & scene,const xmlNode * fourthNode)613 static void LoadPostMode(PostStreamScene &scene, const xmlNode *fourthNode)
614 {
615 CHECK_AND_RETURN_LOG(fourthNode->xmlChildrenNode,
616 "missing information: stream has no child streamEffectMode");
617 int32_t countMode = 0;
618 int32_t modeNum = 0;
619 xmlNode *currNode = fourthNode->xmlChildrenNode;
620 while (currNode != nullptr) {
621 CHECK_AND_RETURN_LOG(countMode < AUDIO_EFFECT_COUNT_UPPER_LIMIT,
622 "the number of streamEffectMode nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
623 if (currNode->type != XML_ELEMENT_NODE) {
624 currNode = currNode->next;
625 continue;
626 }
627 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("streamEffectMode"))) {
628 if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("mode"))) {
629 AUDIO_ERR_LOG("missing information: streamEffectMode has no mode attribute");
630 } else {
631 std::string pStreamAEMode = reinterpret_cast<char*>
632 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("mode")));
633 scene.mode.push_back(pStreamAEMode);
634 scene.device.push_back({});
635 LoadPostDevice(scene.device[modeNum], currNode);
636 modeNum++;
637 }
638 } else {
639 AUDIO_WARNING_LOG("wrong name: %{public}s, should be streamEffectMode", currNode->name);
640 }
641 countMode++;
642 currNode = currNode->next;
643 }
644 if (countMode == 0) {
645 AUDIO_WARNING_LOG("missing information: stream has no child streamEffectMode");
646 }
647 }
648
LoadPostStreamScenes(std::vector<PostStreamScene> & scenes,xmlNode * thirdNode)649 static void LoadPostStreamScenes(std::vector<PostStreamScene> &scenes, xmlNode *thirdNode)
650 {
651 std::string stream;
652 std::vector<std::string> mode;
653 std::vector<std::vector<Device>> device;
654 PostStreamScene tmp = {stream, mode, device};
655 xmlNode *currNode = thirdNode;
656 int32_t countPostProcess = 0;
657 int32_t streamNum = 0;
658 while (currNode != nullptr) {
659 CHECK_AND_RETURN_LOG(countPostProcess < AUDIO_EFFECT_COUNT_UPPER_LIMIT,
660 "the number of stream nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
661 if (currNode->type != XML_ELEMENT_NODE) {
662 currNode = currNode->next;
663 continue;
664 }
665 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("stream"))) {
666 if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("scene"))) {
667 AUDIO_WARNING_LOG("missing information: stream has no scene attribute");
668 } else {
669 std::string pStreamType = reinterpret_cast<char*>
670 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("scene")));
671 tmp.stream = pStreamType;
672 scenes.push_back(tmp);
673 LoadPostMode(scenes[streamNum], currNode);
674 streamNum++;
675 }
676 } else {
677 AUDIO_WARNING_LOG("wrong name: %{public}s, should be stream", currNode->name);
678 }
679 countPostProcess++;
680 currNode = currNode->next;
681 }
682 if (countPostProcess == 0) {
683 AUDIO_WARNING_LOG("missing information: postProcess has no child stream");
684 }
685 }
686
LoadPostStreamScenesCheck(std::vector<PostStreamScene> & scenes,const xmlNode * currNode,int32_t & nodeCounter)687 static void LoadPostStreamScenesCheck(std::vector<PostStreamScene> &scenes, const xmlNode *currNode,
688 int32_t &nodeCounter)
689 {
690 if (nodeCounter >= AUDIO_EFFECT_COUNT_POST_SECOND_NODE_UPPER_LIMIT) {
691 if (nodeCounter == AUDIO_EFFECT_COUNT_POST_SECOND_NODE_UPPER_LIMIT) {
692 nodeCounter++;
693 AUDIO_WARNING_LOG("the number of postprocessStreams nodes exceeds limit: %{public}d",
694 AUDIO_EFFECT_COUNT_POST_SECOND_NODE_UPPER_LIMIT);
695 }
696 } else if (currNode->xmlChildrenNode) {
697 LoadPostStreamScenes(scenes, currNode->xmlChildrenNode);
698 nodeCounter++;
699 } else {
700 AUDIO_WARNING_LOG("missing information: postprocessStreams has no child stream");
701 nodeCounter++;
702 }
703 }
704
LoadStreamUsageMappingCheck(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countPostSecondNode)[NODE_SIZE_POST])705 static void LoadStreamUsageMappingCheck(OriginalEffectConfig &result, const xmlNode *currNode,
706 int32_t (&countPostSecondNode)[NODE_SIZE_POST])
707 {
708 if (countPostSecondNode[INDEX_POST_MAPPING] >= AUDIO_EFFECT_COUNT_POST_SECOND_NODE_UPPER_LIMIT) {
709 if (countPostSecondNode[INDEX_POST_MAPPING] == AUDIO_EFFECT_COUNT_POST_SECOND_NODE_UPPER_LIMIT) {
710 countPostSecondNode[INDEX_POST_MAPPING]++;
711 AUDIO_WARNING_LOG("the number of sceneMap nodes exceeds limit: %{public}d",
712 AUDIO_EFFECT_COUNT_POST_SECOND_NODE_UPPER_LIMIT);
713 }
714 } else if (currNode->xmlChildrenNode) {
715 LoadStreamUsageMapping(result, currNode->xmlChildrenNode);
716 countPostSecondNode[INDEX_POST_MAPPING]++;
717 } else {
718 AUDIO_WARNING_LOG("missing information: sceneMap has no child stream");
719 countPostSecondNode[INDEX_POST_MAPPING]++;
720 }
721 }
722
LoadPostprocessExceptionCheck(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countPostSecondNode)[NODE_SIZE_POST])723 static void LoadPostprocessExceptionCheck(OriginalEffectConfig &result, const xmlNode *currNode,
724 int32_t (&countPostSecondNode)[NODE_SIZE_POST])
725 {
726 if (countPostSecondNode[INDEX_POST_EXCEPTION] >= AUDIO_EFFECT_COUNT_POST_SECOND_NODE_UPPER_LIMIT) {
727 if (countPostSecondNode[INDEX_POST_EXCEPTION] == AUDIO_EFFECT_COUNT_POST_SECOND_NODE_UPPER_LIMIT) {
728 countPostSecondNode[INDEX_POST_EXCEPTION]++;
729 AUDIO_ERR_LOG("the number of postprocess nodes with wrong name exceeds limit: %{public}d",
730 AUDIO_EFFECT_COUNT_POST_SECOND_NODE_UPPER_LIMIT);
731 }
732 } else {
733 AUDIO_WARNING_LOG("wrong name: %{public}s", currNode->name);
734 countPostSecondNode[INDEX_POST_EXCEPTION]++;
735 }
736 }
737
LoadPostProcessCfg(OriginalEffectConfig & result,xmlNode * secondNode)738 static void LoadPostProcessCfg(OriginalEffectConfig &result, xmlNode *secondNode)
739 {
740 int32_t countPostSecondNode[NODE_SIZE_POST] = {0};
741 xmlNode *currNode = secondNode;
742 while (currNode != nullptr) {
743 if (currNode->type != XML_ELEMENT_NODE) {
744 currNode = currNode->next;
745 continue;
746 }
747
748 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("defaultScene"))) {
749 LoadPostStreamScenesCheck(result.postProcess.defaultScenes, currNode,
750 countPostSecondNode[INDEX_POST_DEFAULT_SCENE]);
751 } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("priorScene"))) {
752 LoadPostStreamScenesCheck(result.postProcess.priorScenes, currNode,
753 countPostSecondNode[INDEX_POST_PRIOR_SCENE]);
754 } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("normalScene"))) {
755 int32_t maxExtraNum = 0;
756 if (xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("maxExtSceneNumber"))) {
757 maxExtraNum = atoi(reinterpret_cast<char*>(xmlGetProp(currNode,
758 reinterpret_cast<const xmlChar*>("maxExtSceneNumber"))));
759 }
760 result.postProcess.maxExtSceneNum = static_cast<uint32_t>(maxExtraNum);
761 LoadPostStreamScenesCheck(result.postProcess.normalScenes, currNode,
762 countPostSecondNode[INDEX_POST_NORMAL_SCENE]);
763 } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("effectSceneStreams"))) {
764 // TO BE COMPATIBLE WITH OLDER VERSION XML
765 LoadPostStreamScenesCheck(result.postProcess.normalScenes, currNode,
766 countPostSecondNode[INDEX_POST_NORMAL_SCENE]);
767 } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("sceneMap"))) {
768 LoadStreamUsageMappingCheck(result, currNode, countPostSecondNode);
769 } else {
770 LoadPostprocessExceptionCheck(result, currNode, countPostSecondNode);
771 }
772 currNode = currNode->next;
773 }
774 }
775
LoadEffectConfigPostProcessCfg(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countFirstNode)[NODE_SIZE])776 static void LoadEffectConfigPostProcessCfg(OriginalEffectConfig &result, const xmlNode *currNode,
777 int32_t (&countFirstNode)[NODE_SIZE])
778 {
779 if (countFirstNode[INDEX_POSTPROCESS] >= AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
780 if (countFirstNode[INDEX_POSTPROCESS] == AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
781 countFirstNode[INDEX_POSTPROCESS]++;
782 AUDIO_WARNING_LOG("the number of postProcess nodes exceeds limit: %{public}d",
783 AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT);
784 }
785 } else if (currNode->xmlChildrenNode) {
786 LoadPostProcessCfg(result, currNode->xmlChildrenNode);
787 countFirstNode[INDEX_POSTPROCESS]++;
788 } else {
789 AUDIO_WARNING_LOG("missing information: postProcess has no child stream");
790 countFirstNode[INDEX_POSTPROCESS]++;
791 }
792 }
793
LoadEffectConfigException(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countFirstNode)[NODE_SIZE])794 static void LoadEffectConfigException(OriginalEffectConfig &result, const xmlNode *currNode,
795 int32_t (&countFirstNode)[NODE_SIZE])
796 {
797 if (countFirstNode[INDEX_EXCEPTION] >= AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
798 if (countFirstNode[INDEX_EXCEPTION] == AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
799 countFirstNode[INDEX_EXCEPTION]++;
800 AUDIO_ERR_LOG("the number of nodes with wrong name exceeds limit: %{public}d",
801 AUDIO_EFFECT_COUNT_UPPER_LIMIT);
802 }
803 } else {
804 AUDIO_WARNING_LOG("wrong name: %{public}s", currNode->name);
805 countFirstNode[INDEX_EXCEPTION]++;
806 }
807 }
808
LoadEffectConfig(OriginalEffectConfig & result)809 int32_t AudioEffectConfigParser::LoadEffectConfig(OriginalEffectConfig &result)
810 {
811 int32_t countFirstNode[NODE_SIZE] = {0};
812 xmlDoc *doc = nullptr;
813 xmlNode *rootElement = nullptr;
814
815 int32_t ret = ParseEffectConfigFile(doc);
816 CHECK_AND_RETURN_RET_LOG(ret == 0, ret, "error: could not parse audio effect config file");
817
818 rootElement = xmlDocGetRootElement(doc);
819 xmlNode *currNode = rootElement;
820
821 if (LoadConfigCheck(doc, currNode) == 0) {
822 LoadConfigVersion(result, currNode);
823 currNode = currNode->xmlChildrenNode;
824 } else {
825 return FILE_CONTENT_ERROR;
826 }
827
828 while (currNode != nullptr) {
829 if (currNode->type != XML_ELEMENT_NODE) {
830 currNode = currNode->next;
831 continue;
832 }
833
834 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("libraries"))) {
835 LoadEffectConfigLibraries(result, currNode, countFirstNode);
836 } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("effects"))) {
837 LoadEffectConfigEffects(result, currNode, countFirstNode);
838 } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("effectChains"))) {
839 LoadEffectConfigEffectChains(result, currNode, countFirstNode);
840 } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("preProcess"))) {
841 LoadEffectConfigPreProcessCfg(result, currNode, countFirstNode);
842 } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("postProcess"))) {
843 LoadEffectConfigPostProcessCfg(result, currNode, countFirstNode);
844 } else {
845 LoadEffectConfigException(result, currNode, countFirstNode);
846 }
847
848 currNode = currNode->next;
849 }
850
851 for (int32_t i = 0; i < MODULE_SIZE; i++) {
852 if (countFirstNode[i] == 0) {
853 AUDIO_WARNING_LOG("missing information: %{public}s", EFFECT_CONFIG_NAME[i].c_str());
854 }
855 }
856
857 if (doc) {
858 xmlFreeDoc(doc);
859 }
860 return 0;
861 }
862 } // namespace AudioStandard
863 } // namespace OHOS