1 /*
2 * Copyright (c) 2023 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 #include "audio_volume_parser.h"
16 #ifdef USB_CONFIG_POLICY
17 #include "config_policy_utils.h"
18 #endif
19
20 namespace OHOS {
21 namespace AudioStandard {
AudioVolumeParser()22 AudioVolumeParser::AudioVolumeParser()
23 {
24 AUDIO_INFO_LOG("AudioVolumeParser ctor");
25 audioStreamMap_ = {
26 {"VOICE_CALL", STREAM_VOICE_CALL},
27 {"MUSIC", STREAM_MUSIC},
28 {"RING", STREAM_RING},
29 {"VOICE_ASSISTANT", STREAM_VOICE_ASSISTANT},
30 {"ALARM", STREAM_ALARM},
31 {"ACCESSIBILITY", STREAM_ACCESSIBILITY},
32 {"ULTRASONIC", STREAM_ULTRASONIC},
33 };
34
35 audioDeviceMap_ = {
36 {"earpiece", EARPIECE_VOLUME_TYPE},
37 {"speaker", SPEAKER_VOLUME_TYPE},
38 {"headset", HEADSET_VOLUME_TYPE},
39 };
40 }
41
~AudioVolumeParser()42 AudioVolumeParser::~AudioVolumeParser()
43 {
44 AUDIO_INFO_LOG("AudioVolumeParser dtor");
45 }
46
ParseVolumeConfig(const char * path,StreamVolumeInfoMap & streamVolumeInfoMap)47 int32_t AudioVolumeParser::ParseVolumeConfig(const char *path, StreamVolumeInfoMap &streamVolumeInfoMap)
48 {
49 xmlDoc *doc = nullptr;
50 xmlNode *rootElement = nullptr;
51 if ((doc = xmlReadFile(path, nullptr, 0)) == nullptr) {
52 AUDIO_ERR_LOG("could not parse file %{public}s", path);
53 return ERROR;
54 }
55 rootElement = xmlDocGetRootElement(doc);
56 xmlNode *currNode = rootElement;
57 CHECK_AND_RETURN_RET_LOG(currNode != nullptr, ERROR, "root element is null");
58 if (xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("audio_volume_config"))) {
59 AUDIO_ERR_LOG("Missing tag - audio_volume_config in : %s", path);
60 xmlFreeDoc(doc);
61 xmlCleanupParser();
62 return ERROR;
63 }
64 if (currNode->children) {
65 currNode = currNode->children;
66 } else {
67 AUDIO_ERR_LOG("empty volume config in : %s", path);
68 xmlFreeDoc(doc);
69 xmlCleanupParser();
70 return ERROR;
71 }
72
73 while (currNode != nullptr) {
74 if ((currNode->type == XML_ELEMENT_NODE) &&
75 (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("volume_type")))) {
76 ParseStreamInfos(currNode, streamVolumeInfoMap);
77 break;
78 } else {
79 currNode = currNode->next;
80 }
81 }
82
83 xmlFreeDoc(doc);
84 xmlCleanupParser();
85 return SUCCESS;
86 }
87
LoadConfig(StreamVolumeInfoMap & streamVolumeInfoMap)88 int32_t AudioVolumeParser::LoadConfig(StreamVolumeInfoMap &streamVolumeInfoMap)
89 {
90 AUDIO_INFO_LOG("Load Volume Config xml");
91 int ret = ERROR;
92 #ifdef USB_CONFIG_POLICY
93 CfgFiles *cfgFiles = GetCfgFiles(AUDIO_VOLUME_CONFIG_FILE);
94 if (cfgFiles == nullptr) {
95 AUDIO_ERR_LOG("Not found audio_volume_config.xml!");
96 return ERROR;
97 }
98
99 for (int32_t i = MAX_CFG_POLICY_DIRS_CNT - 1; i >= 0; i--) {
100 if (cfgFiles->paths[i] && *(cfgFiles->paths[i]) != '\0') {
101 AUDIO_INFO_LOG("volume config file path:%{public}s", cfgFiles->paths[i]);
102 ret = ParseVolumeConfig(cfgFiles->paths[i], streamVolumeInfoMap);
103 break;
104 }
105 }
106 FreeCfgFiles(cfgFiles);
107 #else
108 ret = ParseVolumeConfig(AUDIO_VOLUME_CONFIG_FILE, streamVolumeInfoMap);
109 AUDIO_INFO_LOG("use default volume config file path:%{public}s", AUDIO_VOLUME_CONFIG_FILE);
110 #endif
111 return ret;
112 }
113
ParseStreamInfos(xmlNode * node,StreamVolumeInfoMap & streamVolumeInfoMap)114 void AudioVolumeParser::ParseStreamInfos(xmlNode *node, StreamVolumeInfoMap &streamVolumeInfoMap)
115 {
116 xmlNode *currNode = node;
117 AUDIO_DEBUG_LOG("AudioVolumeParser::ParseStreamInfos");
118 while (currNode) {
119 if (currNode->type == XML_ELEMENT_NODE
120 && (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("volume_type")))) {
121 std::shared_ptr<StreamVolumeInfo> streamVolInfo = std::make_shared<StreamVolumeInfo>();
122 ParseStreamVolumeInfoAttr(currNode, streamVolInfo);
123 ParseDeviceVolumeInfos(currNode->children, streamVolInfo);
124 AUDIO_DEBUG_LOG("Parse streamType:%{public}d ", streamVolInfo->streamType);
125 streamVolumeInfoMap[streamVolInfo->streamType] = streamVolInfo;
126 }
127 currNode = currNode->next;
128 }
129 }
130
ParseStreamVolumeInfoAttr(xmlNode * node,std::shared_ptr<StreamVolumeInfo> & streamVolInfo)131 void AudioVolumeParser::ParseStreamVolumeInfoAttr(xmlNode *node, std::shared_ptr<StreamVolumeInfo> &streamVolInfo)
132 {
133 xmlNode *currNode = node;
134 AUDIO_DEBUG_LOG("AudioVolumeParser::ParseStreamVolumeInfoAttr");
135 char *pValue = reinterpret_cast<char*>(xmlGetProp(currNode,
136 reinterpret_cast<xmlChar*>(const_cast<char*>("type"))));
137 streamVolInfo->streamType = audioStreamMap_[pValue];
138 AUDIO_DEBUG_LOG("stream type: %{public}s; currNode->name %{public}s;", pValue, currNode->name);
139 xmlFree(pValue);
140
141 pValue = reinterpret_cast<char*>(xmlGetProp(currNode,
142 reinterpret_cast<xmlChar*>(const_cast<char*>("minidx"))));
143 streamVolInfo->minLevel = atoi(pValue);
144 AUDIO_DEBUG_LOG("minidx: %{public}d", atoi(pValue));
145 xmlFree(pValue);
146
147 pValue = reinterpret_cast<char*>(xmlGetProp(currNode,
148 reinterpret_cast<xmlChar*>(const_cast<char*>("maxidx"))));
149 streamVolInfo->maxLevel = atoi(pValue);
150 AUDIO_DEBUG_LOG("minidx: %{public}d", atoi(pValue));
151 xmlFree(pValue);
152
153 pValue = reinterpret_cast<char*>(xmlGetProp(currNode,
154 reinterpret_cast<xmlChar*>(const_cast<char*>("defaultidx"))));
155 streamVolInfo->defaultLevel = atoi(pValue);
156 AUDIO_DEBUG_LOG("defaultidx: %{public}d", atoi(pValue));
157 xmlFree(pValue);
158 }
159
ParseDeviceVolumeInfos(xmlNode * node,std::shared_ptr<StreamVolumeInfo> & streamVolInfo)160 void AudioVolumeParser::ParseDeviceVolumeInfos(xmlNode *node, std::shared_ptr<StreamVolumeInfo> &streamVolInfo)
161 {
162 xmlNode *currNode = node;
163 AUDIO_DEBUG_LOG("AudioVolumeParser::ParseDeviceVolumeInfos");
164 while (currNode) {
165 if (currNode->type == XML_ELEMENT_NODE
166 && (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("volumecurve")))) {
167 char *pValue = reinterpret_cast<char*>(xmlGetProp(currNode,
168 reinterpret_cast<xmlChar*>(const_cast<char*>("deviceClass"))));
169 std::shared_ptr<DeviceVolumeInfo> deviceVolInfo = std::make_shared<DeviceVolumeInfo>();
170 AUDIO_DEBUG_LOG("deviceClass: %{public}s; currNode->name %{public}s;", pValue, currNode->name);
171 deviceVolInfo->deviceType = audioDeviceMap_[pValue];
172 AUDIO_DEBUG_LOG("deviceVolInfo->deviceType %{public}d;", deviceVolInfo->deviceType);
173 xmlFree(pValue);
174 ParseVolumePoints(currNode->children, deviceVolInfo);
175 streamVolInfo->deviceVolumeInfos[deviceVolInfo->deviceType] = deviceVolInfo;
176 }
177 currNode = currNode->next;
178 }
179 }
180
ParseVolumePoints(xmlNode * node,std::shared_ptr<DeviceVolumeInfo> & deviceVolInfo)181 void AudioVolumeParser::ParseVolumePoints(xmlNode *node, std::shared_ptr<DeviceVolumeInfo> &deviceVolInfo)
182 {
183 xmlNode *currNode = node;
184 AUDIO_DEBUG_LOG("AudioVolumeParser::ParseVolumePoints");
185 while (currNode) {
186 if (currNode->type == XML_ELEMENT_NODE
187 && (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("point")))) {
188 struct VolumePoint volumePoint;
189 char *pValue = reinterpret_cast<char*>(xmlGetProp(currNode,
190 reinterpret_cast<xmlChar*>(const_cast<char*>("idx"))));
191 volumePoint.index = atoi(pValue);
192 AUDIO_DEBUG_LOG("idx: %{public}d", atoi(pValue));
193 xmlFree(pValue);
194 pValue = reinterpret_cast<char*>(xmlGetProp(currNode,
195 reinterpret_cast<xmlChar*>(const_cast<char*>("decibel"))));
196 volumePoint.dbValue = atoi(pValue);
197 AUDIO_DEBUG_LOG("decibel: %{public}d", atoi(pValue));
198 xmlFree(pValue);
199 deviceVolInfo->volumePoints.push_back(volumePoint);
200 }
201 currNode = currNode->next;
202 }
203 }
204 } // namespace AudioStandard
205 } // namespace OHOS
206