1 /*
2 * Copyright (c) 2024 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
16 #ifndef LOG_TAG
17 #define LOG_TAG "AudioPolicyParser"
18 #endif
19
20 #include "audio_policy_parser.h"
21
22 #include <sstream>
23
24 namespace OHOS {
25 namespace AudioStandard {
26 constexpr int32_t AUDIO_MS_PER_S = 1000;
27 constexpr uint32_t LAYOUT_MONO_CHANNEL_ENUM = 1;
28 constexpr uint32_t LAYOUT_STEREO_CHANNEL_ENUM = 2;
29 constexpr uint32_t LAYOUT_4POINT0_CHANNEL_ENUM = 4;
30 constexpr uint32_t LAYOUT_QUAD_CHANNEL_ENUM = 4;
31 constexpr uint32_t LAYOUT_5POINT1_CHANNEL_ENUM = 6;
32 constexpr uint32_t LAYOUT_7POINT1_CHANNEL_ENUM = 8;
33 constexpr uint32_t S16LE_TO_BYTE = 2;
34 constexpr uint32_t S24LE_TO_BYTE = 3;
35 constexpr uint32_t S32LE_TO_BYTE = 4;
36
37 static std::map<std::string, uint32_t> layoutStrToChannels = {
38 {"CH_LAYOUT_MONO", LAYOUT_MONO_CHANNEL_ENUM},
39 {"CH_LAYOUT_STEREO", LAYOUT_STEREO_CHANNEL_ENUM},
40 {"CH_LAYOUT_4POINT0", LAYOUT_4POINT0_CHANNEL_ENUM},
41 {"CH_LAYOUT_QUAD", LAYOUT_QUAD_CHANNEL_ENUM},
42 {"CH_LAYOUT_5POINT1", LAYOUT_5POINT1_CHANNEL_ENUM},
43 {"CH_LAYOUT_7POINT1", LAYOUT_7POINT1_CHANNEL_ENUM},
44 };
45
46 static std::map<std::string, uint32_t> formatStrToEnum = {
47 {"s16le", S16LE_TO_BYTE},
48 {"s24le", S24LE_TO_BYTE},
49 {"s32le", S32LE_TO_BYTE},
50 };
51
52 static std::map<std::string, uint32_t> audioFlagStrToEnum = {
53 {"AUDIO_FLAG_NORMAL", AUDIO_FLAG_NORMAL},
54 {"AUDIO_FLAG_MMAP", AUDIO_FLAG_MMAP},
55 };
56
57 static std::map<std::string, uint32_t> audioUsageStrToEnum = {
58 {"AUDIO_USAGE_NORMAL", AUDIO_USAGE_NORMAL},
59 {"AUDIO_USAGE_VOIP", AUDIO_USAGE_VOIP},
60 };
61
LoadConfiguration()62 bool AudioPolicyParser::LoadConfiguration()
63 {
64 AUDIO_INFO_LOG("Enter");
65 doc_ = xmlReadFile(CHIP_PROD_CONFIG_FILE, nullptr, 0);
66 if (doc_ == nullptr) {
67 doc_ = xmlReadFile(CONFIG_FILE, nullptr, 0);
68 if (doc_ == nullptr) {
69 AUDIO_ERR_LOG("xmlReadFile Failed");
70 return false;
71 }
72 }
73 AUDIO_INFO_LOG("Done");
74 return true;
75 }
76
77 // LCOV_EXCL_START
Parse()78 bool AudioPolicyParser::Parse()
79 {
80 AUDIO_INFO_LOG("Enter");
81 xmlNode *root = xmlDocGetRootElement(doc_);
82 if (root == nullptr) {
83 AUDIO_ERR_LOG("xmlDocGetRootElement Failed");
84 return false;
85 }
86 if (!ParseInternal(*root)) {
87 AUDIO_ERR_LOG("Audio policy config xml parse failed.");
88 return false;
89 }
90
91 std::unordered_map<std::string, std::string> volumeGroupMap {};
92 std::unordered_map<std::string, std::string> interruptGroupMap {};
93
94 ConvertAdapterInfoToGroupInfo(volumeGroupMap, interruptGroupMap);
95 ConvertAdapterInfoToAudioModuleInfo();
96
97 volumeGroupMap_ = volumeGroupMap;
98 interruptGroupMap_ = interruptGroupMap;
99
100 portObserver_.OnAudioPolicyXmlParsingCompleted(adapterInfoMap_);
101 portObserver_.OnXmlParsingCompleted(xmlParsedDataMap_);
102 portObserver_.OnVolumeGroupParsed(volumeGroupMap_);
103 portObserver_.OnInterruptGroupParsed(interruptGroupMap_);
104 portObserver_.OnGlobalConfigsParsed(globalConfigs_);
105 AUDIO_INFO_LOG("Done");
106 return true;
107 }
108
Destroy()109 void AudioPolicyParser::Destroy()
110 {
111 if (doc_ != nullptr) {
112 xmlFreeDoc(doc_);
113 }
114 }
115
ParseInternal(xmlNode & node)116 bool AudioPolicyParser::ParseInternal(xmlNode &node)
117 {
118 xmlNode *currNode = &node;
119 for (; currNode; currNode = currNode->next) {
120 if (XML_ELEMENT_NODE == currNode->type) {
121 switch (GetXmlNodeTypeAsInt(*currNode)) {
122 case XmlNodeType::ADAPTERS:
123 ParseAdapters(*currNode);
124 break;
125 case XmlNodeType::VOLUME_GROUPS:
126 ParseGroups(*currNode, XmlNodeType::VOLUME_GROUPS);
127 break;
128 case XmlNodeType::INTERRUPT_GROUPS:
129 ParseGroups(*currNode, XmlNodeType::INTERRUPT_GROUPS);
130 break;
131 case XmlNodeType::GLOBAL_CONFIGS:
132 ParseGlobalConfigs(*currNode);
133 break;
134 default:
135 ParseInternal(*(currNode->children));
136 break;
137 }
138 }
139 }
140 return true;
141 }
142
ParseAdapters(xmlNode & node)143 void AudioPolicyParser::ParseAdapters(xmlNode &node)
144 {
145 xmlNode *currNode = nullptr;
146 currNode = node.xmlChildrenNode;
147
148 while (currNode != nullptr) {
149 if (currNode->type == XML_ELEMENT_NODE) {
150 ParseAdapter(*currNode);
151 }
152 currNode = currNode->next;
153 }
154 }
155
ConvertAdapterInfoToGroupInfo(std::unordered_map<std::string,std::string> & volumeGroupMap,std::unordered_map<std::string,std::string> & interruptGroupMap)156 void AudioPolicyParser::ConvertAdapterInfoToGroupInfo(std::unordered_map<std::string, std::string> &volumeGroupMap,
157 std::unordered_map<std::string, std::string> &interruptGroupMap)
158 {
159 for (auto &[sinkName, groupName] : volumeGroupMap_) {
160 volumeGroupMap["Speaker"] = groupName;
161 }
162
163 for (auto &[sinkName, groupName] : interruptGroupMap_) {
164 interruptGroupMap["Speaker"] = groupName;
165 }
166 }
167
GetCommontAudioModuleInfo(PipeInfo & pipeInfo,AudioModuleInfo & audioModuleInfo)168 void AudioPolicyParser::GetCommontAudioModuleInfo(PipeInfo &pipeInfo, AudioModuleInfo &audioModuleInfo)
169 {
170 audioModuleInfo.role = pipeInfo.paPropRole_;
171
172 for (auto sampleRate : pipeInfo.sampleRates_) {
173 audioModuleInfo.supportedRate_.insert(sampleRate);
174 }
175 for (auto channelLayout : pipeInfo.channelLayouts_) {
176 audioModuleInfo.supportedChannels_.insert(channelLayout);
177 }
178
179 audioModuleInfo.lib = pipeInfo.lib_;
180
181 if (pipeInfo.streamPropInfos_.size() != 0) {
182 audioModuleInfo.rate = std::to_string((*pipeInfo.streamPropInfos_.begin()).sampleRate_);
183 audioModuleInfo.format = (*pipeInfo.streamPropInfos_.begin()).format_;
184 audioModuleInfo.channels = std::to_string((*pipeInfo.streamPropInfos_.begin()).channelLayout_);
185 audioModuleInfo.bufferSize = std::to_string((*pipeInfo.streamPropInfos_.begin()).bufferSize_);
186 }
187
188 for (auto &config : pipeInfo.configInfos_) {
189 if (config.name_ == "filePath") {
190 audioModuleInfo.fileName = config.value_;
191 }
192 }
193
194 audioModuleInfo.fixedLatency = pipeInfo.fixedLatency_;
195 audioModuleInfo.renderInIdleState = pipeInfo.renderInIdleState_;
196 }
197
GetClassTypeByAdapterType(AdaptersType adapterType)198 ClassType AudioPolicyParser::GetClassTypeByAdapterType(AdaptersType adapterType)
199 {
200 if (adapterType == AdaptersType::TYPE_PRIMARY) {
201 return ClassType::TYPE_PRIMARY;
202 } else if (adapterType == AdaptersType::TYPE_A2DP) {
203 return ClassType::TYPE_A2DP;
204 } else if (adapterType == AdaptersType::TYPE_REMOTE_AUDIO) {
205 return ClassType::TYPE_REMOTE_AUDIO;
206 } else if (adapterType == AdaptersType::TYPE_FILE_IO) {
207 return ClassType::TYPE_FILE_IO;
208 } else if (adapterType == AdaptersType::TYPE_USB) {
209 return ClassType::TYPE_USB;
210 } else if (adapterType == AdaptersType::TYPE_DP) {
211 return ClassType::TYPE_DP;
212 } else {
213 return ClassType::TYPE_INVALID;
214 }
215 }
216
217 // LCOV_EXCL_STOP
GetOffloadAndOpenMicState(AudioAdapterInfo & adapterInfo,bool & shouldEnableOffload)218 void AudioPolicyParser::GetOffloadAndOpenMicState(AudioAdapterInfo &adapterInfo,
219 bool &shouldEnableOffload)
220 {
221 for (auto &pipeInfo : adapterInfo.pipeInfos_) {
222 if (pipeInfo.paPropRole_ == MODULE_TYPE_SINK &&
223 pipeInfo.name_.find(MODULE_SINK_OFFLOAD) != std::string::npos) {
224 shouldEnableOffload = true;
225 }
226 }
227 }
228
GetAudioModuleInfoName(std::string & pipeInfoName,std::list<AudioPipeDeviceInfo> & deviceInfos)229 std::string AudioPolicyParser::GetAudioModuleInfoName(std::string &pipeInfoName,
230 std::list<AudioPipeDeviceInfo> &deviceInfos)
231 {
232 for (auto &deviceInfo : deviceInfos) {
233 if (std::find(deviceInfo.supportPipes_.begin(), deviceInfo.supportPipes_.end(), pipeInfoName) !=
234 deviceInfo.supportPipes_.end()) {
235 return deviceInfo.name_;
236 }
237 }
238 return "";
239 }
240
241 // LCOV_EXCL_START
ConvertAdapterInfoToAudioModuleInfo()242 void AudioPolicyParser::ConvertAdapterInfoToAudioModuleInfo()
243 {
244 for (auto &[adapterType, adapterInfo] : adapterInfoMap_) {
245 std::list<AudioModuleInfo> audioModuleList = {};
246 bool shouldEnableOffload = false;
247 if (adapterType == AdaptersType::TYPE_PRIMARY) {
248 GetOffloadAndOpenMicState(adapterInfo, shouldEnableOffload);
249 }
250
251 std::string currentRole = "";
252 for (auto &pipeInfo : adapterInfo.pipeInfos_) {
253 if (currentRole == pipeInfo.pipeRole_) {
254 continue;
255 }
256 currentRole = pipeInfo.pipeRole_;
257 CHECK_AND_CONTINUE_LOG(pipeInfo.name_.find(MODULE_SINK_OFFLOAD) == std::string::npos,
258 "skip offload out sink.");
259 AudioModuleInfo audioModuleInfo = {};
260 GetCommontAudioModuleInfo(pipeInfo, audioModuleInfo);
261
262 audioModuleInfo.className = adapterInfo.adapterName_;
263 // The logic here strongly depends on the moduleName in the XML
264 if (pipeInfo.moduleName_ != "") {
265 audioModuleInfo.name = pipeInfo.moduleName_;
266 } else {
267 audioModuleInfo.name = GetAudioModuleInfoName(pipeInfo.name_, adapterInfo.deviceInfos_);
268 }
269
270 audioModuleInfo.adapterName = adapterInfo.adapterName_;
271 if (adapterType == AdaptersType::TYPE_FILE_IO) {
272 audioModuleInfo.adapterName = STR_INIT;
273 audioModuleInfo.format = STR_INIT;
274 audioModuleInfo.className = FILE_CLASS;
275 }
276 audioModuleInfo.sinkLatency = globalConfigs_.globalPaConfigs_.sinkLatency_;
277
278 shouldOpenMicSpeaker_ ? audioModuleInfo.OpenMicSpeaker = "1" : audioModuleInfo.OpenMicSpeaker = "0";
279 if (adapterType == AdaptersType::TYPE_PRIMARY &&
280 shouldEnableOffload && pipeInfo.paPropRole_ == MODULE_TYPE_SINK) {
281 audioModuleInfo.offloadEnable = "1";
282 }
283 audioModuleList.push_back(audioModuleInfo);
284 }
285 std::list<AudioModuleInfo> audioModuleListTmp = audioModuleList;
286 std::list<AudioModuleInfo> audioModuleListData = {};
287 for (auto audioModuleInfo : audioModuleList) {
288 audioModuleInfo.ports = audioModuleListTmp;
289 audioModuleListData.push_back(audioModuleInfo);
290 }
291 ClassType classType = GetClassTypeByAdapterType(adapterType);
292 xmlParsedDataMap_[classType] = audioModuleListData;
293 }
294 }
295
ParseAdapter(xmlNode & node)296 void AudioPolicyParser::ParseAdapter(xmlNode &node)
297 {
298 std::string adapterName = ExtractPropertyValue("name", node);
299 if (adapterName.empty()) {
300 AUDIO_ERR_LOG("No name provided for the adapter class %{public}s", node.name);
301 return;
302 }
303
304 AdaptersType adaptersType = GetAdaptersType(adapterName);
305 adapterInfoMap_[adaptersType] = {};
306
307 AudioAdapterInfo adapterInfo = {};
308 adapterInfo.adapterName_ = adapterName;
309 adapterInfo.adaptersupportScene_ = ExtractPropertyValue("supportScene", node);
310
311 xmlNode *currNode = node.xmlChildrenNode;
312 while (currNode != nullptr) {
313 if (currNode->type == XML_ELEMENT_NODE) {
314 switch (GetAdapterTypeAsInt(*currNode)) {
315 case AdapterType::PIPES:
316 ParsePipes(*currNode, adapterInfo);
317 break;
318 case AdapterType::DEVICES:
319 ParseDevices(*currNode, adapterInfo);
320 break;
321 default:
322 ParseAdapter(*(currNode->children));
323 break;
324 }
325 }
326 currNode = currNode->next;
327 }
328 adapterInfoMap_[adaptersType] = adapterInfo;
329 }
330
ParsePipes(xmlNode & node,AudioAdapterInfo & adapterInfo)331 void AudioPolicyParser::ParsePipes(xmlNode &node, AudioAdapterInfo &adapterInfo)
332 {
333 xmlNode *currNode = node.xmlChildrenNode;
334 std::list<PipeInfo> pipeInfos;
335
336 while (currNode != nullptr) {
337 if (currNode->type == XML_ELEMENT_NODE) {
338 PipeInfo pipeInfo {};
339 pipeInfo.name_ = ExtractPropertyValue("name", *currNode);
340 pipeInfo.pipeRole_ = ExtractPropertyValue("role", *currNode);
341 pipeInfo.pipeFlags_ = ExtractPropertyValue("flags", *currNode);
342 ParsePipeInfos(*currNode, pipeInfo);
343 pipeInfos.push_back(pipeInfo);
344 }
345 currNode = currNode->next;
346 }
347 adapterInfo.pipeInfos_ = pipeInfos;
348 }
349
SplitChannelStringToSet(std::string & str,std::set<uint32_t> & result)350 void AudioPolicyParser::SplitChannelStringToSet(std::string &str, std::set<uint32_t> &result)
351 {
352 std::stringstream ss(str);
353 std::string token;
354
355 while (std::getline(ss, token, ',')) {
356 result.insert(layoutStrToChannels[token]);
357 }
358 }
359
ParsePipeInfos(xmlNode & node,PipeInfo & pipeInfo)360 void AudioPolicyParser::ParsePipeInfos(xmlNode &node, PipeInfo &pipeInfo)
361 {
362 xmlNode *currNode = node.xmlChildrenNode;
363 while (currNode != nullptr) {
364 if (currNode->type == XML_ELEMENT_NODE) {
365 switch (GetPipeInfoTypeAsInt(*currNode)) {
366 case PipeType::PA_PROP:
367 pipeInfo.lib_ = ExtractPropertyValue("lib", *currNode);
368 pipeInfo.paPropRole_ = ExtractPropertyValue("role", *currNode);
369 pipeInfo.fixedLatency_ = ExtractPropertyValue("fixed_latency", *currNode);
370 pipeInfo.renderInIdleState_ = ExtractPropertyValue("render_in_idle_state", *currNode);
371 pipeInfo.moduleName_ = ExtractPropertyValue("moduleName", *currNode);
372 break;
373 case PipeType::STREAM_PROP:
374 ParseStreamProps(*currNode, pipeInfo);
375 break;
376 case PipeType::CONFIGS:
377 ParseConfigs(*currNode, pipeInfo);
378 break;
379 default:
380 ParsePipeInfos(*(currNode->children), pipeInfo);
381 break;
382 }
383 }
384 currNode = currNode->next;
385 }
386 }
387
GetAdapterTypeAsInt(xmlNode & node)388 AdapterType AudioPolicyParser::GetAdapterTypeAsInt(xmlNode &node)
389 {
390 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("pipes"))) {
391 return AdapterType::PIPES;
392 } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("devices"))) {
393 return AdapterType::DEVICES;
394 } else {
395 return AdapterType::UNKNOWN;
396 }
397 }
398
GetPipeInfoTypeAsInt(xmlNode & node)399 PipeType AudioPolicyParser::GetPipeInfoTypeAsInt(xmlNode &node)
400 {
401 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("paProp"))) {
402 return PipeType::PA_PROP;
403 } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("streamProps"))) {
404 return PipeType::STREAM_PROP;
405 } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("attributes"))) {
406 return PipeType::CONFIGS;
407 } else {
408 return PipeType::UNKNOWN;
409 }
410 }
411
ParseStreamProps(xmlNode & node,PipeInfo & pipeInfo)412 void AudioPolicyParser::ParseStreamProps(xmlNode &node, PipeInfo &pipeInfo)
413 {
414 xmlNode *currNode = node.xmlChildrenNode;
415 std::list<StreamPropInfo> streamPropInfos;
416
417 while (currNode != nullptr) {
418 if (currNode->type == XML_ELEMENT_NODE) {
419 StreamPropInfo streamPropInfo = {};
420 streamPropInfo.format_ = ExtractPropertyValue("format", *currNode);
421 std::string sampleRateStr = ExtractPropertyValue("sampleRates", *currNode);
422 if (sampleRateStr != "") {
423 streamPropInfo.sampleRate_ = (uint32_t)std::stoi(sampleRateStr);
424 pipeInfo.sampleRates_.push_back(streamPropInfo.sampleRate_);
425 }
426 std::string periodInMsStr = ExtractPropertyValue("periodInMs", *currNode);
427 if (periodInMsStr != "") {
428 streamPropInfo.periodInMs_ = (uint32_t)std::stoi(periodInMsStr);
429 }
430 std::string channelLayoutStr = ExtractPropertyValue("channelLayout", *currNode);
431 if (channelLayoutStr != "") {
432 streamPropInfo.channelLayout_ = layoutStrToChannels[channelLayoutStr];
433 pipeInfo.channelLayouts_.push_back(streamPropInfo.channelLayout_);
434 }
435
436 std::string bufferSizeStr = ExtractPropertyValue("bufferSize", *currNode);
437 if (bufferSizeStr != "") {
438 streamPropInfo.bufferSize_ = (uint32_t)std::stoi(bufferSizeStr);
439 } else {
440 streamPropInfo.bufferSize_ = formatStrToEnum[streamPropInfo.format_] * streamPropInfo.sampleRate_ *
441 streamPropInfo.periodInMs_ * streamPropInfo.channelLayout_ / AUDIO_MS_PER_S;
442 }
443
444 streamPropInfos.push_back(streamPropInfo);
445 }
446 currNode = currNode->next;
447 }
448 pipeInfo.streamPropInfos_ = streamPropInfos;
449 }
450
ParseConfigs(xmlNode & node,PipeInfo & pipeInfo)451 void AudioPolicyParser::ParseConfigs(xmlNode &node, PipeInfo &pipeInfo)
452 {
453 xmlNode *configNode = nullptr;
454 configNode = node.xmlChildrenNode;
455 std::list<ConfigInfo> configInfos;
456
457 while (configNode != nullptr) {
458 if (configNode->type == XML_ELEMENT_NODE) {
459 ConfigInfo configInfo = {};
460 configInfo.name_ = ExtractPropertyValue("name", *configNode);
461 configInfo.value_ = ExtractPropertyValue("value", *configNode);
462 configInfos.push_back(configInfo);
463 HandleConfigFlagAndUsage(configInfo, pipeInfo);
464 }
465 configNode = configNode->next;
466 }
467
468 if (pipeInfo.audioUsage_ == AUDIO_USAGE_VOIP && pipeInfo.audioFlag_ == AUDIO_FLAG_MMAP) {
469 portObserver_.OnVoipConfigParsed(true);
470 }
471 pipeInfo.configInfos_ = configInfos;
472 }
473
HandleConfigFlagAndUsage(ConfigInfo & configInfo,PipeInfo & pipeInfo)474 void AudioPolicyParser::HandleConfigFlagAndUsage(ConfigInfo &configInfo, PipeInfo &pipeInfo)
475 {
476 if (configInfo.name_ == "flag") {
477 auto it = audioFlagStrToEnum.find(configInfo.value_);
478 if (it != audioFlagStrToEnum.end()) {
479 pipeInfo.audioFlag_ = static_cast<int32_t>(it->second);
480 }
481 } else if (configInfo.name_ == "usage") {
482 auto it = audioUsageStrToEnum.find(configInfo.value_);
483 if (it != audioUsageStrToEnum.end()) {
484 pipeInfo.audioUsage_ = static_cast<int32_t>(it->second);
485 }
486 }
487 }
488
ParseDevices(xmlNode & node,AudioAdapterInfo & adapterInfo)489 void AudioPolicyParser::ParseDevices(xmlNode &node, AudioAdapterInfo &adapterInfo)
490 {
491 xmlNode *currNode = nullptr;
492 currNode = node.xmlChildrenNode;
493 std::list<AudioPipeDeviceInfo> deviceInfos = {};
494
495 while (currNode != nullptr) {
496 if (currNode->type == XML_ELEMENT_NODE) {
497 AudioPipeDeviceInfo deviceInfo = {};
498 deviceInfo.name_ = ExtractPropertyValue("name", *currNode);
499 deviceInfo.type_ = ExtractPropertyValue("type", *currNode);
500 deviceInfo.pin_ = ExtractPropertyValue("pin", *currNode);
501 deviceInfo.role_ = ExtractPropertyValue("role", *currNode);
502 std::string supportPipeInStr = ExtractPropertyValue("supportPipes", *currNode);
503 SplitStringToList(supportPipeInStr, deviceInfo.supportPipes_);
504 deviceInfos.push_back(deviceInfo);
505 }
506 currNode = currNode->next;
507 }
508 adapterInfo.deviceInfos_ = deviceInfos;
509 }
510
SplitStringToList(std::string & str,std::list<std::string> & result)511 void AudioPolicyParser::SplitStringToList(std::string &str, std::list<std::string> &result)
512 {
513 char *token = std::strtok(&str[0], ",");
514 while (token != nullptr) {
515 result.push_back(token);
516 token = std::strtok(nullptr, ",");
517 }
518 }
519
ParseGroups(xmlNode & node,XmlNodeType type)520 void AudioPolicyParser::ParseGroups(xmlNode &node, XmlNodeType type)
521 {
522 xmlNode *currNode = nullptr;
523 currNode = node.xmlChildrenNode;
524
525 while (currNode != nullptr) {
526 if (currNode->type == XML_ELEMENT_NODE) {
527 ParseGroup(*currNode, type);
528 }
529 currNode = currNode->next;
530 }
531 }
532
ParseGroup(xmlNode & node,XmlNodeType type)533 void AudioPolicyParser::ParseGroup(xmlNode &node, XmlNodeType type)
534 {
535 xmlNode *currNode = nullptr;
536 currNode = node.xmlChildrenNode;
537
538 while (currNode != nullptr) {
539 if (currNode->type == XML_ELEMENT_NODE) {
540 std::string groupName = ExtractPropertyValue("name", *currNode);
541 ParseGroupSink(*currNode, type, groupName);
542 }
543 currNode = currNode->next;
544 }
545 }
546
ParseGroupSink(xmlNode & node,XmlNodeType type,std::string & groupName)547 void AudioPolicyParser::ParseGroupSink(xmlNode &node, XmlNodeType type, std::string &groupName)
548 {
549 xmlNode *currNode = nullptr;
550 currNode = node.xmlChildrenNode;
551
552 while (currNode != nullptr) {
553 if (currNode->type == XML_ELEMENT_NODE) {
554 std::string sinkName = ExtractPropertyValue("name", *currNode);
555 if (type == XmlNodeType::VOLUME_GROUPS) {
556 volumeGroupMap_[sinkName] = groupName;
557 } else if (type == XmlNodeType::INTERRUPT_GROUPS) {
558 interruptGroupMap_[sinkName] = groupName;
559 }
560 }
561 currNode = currNode->next;
562 }
563 }
564
ParseGlobalConfigs(xmlNode & node)565 void AudioPolicyParser::ParseGlobalConfigs(xmlNode &node)
566 {
567 xmlNode *currNode = node.xmlChildrenNode;
568 while (currNode != nullptr) {
569 if (currNode->type == XML_ELEMENT_NODE) {
570 switch (GetGlobalConfigTypeAsInt(*currNode)) {
571 case GlobalConfigType::DEFAULT_OUTPUT:
572 globalConfigs_.adapter_ = ExtractPropertyValue("adapter", *currNode);
573 globalConfigs_.pipe_ = ExtractPropertyValue("pipe", *currNode);
574 globalConfigs_.device_ = ExtractPropertyValue("device", *currNode);
575 break;
576 case GlobalConfigType::COMMON_CONFIGS:
577 ParseCommonConfigs(*currNode);
578 break;
579 case GlobalConfigType::PA_CONFIGS:
580 ParsePAConfigs(*currNode);
581 break;
582 case GlobalConfigType::DEFAULT_MAX_CON_CURRENT_INSTANCE:
583 ParseDefaultMaxInstances(*currNode);
584 break;
585 default:
586 ParseGlobalConfigs(*(currNode->children));
587 break;
588 }
589 }
590 currNode = currNode->next;
591 }
592 }
593
GetGlobalConfigTypeAsInt(xmlNode & node)594 GlobalConfigType AudioPolicyParser::GetGlobalConfigTypeAsInt(xmlNode &node)
595 {
596 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("defaultOutput"))) {
597 return GlobalConfigType::DEFAULT_OUTPUT;
598 } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("commonConfigs"))) {
599 return GlobalConfigType::COMMON_CONFIGS;
600 } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("paConfigs"))) {
601 return GlobalConfigType::PA_CONFIGS;
602 } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("maxConcurrentInstances"))) {
603 return GlobalConfigType::DEFAULT_MAX_CON_CURRENT_INSTANCE;
604 } else {
605 return GlobalConfigType::UNKNOWN;
606 }
607 }
608
ParsePAConfigs(xmlNode & node)609 void AudioPolicyParser::ParsePAConfigs(xmlNode &node)
610 {
611 xmlNode *currNode = nullptr;
612 currNode = node.xmlChildrenNode;
613
614 while (currNode != nullptr) {
615 if (currNode->type == XML_ELEMENT_NODE) {
616 std::string name = ExtractPropertyValue("name", *currNode);
617 std::string value = ExtractPropertyValue("value", *currNode);
618
619 switch (GetPaConfigType(name)) {
620 case PAConfigType::AUDIO_LATENCY:
621 portObserver_.OnAudioLatencyParsed((uint64_t)std::stoi(value));
622 globalConfigs_.globalPaConfigs_.audioLatency_ = value;
623 break;
624 case PAConfigType::SINK_LATENCY:
625 portObserver_.OnSinkLatencyParsed((uint64_t)std::stoi(value));
626 globalConfigs_.globalPaConfigs_.sinkLatency_ = value;
627 break;
628 default:
629 ParsePAConfigs(*(currNode->children));
630 break;
631 }
632 }
633 currNode = currNode->next;
634 }
635 }
636
ParseDefaultMaxInstances(xmlNode & node)637 void AudioPolicyParser::ParseDefaultMaxInstances(xmlNode &node)
638 {
639 xmlNode *currNode = node.xmlChildrenNode;
640 while (currNode != nullptr) {
641 if (currNode->type == XML_ELEMENT_NODE) {
642 xmlChar *extendInfo = xmlNodeGetContent(currNode);
643 std::string sExtendInfo(reinterpret_cast<char *>(extendInfo));
644 switch (GetDefaultMaxInstanceTypeAsInt(*currNode)) {
645 case DefaultMaxInstanceType::OUTPUT:
646 ParseOutputMaxInstances(*currNode);
647 break;
648 case DefaultMaxInstanceType::INPUT:
649 ParseInputMaxInstances(*currNode);
650 break;
651 default:
652 ParseDefaultMaxInstances(*(currNode->children));
653 break;
654 }
655 }
656 currNode = currNode->next;
657 }
658 }
659
ParseOutputMaxInstances(xmlNode & node)660 void AudioPolicyParser::ParseOutputMaxInstances(xmlNode &node)
661 {
662 xmlNode *currNode = nullptr;
663 currNode = node.xmlChildrenNode;
664 std::list<ConfigInfo> configInfos;
665
666 while (currNode != nullptr) {
667 if (currNode->type == XML_ELEMENT_NODE) {
668 ConfigInfo configInfo = {};
669 configInfo.name_ = ExtractPropertyValue("name", *currNode);
670 configInfo.type_ = ExtractPropertyValue("flag", *currNode);
671 configInfo.value_ = ExtractPropertyValue("value", *currNode);
672 configInfos.push_back(configInfo);
673 }
674 currNode = currNode->next;
675 }
676 globalConfigs_.outputConfigInfos_ = configInfos;
677 }
678
ParseInputMaxInstances(xmlNode & node)679 void AudioPolicyParser::ParseInputMaxInstances(xmlNode &node)
680 {
681 xmlNode *currNode = nullptr;
682 currNode = node.xmlChildrenNode;
683 std::list<ConfigInfo> configInfos;
684
685 while (currNode != nullptr) {
686 if (currNode->type == XML_ELEMENT_NODE) {
687 ConfigInfo configInfo = {};
688 configInfo.name_ = ExtractPropertyValue("name", *currNode);
689 configInfo.type_ = ExtractPropertyValue("flag", *currNode);
690 configInfo.value_ = ExtractPropertyValue("value", *currNode);
691 configInfos.push_back(configInfo);
692 }
693 currNode = currNode->next;
694 }
695 globalConfigs_.inputConfigInfos_ = configInfos;
696 }
697
ParseCommonConfigs(xmlNode & node)698 void AudioPolicyParser::ParseCommonConfigs(xmlNode &node)
699 {
700 xmlNode *currNode = nullptr;
701 currNode = node.xmlChildrenNode;
702 std::list<ConfigInfo> configInfos;
703
704 while (currNode != nullptr) {
705 if (currNode->type == XML_ELEMENT_NODE) {
706 ConfigInfo configInfo = {};
707 configInfo.name_ = ExtractPropertyValue("name", *currNode);
708 configInfo.value_ = ExtractPropertyValue("value", *currNode);
709 configInfos.push_back(configInfo);
710 if (configInfo.name_ == "updateRouteSupport") {
711 AUDIO_INFO_LOG("update route support: %{public}s", configInfo.value_.c_str());
712 HandleUpdateRouteSupportParsed(configInfo.value_);
713 }
714 }
715 currNode = currNode->next;
716 }
717 globalConfigs_.commonConfigs_ = configInfos;
718 }
719
HandleUpdateRouteSupportParsed(std::string & value)720 void AudioPolicyParser::HandleUpdateRouteSupportParsed(std::string &value)
721 {
722 if (value == "true") {
723 portObserver_.OnUpdateRouteSupport(true);
724 shouldOpenMicSpeaker_ = true;
725 } else {
726 portObserver_.OnUpdateRouteSupport(false);
727 shouldOpenMicSpeaker_ = false;
728 }
729 }
730
GetXmlNodeTypeAsInt(xmlNode & node)731 XmlNodeType AudioPolicyParser::GetXmlNodeTypeAsInt(xmlNode &node)
732 {
733 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("adapters"))) {
734 return XmlNodeType::ADAPTERS;
735 } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("volumeGroups"))) {
736 return XmlNodeType::VOLUME_GROUPS;
737 } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("interruptGroups"))) {
738 return XmlNodeType::INTERRUPT_GROUPS;
739 } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("globalConfigs"))) {
740 return XmlNodeType::GLOBAL_CONFIGS;
741 } else {
742 return XmlNodeType::XML_UNKNOWN;
743 }
744 }
745
ExtractPropertyValue(const std::string & propName,xmlNode & node)746 std::string AudioPolicyParser::ExtractPropertyValue(const std::string &propName, xmlNode &node)
747 {
748 std::string propValue = "";
749 xmlChar *tempValue = nullptr;
750
751 if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
752 tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
753 }
754
755 if (tempValue != nullptr) {
756 propValue = reinterpret_cast<const char*>(tempValue);
757 xmlFree(tempValue);
758 }
759
760 return propValue;
761 }
762
GetAdaptersType(const std::string & adapterName)763 AdaptersType AudioPolicyParser::GetAdaptersType(const std::string &adapterName)
764 {
765 if (adapterName == ADAPTER_PRIMARY_TYPE)
766 return AdaptersType::TYPE_PRIMARY;
767 else if (adapterName == ADAPTER_A2DP_TYPE)
768 return AdaptersType::TYPE_A2DP;
769 else if (adapterName == ADAPTER_REMOTE_TYPE)
770 return AdaptersType::TYPE_REMOTE_AUDIO;
771 else if (adapterName == ADAPTER_FILE_TYPE)
772 return AdaptersType::TYPE_FILE_IO;
773 else if (adapterName == ADAPTER_USB_TYPE)
774 return AdaptersType::TYPE_USB;
775 else if (adapterName == ADAPTER_DP_TYPE)
776 return AdaptersType::TYPE_DP;
777 else
778 return AdaptersType::TYPE_INVALID;
779 }
780
GetPaConfigType(std::string & name)781 PAConfigType AudioPolicyParser::GetPaConfigType(std::string &name)
782 {
783 if (name =="audioLatency") {
784 return PAConfigType::AUDIO_LATENCY;
785 } else if (name =="sinkLatency") {
786 return PAConfigType::SINK_LATENCY;
787 } else {
788 return PAConfigType::UNKNOWN;
789 }
790 }
791
GetDefaultMaxInstanceTypeAsInt(xmlNode & node)792 DefaultMaxInstanceType AudioPolicyParser::GetDefaultMaxInstanceTypeAsInt(xmlNode &node)
793 {
794 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("output"))) {
795 return DefaultMaxInstanceType::OUTPUT;
796 } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("input"))) {
797 return DefaultMaxInstanceType::INPUT;
798 } else {
799 return DefaultMaxInstanceType::UNKNOWN;
800 }
801 }
802
GetStreamTypeAsInt(xmlNode & node)803 StreamType AudioPolicyParser::GetStreamTypeAsInt(xmlNode &node)
804 {
805 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("normal"))) {
806 return StreamType::NORMAL;
807 } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("fast"))) {
808 return StreamType::FAST;
809 } else {
810 return StreamType::UNKNOWN;
811 }
812 }
813 // LCOV_EXCL_STOP
814 } // namespace AudioStandard
815 } // namespace OHOS
816