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