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