• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "audio_utils.h"
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         {"SYSTEM", STREAM_SYSTEM},
40         {"APP", STREAM_APP}
41     };
42 
43     audioDeviceMap_ = {
44         {"earpiece", EARPIECE_VOLUME_TYPE},
45         {"speaker", SPEAKER_VOLUME_TYPE},
46         {"headset", HEADSET_VOLUME_TYPE},
47     };
48 }
49 
~AudioVolumeParser()50 AudioVolumeParser::~AudioVolumeParser()
51 {
52     AUDIO_INFO_LOG("AudioVolumeParser dtor");
53 }
54 
ParseVolumeConfig(const char * path,StreamVolumeInfoMap & streamVolumeInfoMap)55 int32_t AudioVolumeParser::ParseVolumeConfig(const char *path, StreamVolumeInfoMap &streamVolumeInfoMap)
56 {
57     std::shared_ptr<AudioXmlNode> curNode = AudioXmlNode::Create();
58     int32_t ret = curNode->Config(path, nullptr, 0);
59     if (ret != SUCCESS) {
60         WriteVolumeConfigErrorEvent();
61         return ERROR;
62     }
63 
64     if (!curNode->CompareName("audio_volume_config")) {
65         AUDIO_ERR_LOG("Missing tag - audio_volume_config in : %s", path);
66         WriteVolumeConfigErrorEvent();
67         curNode = nullptr;
68         return ERROR;
69     }
70     curNode->MoveToChildren();
71     if (!curNode->IsNodeValid()) {
72         AUDIO_ERR_LOG("empty volume config in : %s", path);
73         WriteVolumeConfigErrorEvent();
74         curNode = nullptr;
75         return ERROR;
76     }
77 
78     while (curNode->IsNodeValid()) {
79         if (curNode->CompareName("volume_type")) {
80             ParseStreamInfos(curNode->GetCopyNode(), streamVolumeInfoMap);
81             break;
82         } else {
83             curNode->MoveToNext();
84         }
85     }
86     curNode = nullptr;
87     int32_t result = UseVoiceAssistantFixedVolumeConfig(streamVolumeInfoMap);
88     AUDIO_INFO_LOG("The voice assistant uses a fixed volume configuration. Result: %{public}d", result);
89     return SUCCESS;
90 }
91 
UseVoiceAssistantFixedVolumeConfig(StreamVolumeInfoMap & streamVolumeInfoMap)92 int32_t AudioVolumeParser::UseVoiceAssistantFixedVolumeConfig(StreamVolumeInfoMap &streamVolumeInfoMap)
93 {
94     if (streamVolumeInfoMap.find(STREAM_VOICE_ASSISTANT) == streamVolumeInfoMap.end() ||
95         streamVolumeInfoMap[STREAM_VOICE_ASSISTANT] == nullptr) {
96         AUDIO_ERR_LOG("Failed to find the volume config of STREAM_VOICE_ASSISTANT!");
97         return ERROR;
98     }
99 
100     // Allow to set voice assistant volume to 0.
101     streamVolumeInfoMap[STREAM_VOICE_ASSISTANT]->minLevel = 0;
102 
103     // Modify the volume point index for volume level 0.
104     const std::vector<DeviceVolumeType> DEVICE_VOLUME_TYPE_LIST = {
105         EARPIECE_VOLUME_TYPE,
106         SPEAKER_VOLUME_TYPE,
107         HEADSET_VOLUME_TYPE,
108     };
109     DeviceVolumeInfoMap &deviceVolumeInfos = streamVolumeInfoMap[STREAM_VOICE_ASSISTANT]->deviceVolumeInfos;
110     for (auto device : DEVICE_VOLUME_TYPE_LIST) {
111         if (deviceVolumeInfos.find(device) == deviceVolumeInfos.end() ||
112             deviceVolumeInfos[device] == nullptr) {
113             AUDIO_ERR_LOG("Failed to find the device %{public}d in deviceVolumeInfos!", device);
114             continue;
115         }
116         deviceVolumeInfos[device]->minLevel = -1; // Ensure that the minLevel of this device is an invalid value.
117         std::vector<VolumePoint> &volumePoints = deviceVolumeInfos[device]->volumePoints;
118         if (volumePoints.empty()) {
119             AUDIO_ERR_LOG("The vector fo volumePoints is empty!");
120             continue;
121         }
122         if (volumePoints[0].index == 0) {
123             volumePoints[0].index = 1;
124         }
125     }
126     return SUCCESS;
127 }
128 
WriteVolumeConfigErrorEvent()129 void AudioVolumeParser::WriteVolumeConfigErrorEvent()
130 {
131     Trace trace("SYSEVENT FAULT EVENT LOAD_CONFIG_ERROR, CATEGORY: "
132         + std::to_string(Media::MediaMonitor::AUDIO_VOLUME_CONFIG));
133     std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
134         Media::MediaMonitor::AUDIO, Media::MediaMonitor::LOAD_CONFIG_ERROR,
135         Media::MediaMonitor::FAULT_EVENT);
136     bean->Add("CATEGORY", Media::MediaMonitor::AUDIO_VOLUME_CONFIG);
137     Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
138 }
139 
LoadConfig(StreamVolumeInfoMap & streamVolumeInfoMap)140 int32_t AudioVolumeParser::LoadConfig(StreamVolumeInfoMap &streamVolumeInfoMap)
141 {
142     AUDIO_INFO_LOG("Load Volume Config xml");
143     int ret = ERROR;
144 #ifdef USE_CONFIG_POLICY
145     CfgFiles *cfgFiles = GetCfgFiles(AUDIO_VOLUME_CONFIG_FILE);
146     if (cfgFiles == nullptr) {
147         Trace trace("SYSEVENT FAULT EVENT LOAD_CONFIG_ERROR, CATEGORY: "
148             + std::to_string(Media::MediaMonitor::AUDIO_VOLUME_CONFIG));
149         AUDIO_ERR_LOG("Not found audio_volume_config.xml!");
150         std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
151             Media::MediaMonitor::AUDIO, Media::MediaMonitor::LOAD_CONFIG_ERROR,
152             Media::MediaMonitor::FAULT_EVENT);
153         bean->Add("CATEGORY", Media::MediaMonitor::AUDIO_VOLUME_CONFIG);
154         Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
155         return ERROR;
156     }
157 
158     for (int32_t i = MAX_CFG_POLICY_DIRS_CNT - 1; i >= 0; i--) {
159         if (cfgFiles->paths[i] && *(cfgFiles->paths[i]) != '\0') {
160             AUDIO_INFO_LOG("volume config file path:%{public}s", cfgFiles->paths[i]);
161             ret = ParseVolumeConfig(cfgFiles->paths[i], streamVolumeInfoMap);
162             break;
163         }
164     }
165     FreeCfgFiles(cfgFiles);
166 #else
167     ret = ParseVolumeConfig(AUDIO_VOLUME_CONFIG_FILE, streamVolumeInfoMap);
168     AUDIO_INFO_LOG("use default volume config file path:%{public}s", AUDIO_VOLUME_CONFIG_FILE);
169 #endif
170     return ret;
171 }
172 
ParseStreamInfos(std::shared_ptr<AudioXmlNode> curNode,StreamVolumeInfoMap & streamVolumeInfoMap)173 void AudioVolumeParser::ParseStreamInfos(std::shared_ptr<AudioXmlNode> curNode,
174     StreamVolumeInfoMap &streamVolumeInfoMap)
175 {
176     AUDIO_DEBUG_LOG("AudioVolumeParser::ParseStreamInfos");
177     while (curNode->IsNodeValid()) {
178         if (curNode->CompareName("volume_type")) {
179             std::shared_ptr<StreamVolumeInfo> streamVolInfo = std::make_shared<StreamVolumeInfo>();
180             if (ParseStreamVolumeInfoAttr(curNode->GetCopyNode(), streamVolInfo) == AUDIO_OK) {
181                 ParseDeviceVolumeInfos(curNode->GetChildrenNode(), streamVolInfo);
182                 AUDIO_DEBUG_LOG("Parse streamType:%{public}d ", streamVolInfo->streamType);
183                 streamVolumeInfoMap[streamVolInfo->streamType] = streamVolInfo;
184             }
185         }
186         curNode->MoveToNext();
187     }
188 }
189 
ParseStreamVolumeInfoAttr(std::shared_ptr<AudioXmlNode> curNode,std::shared_ptr<StreamVolumeInfo> & streamVolInfo)190 int32_t AudioVolumeParser::ParseStreamVolumeInfoAttr(std::shared_ptr<AudioXmlNode> curNode,
191     std::shared_ptr<StreamVolumeInfo> &streamVolInfo)
192 {
193     AUDIO_DEBUG_LOG("AudioVolumeParser::ParseStreamVolumeInfoAttr");
194     std::string pValueStr;
195     CHECK_AND_RETURN_RET_LOG(curNode->GetProp("type", pValueStr) == SUCCESS,
196         ERR_INVALID_PARAM, "invalid type parameter");
197 
198     if (pValueStr == "VOICE_PC") {
199         VolumeUtils::SetPCVolumeEnable(true);
200         AUDIO_INFO_LOG("PC Volume is Enable");
201         // only read PC volume flag
202         return ERR_NOT_SUPPORTED;
203     }
204     streamVolInfo->streamType = audioStreamMap_[pValueStr];
205 
206     CHECK_AND_RETURN_RET_LOG(curNode->GetProp("minidx", pValueStr) == SUCCESS,
207         ERR_INVALID_PARAM, "invalid minidx parameter");
208     CHECK_AND_RETURN_RET_LOG(StringConverter<int32_t>(pValueStr, streamVolInfo->minLevel), ERROR,
209         "convert streamVolInfo->minLevel fail!");
210     AUDIO_DEBUG_LOG("minidx: %{public}d", streamVolInfo->minLevel);
211 
212     CHECK_AND_RETURN_RET_LOG(curNode->GetProp("maxidx", pValueStr) == SUCCESS,
213         ERR_INVALID_PARAM, "invalid maxidx parameter");
214     CHECK_AND_RETURN_RET_LOG(StringConverter<int32_t>(pValueStr, streamVolInfo->maxLevel), ERROR,
215         "convert streamVolInfo->maxLevel fail!");
216     AUDIO_DEBUG_LOG("maxidx: %{public}d", streamVolInfo->maxLevel);
217 
218     CHECK_AND_RETURN_RET_LOG(curNode->GetProp("defaultidx", pValueStr) == SUCCESS,
219         ERR_INVALID_PARAM, "invalid defaultidx parameter");
220     CHECK_AND_RETURN_RET_LOG(StringConverter<int32_t>(pValueStr, streamVolInfo->defaultLevel), ERROR,
221         "convert streamVolInfo->defaultLevel fail!");
222     AUDIO_DEBUG_LOG("defaultidx: %{public}d", streamVolInfo->defaultLevel);
223 
224     return AUDIO_OK;
225 }
226 
ParseDeviceVolumeInfos(std::shared_ptr<AudioXmlNode> curNode,std::shared_ptr<StreamVolumeInfo> & streamVolInfo)227 void AudioVolumeParser::ParseDeviceVolumeInfos(std::shared_ptr<AudioXmlNode> curNode,
228     std::shared_ptr<StreamVolumeInfo> &streamVolInfo)
229 {
230     AUDIO_DEBUG_LOG("AudioVolumeParser::ParseDeviceVolumeInfos");
231     while (curNode->IsNodeValid()) {
232         if (curNode->CompareName("volumecurve")) {
233             std::string pValueStr;
234             curNode->GetProp("deviceClass", pValueStr);
235             std::shared_ptr<DeviceVolumeInfo> deviceVolInfo = std::make_shared<DeviceVolumeInfo>();
236             deviceVolInfo->deviceType = audioDeviceMap_[pValueStr];
237             AUDIO_DEBUG_LOG("deviceVolInfo->deviceType %{public}d;", deviceVolInfo->deviceType);
238             int32_t result = curNode->GetProp("minidx", pValueStr);
239             if (result == SUCCESS) {
240                 StringConverter<int32_t>(pValueStr, deviceVolInfo->minLevel);
241                 AUDIO_DEBUG_LOG("minidx: %{public}d", deviceVolInfo->minLevel);
242             } else {
243                 AUDIO_DEBUG_LOG("The minidx attribute is not configured or minidx parameter is invalid");
244             }
245             result = curNode->GetProp("maxidx", pValueStr);
246             if (result == SUCCESS) {
247                 StringConverter<int32_t>(pValueStr, deviceVolInfo->maxLevel);
248                 AUDIO_DEBUG_LOG("maxidx: %{public}d", deviceVolInfo->maxLevel);
249             } else {
250                 AUDIO_DEBUG_LOG("The maxidx attribute is not configured or maxidx parameter is invalid");
251             }
252             result = curNode->GetProp("defaultidx", pValueStr);
253             if (result == SUCCESS) {
254                 StringConverter<int32_t>(pValueStr, deviceVolInfo->defaultLevel);
255                 AUDIO_DEBUG_LOG("defaultidx: %{public}d", deviceVolInfo->defaultLevel);
256             } else {
257                 AUDIO_DEBUG_LOG("The defaultidx attribute is not configured or defaultidx parameter is invalid");
258             }
259             ParseVolumePoints(curNode->GetChildrenNode(), deviceVolInfo);
260             streamVolInfo->deviceVolumeInfos[deviceVolInfo->deviceType] = deviceVolInfo;
261         }
262         curNode->MoveToNext();
263     }
264 }
265 
ParseVolumePoints(std::shared_ptr<AudioXmlNode> curNode,std::shared_ptr<DeviceVolumeInfo> & deviceVolInfo)266 void AudioVolumeParser::ParseVolumePoints(std::shared_ptr<AudioXmlNode> curNode,
267     std::shared_ptr<DeviceVolumeInfo> &deviceVolInfo)
268 {
269     AUDIO_DEBUG_LOG("AudioVolumeParser::ParseVolumePoints");
270     while (curNode->IsNodeValid()) {
271         if (curNode->CompareName("point")) {
272             struct VolumePoint volumePoint;
273             std::string pValueStr;
274             curNode->GetProp("idx", pValueStr);
275             CHECK_AND_RETURN_LOG(StringConverter(pValueStr, volumePoint.index),
276                 "convert volumePoint.index fail!");
277             AUDIO_DEBUG_LOG("idx: %{public}d", volumePoint.index);
278 
279             curNode->GetProp("decibel", pValueStr);
280             CHECK_AND_RETURN_LOG(StringConverter(pValueStr, volumePoint.dbValue),
281                 "convert volumePoint.dbValue fail!");
282             AUDIO_DEBUG_LOG("decibel: %{public}d", volumePoint.dbValue);
283 
284             deviceVolInfo->volumePoints.push_back(volumePoint);
285         }
286         curNode->MoveToNext();
287     }
288 }
289 } // namespace AudioStandard
290 } // namespace OHOS
291