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