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