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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioParamParser"
17 #endif
18
19 #include "audio_service_log.h"
20 #include "config/audio_param_parser.h"
21 #ifdef USE_CONFIG_POLICY
22 #include "config_policy_utils.h"
23 #endif
24
25 namespace OHOS {
26 namespace AudioStandard {
AudioParamParser()27 AudioParamParser::AudioParamParser()
28 {
29 AUDIO_DEBUG_LOG("audio extra parameters constructor");
30 }
31
~AudioParamParser()32 AudioParamParser::~AudioParamParser()
33 {
34 AUDIO_DEBUG_LOG("audio extra parameters destructor");
35 }
36
LoadConfiguration(std::unordered_map<std::string,std::unordered_map<std::string,std::set<std::string>>> & audioParameterKeys)37 bool AudioParamParser::LoadConfiguration(
38 std::unordered_map<std::string, std::unordered_map<std::string, std::set<std::string>>> &audioParameterKeys)
39 {
40 AUDIO_INFO_LOG("start LoadConfiguration");
41 xmlDoc *doc = nullptr;
42
43 #ifdef USE_CONFIG_POLICY
44 CfgFiles *cfgFiles = GetCfgFiles(CONFIG_FILE);
45 if (cfgFiles == nullptr) {
46 AUDIO_ERR_LOG("Not found audio_param_config.xml");
47 return false;
48 }
49
50 for (int32_t i = MAX_CFG_POLICY_DIRS_CNT - 1; i >= 0; i--) {
51 if (cfgFiles->paths[i] && *(cfgFiles->paths[i]) != '\0') {
52 AUDIO_INFO_LOG("extra parameter config file path: %{public}s", cfgFiles->paths[i]);
53 doc = xmlReadFile(cfgFiles->paths[i], nullptr, 0);
54 break;
55 }
56 }
57 FreeCfgFiles(cfgFiles);
58 #endif
59
60 if (doc == nullptr) {
61 AUDIO_ERR_LOG("xmlReadFile Failed");
62 return false;
63 }
64
65 xmlNode *root = xmlDocGetRootElement(doc);
66 if (root == nullptr) {
67 AUDIO_ERR_LOG("xmlDocGetRootElement Failed");
68 xmlFreeDoc(doc);
69 return false;
70 }
71
72 if (!ParseInternal(root, audioParameterKeys)) {
73 xmlFreeDoc(doc);
74 return false;
75 }
76
77 xmlFreeDoc(doc);
78 return true;
79 }
80
ParseInternal(xmlNode * node,std::unordered_map<std::string,std::unordered_map<std::string,std::set<std::string>>> & audioParameterKeys)81 bool AudioParamParser::ParseInternal(xmlNode *node,
82 std::unordered_map<std::string, std::unordered_map<std::string, std::set<std::string>>> &audioParameterKeys)
83 {
84 xmlNode *currNode = node;
85 if (currNode == nullptr) {
86 AUDIO_ERR_LOG("parse node is null");
87 return false;
88 }
89
90 for (; currNode; currNode = currNode->next) {
91 if (XML_ELEMENT_NODE == currNode->type &&
92 !xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("mainkeys"))) {
93 ParseMainKeys(currNode, audioParameterKeys);
94 } else {
95 ParseInternal(currNode->xmlChildrenNode, audioParameterKeys);
96 }
97 }
98
99 return true;
100 }
101
ParseMainKeys(xmlNode * node,std::unordered_map<std::string,std::unordered_map<std::string,std::set<std::string>>> & audioParameterKeys)102 void AudioParamParser::ParseMainKeys(xmlNode *node,
103 std::unordered_map<std::string, std::unordered_map<std::string, std::set<std::string>>> &audioParameterKeys)
104 {
105 xmlNode* mainKeysNode = node->xmlChildrenNode;
106 while (mainKeysNode != nullptr) {
107 if (mainKeysNode->type == XML_ELEMENT_NODE) {
108 ParseMainKey(mainKeysNode, audioParameterKeys);
109 }
110 mainKeysNode = mainKeysNode->next;
111 }
112 }
113
ParseMainKey(xmlNode * node,std::unordered_map<std::string,std::unordered_map<std::string,std::set<std::string>>> & audioParameterKeys)114 void AudioParamParser::ParseMainKey(xmlNode *node,
115 std::unordered_map<std::string, std::unordered_map<std::string, std::set<std::string>>> &audioParameterKeys)
116 {
117 std::string mainKeyName = ExtractPropertyValue("name", *node);
118 if (mainKeyName.empty()) {
119 AUDIO_ERR_LOG("No name provided for the main key %{public}s", node->name);
120 return;
121 }
122
123 xmlNode *mainKeyNode = node->xmlChildrenNode;
124 while (mainKeyNode != nullptr) {
125 if (mainKeyNode->type == XML_ELEMENT_NODE) {
126 ParseSubKeys(mainKeyNode, mainKeyName, audioParameterKeys);
127 }
128 mainKeyNode = mainKeyNode->next;
129 }
130 }
131
ParseSubKeys(xmlNode * node,std::string & mainKeyName,std::unordered_map<std::string,std::unordered_map<std::string,std::set<std::string>>> & audioParameterKeys)132 void AudioParamParser::ParseSubKeys(xmlNode *node, std::string &mainKeyName,
133 std::unordered_map<std::string, std::unordered_map<std::string, std::set<std::string>>> &audioParameterKeys)
134 {
135 std::unordered_map<std::string, std::set<std::string>> subKeyMap = {};
136 std::set<std::string> supportedUsage;
137 xmlNode *subKeyNode = node->xmlChildrenNode;
138
139 while (subKeyNode != nullptr) {
140 if (subKeyNode->type == XML_ELEMENT_NODE) {
141 std::string subKeyName = ExtractPropertyValue("name", *subKeyNode);
142 std::regex regexDelimiter(",");
143 std::string usage = ExtractPropertyValue("usage", *subKeyNode);
144 const std::sregex_token_iterator itEnd;
145 for (std::sregex_token_iterator it(usage.begin(), usage.end(), regexDelimiter, -1); it != itEnd; it++) {
146 supportedUsage.insert(it->str());
147 }
148 subKeyMap.emplace(subKeyName, supportedUsage);
149 supportedUsage.clear();
150 }
151 subKeyNode = subKeyNode->next;
152 }
153 audioParameterKeys.emplace(mainKeyName, subKeyMap);
154 }
155
ExtractPropertyValue(const std::string & propName,xmlNode & node)156 std::string AudioParamParser::ExtractPropertyValue(const std::string &propName, xmlNode &node)
157 {
158 std::string propValue = "";
159 xmlChar *tempValue = nullptr;
160
161 if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
162 tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
163 }
164
165 if (tempValue != nullptr) {
166 propValue = reinterpret_cast<const char*>(tempValue);
167 xmlFree(tempValue);
168 }
169
170 return propValue;
171 }
172 } // namespace AudioStandard
173 } // namespace OHOS
174