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