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