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