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