• 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("source_type", *portNode);
208             if (!value.empty()) {
209                 moduleInfo.sourceType = value;
210             }
211 
212             value = ExtractPropertyValue("file", *portNode);
213             if (!value.empty()) {
214                 moduleInfo.fileName = value;
215             }
216 
217             portInfoList.push_back(moduleInfo);
218         }
219         portNode = portNode->next;
220     }
221 
222     moduleInfo.ports.assign(portInfoList.begin(), portInfoList.end());
223 }
224 
GetNodeNameAsInt(xmlNode & node)225 NodeName XMLParser::GetNodeNameAsInt(xmlNode &node)
226 {
227     if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("deviceclass"))) {
228         return DEVICE_CLASS;
229     } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("AudioInterruptEnable"))) {
230         return AUDIO_INTERRUPT_ENABLE;
231     } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("UpdateRouteSupport"))) {
232         return UPDATE_ROUTE_SUPPORT;
233     } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("AudioLatency"))) {
234         return AUDIO_LATENCY;
235     } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("SinkLatency"))) {
236         return SINK_LATENCY;
237     } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("VolumeGroupConfig"))) {
238         return VOLUME_GROUP_CONFIG;
239     } else if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("InterruptGroupConfig"))) {
240         return INTERRUPT_GROUP_CONFIG;
241     } else {
242         return UNKNOWN;
243     }
244 }
245 
ParseUpdateRouteSupport(xmlNode & node)246 void XMLParser::ParseUpdateRouteSupport(xmlNode &node)
247 {
248     xmlNode *child = node.children;
249     xmlChar *supportFlag = xmlNodeGetContent(child);
250 
251     if (!xmlStrcmp(supportFlag, reinterpret_cast<const xmlChar*>("true"))) {
252         mPortObserver.OnUpdateRouteSupport(true);
253     } else {
254         mPortObserver.OnUpdateRouteSupport(false);
255     }
256 
257     xmlFree(supportFlag);
258 }
259 
ParseAudioInterrupt(xmlNode & node)260 void XMLParser::ParseAudioInterrupt(xmlNode &node)
261 {
262     xmlNode *child = node.children;
263     xmlChar *enableFlag = xmlNodeGetContent(child);
264 
265     if (!xmlStrcmp(enableFlag, reinterpret_cast<const xmlChar*>("true"))) {
266         mPortObserver.OnAudioInterruptEnable(true);
267     } else {
268         mPortObserver.OnAudioInterruptEnable(false);
269     }
270 
271     xmlFree(enableFlag);
272 }
273 
GetDeviceClassType(const std::string & deviceClass)274 ClassType XMLParser::GetDeviceClassType(const std::string &deviceClass)
275 {
276     if (deviceClass == PRIMARY_CLASS)
277         return ClassType::TYPE_PRIMARY;
278     else if (deviceClass == A2DP_CLASS)
279         return ClassType::TYPE_A2DP;
280     else if (deviceClass == USB_CLASS)
281         return ClassType::TYPE_USB;
282     else if (deviceClass == FILE_CLASS)
283         return ClassType::TYPE_FILE_IO;
284     else
285         return ClassType::TYPE_INVALID;
286 }
287 
ExtractPropertyValue(const std::string & propName,xmlNode & node)288 std::string XMLParser::ExtractPropertyValue(const std::string &propName, xmlNode &node)
289 {
290     std::string propValue = "";
291     xmlChar *tempValue = nullptr;
292 
293     if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
294         tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
295     }
296 
297     if (tempValue != nullptr) {
298         propValue = reinterpret_cast<const char*>(tempValue);
299         xmlFree(tempValue);
300     }
301 
302     return propValue;
303 }
304 
ParseAudioLatency(xmlNode & node)305 void XMLParser::ParseAudioLatency(xmlNode &node)
306 {
307     xmlNode *child = node.children;
308     xmlChar *audioLatency = xmlNodeGetContent(child);
309     std::string sAudioLatency(reinterpret_cast<char *>(audioLatency));
310     mPortObserver.OnAudioLatencyParsed((uint64_t)std::stoi(sAudioLatency));
311 
312     xmlFree(audioLatency);
313 }
314 
ParseSinkLatency(xmlNode & node)315 void XMLParser::ParseSinkLatency(xmlNode &node)
316 {
317     xmlNode *child = node.children;
318     xmlChar *latency = xmlNodeGetContent(child);
319     std::string sLatency(reinterpret_cast<char *>(latency));
320     mPortObserver.OnSinkLatencyParsed((uint64_t)std::stoi(sLatency));
321 
322     xmlFree(latency);
323 }
324 
ParseGroups(xmlNode & node,NodeName type)325 void XMLParser::ParseGroups(xmlNode& node, NodeName type)
326 {
327     xmlNode* groupsNode = nullptr;
328     groupsNode = node.xmlChildrenNode; // get <groups>
329     while (groupsNode != nullptr) {
330         if (groupsNode->type == XML_ELEMENT_NODE) {
331             ParseGroup(*groupsNode, type);
332         }
333         groupsNode = groupsNode->next;
334     }
335 }
336 
ParseGroup(xmlNode & node,NodeName type)337 void XMLParser::ParseGroup(xmlNode& node, NodeName type)
338 {
339     xmlNode* groupNode = nullptr;
340     groupNode = node.xmlChildrenNode;
341 
342     while (groupNode != nullptr) {
343         if (groupNode->type == XML_ELEMENT_NODE) {
344             std::string groupName = ExtractPropertyValue("name", *groupNode);
345             ParseGroupModule(*groupNode, type, groupName);
346         }
347         groupNode = groupNode->next;
348     }
349 }
350 
ParseGroupModule(xmlNode & node,NodeName type,std::string groupName)351 void XMLParser::ParseGroupModule(xmlNode& node, NodeName type, std::string groupName)
352 {
353     xmlNode* moduleNode = nullptr;
354     moduleNode = node.xmlChildrenNode;
355     while (moduleNode != nullptr) {
356         if (moduleNode->type == XML_ELEMENT_NODE) {
357             std::string moduleName = ExtractPropertyValue("name", *moduleNode);
358             if (type == VOLUME_GROUP_CONFIG) {
359                 volumeGroupMap_[moduleName] = groupName;
360             } else if (type == INTERRUPT_GROUP_CONFIG) {
361                 interruptGroupMap_[moduleName] = groupName;
362             }
363         }
364         moduleNode = moduleNode->next;
365     }
366 }
367 } // namespace AudioStandard
368 } // namespace OHOS
369