• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 #include "audio_log.h"
17 
18 #include "xml_parser.h"
19 
20 namespace OHOS {
21 namespace AudioStandard {
LoadConfiguration()22 bool XMLParser::LoadConfiguration()
23 {
24     AUDIO_INFO_LOG("start LoadConfiguration");
25     mDoc = xmlReadFile(CONFIG_FILE, nullptr, 0);
26     if (mDoc == nullptr) {
27         AUDIO_ERR_LOG("xmlReadFile Failed");
28         return false;
29     }
30 
31     return true;
32 }
33 
Parse()34 bool XMLParser::Parse()
35 {
36     xmlNode *root = xmlDocGetRootElement(mDoc);
37     if (root == nullptr) {
38         AUDIO_ERR_LOG("xmlDocGetRootElement Failed");
39         return false;
40     }
41 
42     if (!ParseInternal(*root)) {
43         return false;
44     }
45 
46     return true;
47 }
48 
Destroy()49 void XMLParser::Destroy()
50 {
51     if (mDoc != nullptr) {
52         xmlFreeDoc(mDoc);
53     }
54 }
55 
ParseInternal(xmlNode & node)56 bool XMLParser::ParseInternal(xmlNode &node)
57 {
58     xmlNode *currNode = &node;
59     for (; currNode; currNode = currNode->next) {
60         if (XML_ELEMENT_NODE == currNode->type) {
61             switch (GetNodeNameAsInt(*currNode)) {
62                 case DEVICE_CLASS:
63                     ParseDeviceClass(*currNode);
64                     break;
65                 case AUDIO_INTERRUPT_ENABLE:
66                     ParseAudioInterrupt(*currNode);
67                     break;
68                 case UPDATE_ROUTE_SUPPORT:
69                     ParseUpdateRouteSupport(*currNode);
70                     break;
71                 case AUDIO_LATENCY:
72                     ParseAudioLatency(*currNode);
73                     break;
74                 case SINK_LATENCY:
75                     ParseSinkLatency(*currNode);
76                     break;
77                 case VOLUME_GROUP_CONFIG:
78                     ParseGroups(*currNode, VOLUME_GROUP_CONFIG);
79                     break;
80                 case INTERRUPT_GROUP_CONFIG:
81                     ParseGroups(*currNode, INTERRUPT_GROUP_CONFIG);
82                     break;
83                 default:
84                     ParseInternal(*(currNode->children));
85                     break;
86             }
87         }
88     }
89 
90     mPortObserver.OnXmlParsingCompleted(xmlParsedDataMap_);
91     mPortObserver.OnVolumeGroupParsed(volumeGroupMap_);
92     mPortObserver.OnInterruptGroupParsed(interruptGroupMap_);
93     return true;
94 }
95 
ParseDeviceClass(xmlNode & node)96 void XMLParser::ParseDeviceClass(xmlNode &node)
97 {
98     xmlNode *modulesNode = nullptr;
99     modulesNode = node.xmlChildrenNode;
100 
101     std::string className = ExtractPropertyValue("name", node);
102     if (className.empty()) {
103         AUDIO_ERR_LOG("No name provided for the device class %{public}s", node.name);
104         return;
105     }
106 
107     deviceClassType_ = GetDeviceClassType(className);
108     xmlParsedDataMap_[deviceClassType_] = {};
109 
110     while (modulesNode != nullptr) {
111         if (modulesNode->type == XML_ELEMENT_NODE) {
112             ParseModules(*modulesNode, className);
113         }
114         modulesNode = modulesNode->next;
115     }
116 }
117 
ParseModules(xmlNode & node,std::string & className)118 void XMLParser::ParseModules(xmlNode &node, std::string &className)
119 {
120     xmlNode *moduleNode = nullptr;
121     std::list<AudioModuleInfo> moduleList = {};
122     moduleNode = node.xmlChildrenNode;
123 
124     while (moduleNode != nullptr) {
125         if (moduleNode->type == XML_ELEMENT_NODE) {
126             AudioModuleInfo moduleInfo = {};
127             moduleInfo.className = className;
128             moduleInfo.name = ExtractPropertyValue("name", *moduleNode);
129             moduleInfo.lib = ExtractPropertyValue("lib", *moduleNode);
130             moduleInfo.role = ExtractPropertyValue("role", *moduleNode);
131             moduleInfo.rate = ExtractPropertyValue("rate", *moduleNode);
132             moduleInfo.format = ExtractPropertyValue("format", *moduleNode);
133             moduleInfo.channels = ExtractPropertyValue("channels", *moduleNode);
134             moduleInfo.bufferSize = ExtractPropertyValue("buffer_size", *moduleNode);
135             moduleInfo.fileName = ExtractPropertyValue("file", *moduleNode);
136             moduleInfo.ports = {};
137 
138             ParsePorts(*moduleNode, moduleInfo);
139             moduleList.push_back(moduleInfo);
140         }
141         moduleNode = moduleNode->next;
142     }
143 
144     xmlParsedDataMap_[deviceClassType_] = moduleList;
145 }
146 
ParsePorts(xmlNode & node,AudioModuleInfo & moduleInfo)147 void XMLParser::ParsePorts(xmlNode &node, AudioModuleInfo &moduleInfo)
148 {
149     xmlNode *portsNode = nullptr;
150     portsNode = node.xmlChildrenNode;
151 
152     while (portsNode != nullptr) {
153         if (portsNode->type == XML_ELEMENT_NODE) {
154             ParsePort(*portsNode, moduleInfo);
155         }
156         portsNode = portsNode->next;
157     }
158 }
159 
ParsePort(xmlNode & node,AudioModuleInfo & moduleInfo)160 void XMLParser::ParsePort(xmlNode &node, AudioModuleInfo &moduleInfo)
161 {
162     xmlNode *portNode = nullptr;
163     std::list<AudioModuleInfo> portInfoList = {};
164     portNode = node.xmlChildrenNode;
165 
166     while (portNode != nullptr) {
167         if (portNode->type == XML_ELEMENT_NODE) {
168             moduleInfo.adapterName = ExtractPropertyValue("adapter_name", *portNode);
169             moduleInfo.id = ExtractPropertyValue("id", *portNode);
170 
171             // if some parameter is not configured inside <Port>, take data from moduleinfo
172             std::string value = ExtractPropertyValue("rate", *portNode);
173             if (!value.empty()) {
174                 moduleInfo.rate = value;
175             }
176 
177             value = ExtractPropertyValue("format", *portNode);
178             if (!value.empty()) {
179                 moduleInfo.format = value;
180             }
181 
182             value = ExtractPropertyValue("channels", *portNode);
183             if (!value.empty()) {
184                 moduleInfo.channels = value;
185             }
186 
187             value = ExtractPropertyValue("buffer_size", *portNode);
188             if (!value.empty()) {
189                 moduleInfo.bufferSize = value;
190             }
191 
192             value = ExtractPropertyValue("fixed_latency", *portNode);
193             if (!value.empty()) {
194                 moduleInfo.fixedLatency = value;
195             }
196 
197             value = ExtractPropertyValue("render_in_idle_state", *portNode);
198             if (!value.empty()) {
199                 moduleInfo.renderInIdleState = value;
200             }
201 
202             value = ExtractPropertyValue("open_mic_speaker", *portNode);
203             if (!value.empty()) {
204                 moduleInfo.OpenMicSpeaker = value;
205             }
206 
207             value = ExtractPropertyValue("file", *portNode);
208             if (!value.empty()) {
209                 moduleInfo.fileName = value;
210             }
211 
212             portInfoList.push_back(moduleInfo);
213         }
214         portNode = portNode->next;
215     }
216 
217     moduleInfo.ports.assign(portInfoList.begin(), portInfoList.end());
218 }
219 
GetNodeNameAsInt(xmlNode & node)220 NodeName XMLParser::GetNodeNameAsInt(xmlNode &node)
221 {
222     if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("deviceclass"))) {
223         return DEVICE_CLASS;
224     } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("AudioInterruptEnable"))) {
225         return AUDIO_INTERRUPT_ENABLE;
226     } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("UpdateRouteSupport"))) {
227         return UPDATE_ROUTE_SUPPORT;
228     } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("AudioLatency"))) {
229         return AUDIO_LATENCY;
230     } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("SinkLatency"))) {
231         return SINK_LATENCY;
232     } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("VolumeGroupConfig"))) {
233         return VOLUME_GROUP_CONFIG;
234     } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("InterruptGroupConfig"))) {
235         return INTERRUPT_GROUP_CONFIG;
236     } else {
237         return UNKNOWN;
238     }
239 }
240 
ParseUpdateRouteSupport(xmlNode & node)241 void XMLParser::ParseUpdateRouteSupport(xmlNode &node)
242 {
243     xmlNode *child = node.children;
244     xmlChar *supportFlag = xmlNodeGetContent(child);
245 
246     if (!xmlStrcmp(supportFlag, reinterpret_cast<const xmlChar*>("true"))) {
247         mPortObserver.OnUpdateRouteSupport(true);
248     } else {
249         mPortObserver.OnUpdateRouteSupport(false);
250     }
251 
252     xmlFree(supportFlag);
253 }
254 
ParseAudioInterrupt(xmlNode & node)255 void XMLParser::ParseAudioInterrupt(xmlNode &node)
256 {
257     xmlNode *child = node.children;
258     xmlChar *enableFlag = xmlNodeGetContent(child);
259 
260     if (!xmlStrcmp(enableFlag, reinterpret_cast<const xmlChar*>("true"))) {
261         mPortObserver.OnAudioInterruptEnable(true);
262     } else {
263         mPortObserver.OnAudioInterruptEnable(false);
264     }
265 
266     xmlFree(enableFlag);
267 }
268 
GetDeviceClassType(const std::string & deviceClass)269 ClassType XMLParser::GetDeviceClassType(const std::string &deviceClass)
270 {
271     if (deviceClass == PRIMARY_CLASS)
272         return ClassType::TYPE_PRIMARY;
273     else if (deviceClass == A2DP_CLASS)
274         return ClassType::TYPE_A2DP;
275     else if (deviceClass == USB_CLASS)
276         return ClassType::TYPE_USB;
277     else if (deviceClass == FILE_CLASS)
278         return ClassType::TYPE_FILE_IO;
279     else
280         return ClassType::TYPE_INVALID;
281 }
282 
ExtractPropertyValue(const std::string & propName,xmlNode & node)283 std::string XMLParser::ExtractPropertyValue(const std::string &propName, xmlNode &node)
284 {
285     std::string propValue = "";
286     xmlChar *tempValue = nullptr;
287 
288     if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
289         tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
290     }
291 
292     if (tempValue != nullptr) {
293         propValue = reinterpret_cast<const char*>(tempValue);
294         xmlFree(tempValue);
295     }
296 
297     return propValue;
298 }
299 
ParseAudioLatency(xmlNode & node)300 void XMLParser::ParseAudioLatency(xmlNode &node)
301 {
302     xmlNode *child = node.children;
303     xmlChar *audioLatency = xmlNodeGetContent(child);
304     std::string sAudioLatency(reinterpret_cast<char *>(audioLatency));
305     mPortObserver.OnAudioLatencyParsed((uint64_t)std::stoi(sAudioLatency));
306 
307     xmlFree(audioLatency);
308 }
309 
ParseSinkLatency(xmlNode & node)310 void XMLParser::ParseSinkLatency(xmlNode &node)
311 {
312     xmlNode *child = node.children;
313     xmlChar *latency = xmlNodeGetContent(child);
314     std::string sLatency(reinterpret_cast<char *>(latency));
315     mPortObserver.OnSinkLatencyParsed((uint64_t)std::stoi(sLatency));
316 
317     xmlFree(latency);
318 }
319 
ParseGroups(xmlNode & node,NodeName type)320 void XMLParser::ParseGroups(xmlNode& node, NodeName type)
321 {
322     xmlNode* groupsNode = nullptr;
323     groupsNode = node.xmlChildrenNode; // get <groups>
324     while (groupsNode != nullptr) {
325         if (groupsNode->type == XML_ELEMENT_NODE) {
326             ParseGroup(*groupsNode, type);
327         }
328         groupsNode = groupsNode->next;
329     }
330 }
331 
ParseGroup(xmlNode & node,NodeName type)332 void XMLParser::ParseGroup(xmlNode& node, NodeName type)
333 {
334     xmlNode* groupNode = nullptr;
335     groupNode = node.xmlChildrenNode;
336 
337     while (groupNode != nullptr) {
338         if (groupNode->type == XML_ELEMENT_NODE) {
339             std::string groupName = ExtractPropertyValue("name", *groupNode);
340             ParseGroupModule(*groupNode, type, groupName);
341         }
342         groupNode = groupNode->next;
343     }
344 }
345 
ParseGroupModule(xmlNode & node,NodeName type,std::string groupName)346 void XMLParser::ParseGroupModule(xmlNode& node, NodeName type, std::string groupName)
347 {
348     xmlNode* moduleNode = nullptr;
349     moduleNode = node.xmlChildrenNode;
350     while (moduleNode != nullptr) {
351         if (moduleNode->type == XML_ELEMENT_NODE) {
352             std::string moduleName = ExtractPropertyValue("name", *moduleNode);
353             if (type == VOLUME_GROUP_CONFIG) {
354                 volumeGroupMap_[moduleName] = groupName;
355             } else if (type == INTERRUPT_GROUP_CONFIG) {
356                 interruptGroupMap_[moduleName] = groupName;
357             }
358         }
359         moduleNode = moduleNode->next;
360     }
361 }
362 } // namespace AudioStandard
363 } // namespace OHOS
364