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
16 #ifndef LOG_TAG
17 #define LOG_TAG "AudioVolume"
18 #endif
19
20 #include "audio_volume.h"
21 #include "audio_volume_c.h"
22 #include "audio_service_log.h"
23 #include "audio_utils.h"
24 #include "audio_stream_info.h"
25 #include "media_monitor_manager.h"
26 #include "event_bean.h"
27
28 namespace OHOS {
29 namespace AudioStandard {
30 static const std::unordered_map<std::string, AudioStreamType> STREAM_TYPE_STRING_ENUM_MAP = {
31 {"voice_call", STREAM_VOICE_CALL},
32 {"voice_call_assistant", STREAM_VOICE_CALL_ASSISTANT},
33 {"music", STREAM_MUSIC},
34 {"ring", STREAM_RING},
35 {"media", STREAM_MEDIA},
36 {"voice_assistant", STREAM_VOICE_ASSISTANT},
37 {"system", STREAM_SYSTEM},
38 {"alarm", STREAM_ALARM},
39 {"notification", STREAM_NOTIFICATION},
40 {"bluetooth_sco", STREAM_BLUETOOTH_SCO},
41 {"enforced_audible", STREAM_ENFORCED_AUDIBLE},
42 {"dtmf", STREAM_DTMF},
43 {"tts", STREAM_TTS},
44 {"accessibility", STREAM_ACCESSIBILITY},
45 {"recording", STREAM_RECORDING},
46 {"movie", STREAM_MOVIE},
47 {"game", STREAM_GAME},
48 {"speech", STREAM_SPEECH},
49 {"system_enforced", STREAM_SYSTEM_ENFORCED},
50 {"ultrasonic", STREAM_ULTRASONIC},
51 {"wakeup", STREAM_WAKEUP},
52 {"voice_message", STREAM_VOICE_MESSAGE},
53 {"navigation", STREAM_NAVIGATION}
54 };
55
GetInstance()56 AudioVolume *AudioVolume::GetInstance()
57 {
58 static AudioVolume instance;
59 return &instance;
60 }
61
AudioVolume()62 AudioVolume::AudioVolume()
63 {
64 AUDIO_INFO_LOG("AudioVolume construct");
65 }
66
~AudioVolume()67 AudioVolume::~AudioVolume()
68 {
69 streamVolume_.clear();
70 systemVolume_.clear();
71 historyVolume_.clear();
72 monitorVolume_.clear();
73 }
74
GetVolume(uint32_t sessionId, int32_t volumeType, const std::string &deviceClass)75 float AudioVolume::GetVolume(uint32_t sessionId, int32_t volumeType, const std::string &deviceClass)
76 {
77 Trace trace("AudioVolume::GetVolume sessionId:" + std::to_string(sessionId));
78 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
79 float volumeStream = 1.0f;
80 auto it = streamVolume_.find(sessionId);
81 if (it != streamVolume_.end()) {
82 volumeStream =
83 it->second.isMuted_ ? 0.0f : it->second.volume_ * it->second.duckFactor_ * it->second.lowPowerFactor_;
84 AUDIO_DEBUG_LOG("stream volume, sessionId:%{public}u, volume:%{public}f, duck:%{public}f, lowPower:%{public}f,"
85 " isMuted:%{public}d, streamVolumeSize:%{public}zu",
86 sessionId, it->second.volume_, it->second.duckFactor_, it->second.lowPowerFactor_, it->second.isMuted_,
87 streamVolume_.size());
88 } else {
89 AUDIO_ERR_LOG("stream volume not exist, sessionId:%{public}u, streamVolumeSize:%{public}zu",
90 sessionId, streamVolume_.size());
91 }
92
93 int32_t volumeLevel = 0;
94 float volumeSystem = 1.0f;
95 std::string key = std::to_string(volumeType) + deviceClass;
96 auto itSV = systemVolume_.find(key);
97 if (itSV != systemVolume_.end()) {
98 volumeLevel = itSV->second.volumeLevel_;
99 volumeSystem = itSV->second.isMuted_ ? 0.0f : itSV->second.volume_;
100 AUDIO_DEBUG_LOG("system volume, volumeType:%{public}d, deviceClass:%{public}s,"
101 " volume:%{public}f, isMuted:%{public}d, systemVolumeSize:%{public}zu",
102 volumeType, deviceClass.c_str(), itSV->second.volume_, itSV->second.isMuted_, systemVolume_.size());
103 } else {
104 AUDIO_ERR_LOG("system volume not exist, volumeType:%{public}d, deviceClass:%{public}s,"
105 " systemVolumeSize:%{public}zu", volumeType, deviceClass.c_str(), systemVolume_.size());
106 }
107 float volumeFloat = volumeStream * volumeSystem;
108 if (monitorVolume_.find(sessionId) != monitorVolume_.end()) {
109 monitorVolume_[sessionId] = {volumeFloat, volumeLevel};
110 }
111 return volumeFloat;
112 }
113
GetHistoryVolume(uint32_t sessionId)114 float AudioVolume::GetHistoryVolume(uint32_t sessionId)
115 {
116 Trace trace("AudioVolume::GetHistoryVolume sessionId:" + std::to_string(sessionId));
117 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
118 auto it = historyVolume_.find(sessionId);
119 if (it != historyVolume_.end()) {
120 return it->second;
121 }
122 return 0.0f;
123 }
124
SetHistoryVolume(uint32_t sessionId, float volume)125 void AudioVolume::SetHistoryVolume(uint32_t sessionId, float volume)
126 {
127 AUDIO_INFO_LOG("history volume, sessionId:%{public}u, volume:%{public}f", sessionId, volume);
128 Trace trace("AudioVolume::SetHistoryVolume sessionId:" + std::to_string(sessionId));
129 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
130 auto it = historyVolume_.find(sessionId);
131 if (it != historyVolume_.end()) {
132 it->second = volume;
133 }
134 }
135
AddStreamVolume(uint32_t sessionId, int32_t streamType, int32_t streamUsage, int32_t uid, int32_t pid)136 void AudioVolume::AddStreamVolume(uint32_t sessionId, int32_t streamType, int32_t streamUsage,
137 int32_t uid, int32_t pid)
138 {
139 AUDIO_INFO_LOG("stream volume, sessionId:%{public}u", sessionId);
140 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
141 auto it = streamVolume_.find(sessionId);
142 if (it == streamVolume_.end()) {
143 streamVolume_.insert(std::make_pair(sessionId, StreamVolume(sessionId, streamType, streamUsage, uid, pid)));
144 historyVolume_.insert(std::make_pair(sessionId, 0.0f));
145 monitorVolume_.insert(std::make_pair(sessionId, std::make_pair(0.0f, 0)));
146 } else {
147 AUDIO_ERR_LOG("stream volume already exist, sessionId:%{public}u", sessionId);
148 }
149 }
150
RemoveStreamVolume(uint32_t sessionId)151 void AudioVolume::RemoveStreamVolume(uint32_t sessionId)
152 {
153 AUDIO_INFO_LOG("stream volume, sessionId:%{public}u", sessionId);
154 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
155 auto it = streamVolume_.find(sessionId);
156 if (it != streamVolume_.end()) {
157 streamVolume_.erase(sessionId);
158 } else {
159 AUDIO_ERR_LOG("stream volume already delete, sessionId:%{public}u", sessionId);
160 }
161 auto itHistory = historyVolume_.find(sessionId);
162 if (itHistory != historyVolume_.end()) {
163 historyVolume_.erase(sessionId);
164 }
165 auto itMonitor = monitorVolume_.find(sessionId);
166 if (itMonitor != monitorVolume_.end()) {
167 monitorVolume_.erase(sessionId);
168 }
169 }
170
SetStreamVolume(uint32_t sessionId, float volume)171 void AudioVolume::SetStreamVolume(uint32_t sessionId, float volume)
172 {
173 AUDIO_INFO_LOG("stream volume, sessionId:%{public}u, volume:%{public}f", sessionId, volume);
174 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
175 auto it = streamVolume_.find(sessionId);
176 if (it != streamVolume_.end()) {
177 it->second.volume_ = volume;
178 } else {
179 AUDIO_ERR_LOG("stream volume not exist, sessionId:%{public}u", sessionId);
180 }
181 }
182
SetStreamVolumeDuckFactor(uint32_t sessionId, float duckFactor)183 void AudioVolume::SetStreamVolumeDuckFactor(uint32_t sessionId, float duckFactor)
184 {
185 AUDIO_INFO_LOG("stream volume, sessionId:%{public}u, duckFactor:%{public}f", sessionId, duckFactor);
186 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
187 auto it = streamVolume_.find(sessionId);
188 if (it != streamVolume_.end()) {
189 it->second.duckFactor_ = duckFactor;
190 } else {
191 AUDIO_ERR_LOG("stream volume not exist, sessionId:%{public}u", sessionId);
192 }
193 }
194
SetStreamVolumeLowPowerFactor(uint32_t sessionId, float lowPowerFactor)195 void AudioVolume::SetStreamVolumeLowPowerFactor(uint32_t sessionId, float lowPowerFactor)
196 {
197 AUDIO_INFO_LOG("stream volume, sessionId:%{public}u, lowPowerFactor:%{public}f", sessionId, lowPowerFactor);
198 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
199 auto it = streamVolume_.find(sessionId);
200 if (it != streamVolume_.end()) {
201 it->second.lowPowerFactor_ = lowPowerFactor;
202 } else {
203 AUDIO_ERR_LOG("stream volume not exist, sessionId:%{public}u", sessionId);
204 }
205 }
206
SetStreamVolumeMute(uint32_t sessionId, bool isMuted)207 void AudioVolume::SetStreamVolumeMute(uint32_t sessionId, bool isMuted)
208 {
209 AUDIO_INFO_LOG("stream volume, sessionId:%{public}u, isMuted:%{public}d", sessionId, isMuted);
210 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
211 auto it = streamVolume_.find(sessionId);
212 if (it != streamVolume_.end()) {
213 it->second.isMuted_ = isMuted;
214 }
215 }
216
SetStreamVolumeFade(uint32_t sessionId, float fadeBegin, float fadeEnd)217 void AudioVolume::SetStreamVolumeFade(uint32_t sessionId, float fadeBegin, float fadeEnd)
218 {
219 AUDIO_INFO_LOG("stream volume, sessionId:%{public}u, fadeBegin:%{public}f, fadeEnd:%{public}f",
220 sessionId, fadeBegin, fadeEnd);
221 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
222 auto it = streamVolume_.find(sessionId);
223 if (it != streamVolume_.end()) {
224 it->second.fadeBegin_ = fadeBegin;
225 it->second.fadeEnd_ = fadeEnd;
226 } else {
227 AUDIO_ERR_LOG("stream volume not exist, sessionId:%{public}u", sessionId);
228 }
229 }
230
GetStreamVolumeFade(uint32_t sessionId)231 std::pair<float, float> AudioVolume::GetStreamVolumeFade(uint32_t sessionId)
232 {
233 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
234 auto it = streamVolume_.find(sessionId);
235 if (it != streamVolume_.end()) {
236 return {it->second.fadeBegin_, it->second.fadeEnd_};
237 } else {
238 AUDIO_ERR_LOG("stream volume not exist, sessionId:%{public}u", sessionId);
239 }
240 return {1.0f, 1.0f};
241 }
242
SetSystemVolume(SystemVolume &systemVolume)243 void AudioVolume::SetSystemVolume(SystemVolume &systemVolume)
244 {
245 auto volumeType = systemVolume.GetVolumeType();
246 auto deviceClass = systemVolume.GetDeviceClass();
247 std::string key = std::to_string(volumeType) + deviceClass;
248 auto it = systemVolume_.find(key);
249 if (it != systemVolume_.end()) {
250 it->second.volume_ = systemVolume.volume_;
251 it->second.volumeLevel_ = systemVolume.volumeLevel_;
252 it->second.isMuted_ = systemVolume.isMuted_;
253 } else {
254 systemVolume_.insert(std::make_pair(key, systemVolume));
255 }
256 AUDIO_INFO_LOG("system volume, volumeType:%{public}d, deviceClass:%{public}s,"
257 " volume:%{public}f, volumeLevel:%{public}d, isMuted:%{public}d, systemVolumeSize:%{public}zu",
258 volumeType, deviceClass.c_str(), systemVolume.volume_, systemVolume.volumeLevel_, systemVolume.isMuted_,
259 systemVolume_.size());
260 }
261
SetSystemVolume(int32_t volumeType, const std::string &deviceClass, float volume, int32_t volumeLevel)262 void AudioVolume::SetSystemVolume(int32_t volumeType, const std::string &deviceClass, float volume, int32_t volumeLevel)
263 {
264 std::string key = std::to_string(volumeType) + deviceClass;
265 auto it = systemVolume_.find(key);
266 if (it != systemVolume_.end()) {
267 it->second.volume_ = volume;
268 it->second.volumeLevel_ = volumeLevel;
269 } else {
270 SystemVolume systemVolume(volumeType, deviceClass);
271 systemVolume.volume_ = volume;
272 systemVolume.volumeLevel_ = volumeLevel;
273 systemVolume_.insert(std::make_pair(key, systemVolume));
274 }
275 AUDIO_INFO_LOG("system volume, volumeType:%{public}d, deviceClass:%{public}s,"
276 " volume:%{public}f, volumeLevel:%{public}d, systemVolumeSize:%{public}zu",
277 volumeType, deviceClass.c_str(), volume, volumeLevel, systemVolume_.size());
278 }
279
SetSystemVolumeMute(int32_t volumeType, const std::string &deviceClass, bool isMuted)280 void AudioVolume::SetSystemVolumeMute(int32_t volumeType, const std::string &deviceClass, bool isMuted)
281 {
282 AUDIO_INFO_LOG("system volume, volumeType:%{public}d, deviceClass:%{public}s, isMuted:%{public}d",
283 volumeType, deviceClass.c_str(), isMuted);
284 std::string key = std::to_string(volumeType) + deviceClass;
285 auto it = systemVolume_.find(key);
286 if (it != systemVolume_.end()) {
287 it->second.isMuted_ = isMuted;
288 } else {
289 SystemVolume systemVolume(volumeType, deviceClass);
290 systemVolume.isMuted_ = isMuted;
291 systemVolume_.insert(std::make_pair(key, systemVolume));
292 }
293 }
294
ConvertStreamTypeStrToInt(const std::string &streamType)295 int32_t AudioVolume::ConvertStreamTypeStrToInt(const std::string &streamType)
296 {
297 AudioStreamType stream = STREAM_MUSIC;
298 if (STREAM_TYPE_STRING_ENUM_MAP.find(streamType) != STREAM_TYPE_STRING_ENUM_MAP.end()) {
299 stream = STREAM_TYPE_STRING_ENUM_MAP.at(streamType);
300 } else {
301 AUDIO_WARNING_LOG("Invalid stream type [%{public}s]. Use default type", streamType.c_str());
302 }
303 return stream;
304 }
305
IsSameVolume(float x, float y)306 bool AudioVolume::IsSameVolume(float x, float y)
307 {
308 return (std::abs((x) - (y)) <= std::abs(FLOAT_EPS));
309 }
310
Dump(std::string &dumpString)311 void AudioVolume::Dump(std::string &dumpString)
312 {
313 AUDIO_INFO_LOG("AudioVolume dump begin");
314 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
315 // dump system volume
316 std::vector<SystemVolume> systemVolumeList;
317 for (auto &systemVolume : systemVolume_) {
318 systemVolumeList.push_back(systemVolume.second);
319 }
320 std::sort(systemVolumeList.begin(), systemVolumeList.end(), [](SystemVolume &a, SystemVolume &b) {
321 return a.GetVolumeType() < b.GetVolumeType();
322 });
323 AppendFormat(dumpString, "\n - audio system volume size: %zu\n", systemVolumeList.size());
324 for (auto &systemVolume : systemVolumeList) {
325 AppendFormat(dumpString, " streamtype: %d ", systemVolume.GetVolumeType());
326 AppendFormat(dumpString, " isMute: %s ", (systemVolume.isMuted_ ? "true" : "false"));
327 AppendFormat(dumpString, " volFloat: %f ", systemVolume.volume_);
328 AppendFormat(dumpString, " volInt: %d ", systemVolume.volumeLevel_);
329 AppendFormat(dumpString, " device class: %s \n", systemVolume.GetDeviceClass().c_str());
330 }
331
332 // dump stream volume
333 std::vector<StreamVolume> streamVolumeList;
334 for (auto &streamVolume : streamVolume_) {
335 streamVolumeList.push_back(streamVolume.second);
336 }
337 std::sort(streamVolumeList.begin(), streamVolumeList.end(), [](StreamVolume &a, StreamVolume &b) {
338 return a.GetSessionId() < b.GetSessionId();
339 });
340 AppendFormat(dumpString, "\n - audio stream volume size: %zu, his volume size: %zu, mon volume size: %zu\n",
341 streamVolumeList.size(), historyVolume_.size(), monitorVolume_.size());
342 for (auto &streamVolume : streamVolumeList) {
343 auto monVol = monitorVolume_.find(streamVolume.GetSessionId());
344 AppendFormat(dumpString, " sessionId: %u ", streamVolume.GetSessionId());
345 AppendFormat(dumpString, " streamType: %d ", streamVolume.GetStreamType());
346 AppendFormat(dumpString, " streamUsage: %d ", streamVolume.GetStreamUsage());
347 AppendFormat(dumpString, " appUid: %d ", streamVolume.GetAppUid());
348 AppendFormat(dumpString, " appPid: %d ", streamVolume.GetAppPid());
349 AppendFormat(dumpString, " volume: %f ", monVol != monitorVolume_.end() ? monVol->second.first : 0.0f);
350 AppendFormat(dumpString, " volumeLevel: %d ", monVol != monitorVolume_.end() ? monVol->second.second : 0);
351 AppendFormat(dumpString, " volFactor: %f ", streamVolume.volume_);
352 AppendFormat(dumpString, " duckFactor: %f ", streamVolume.duckFactor_);
353 AppendFormat(dumpString, " powerFactor: %f ", streamVolume.lowPowerFactor_);
354 AppendFormat(dumpString, " fadeBegin: %f ", streamVolume.fadeBegin_);
355 AppendFormat(dumpString, " fadeEnd: %f \n", streamVolume.fadeEnd_);
356 }
357 }
358
Monitor(uint32_t sessionId, bool isOutput)359 void AudioVolume::Monitor(uint32_t sessionId, bool isOutput)
360 {
361 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
362 auto streamVolume = streamVolume_.find(sessionId);
363 if (streamVolume != streamVolume_.end()) {
364 auto monVol = monitorVolume_.find(sessionId);
365 std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
366 Media::MediaMonitor::AUDIO, Media::MediaMonitor::VOLUME_CHANGE,
367 Media::MediaMonitor::BEHAVIOR_EVENT);
368 bean->Add("ISOUTPUT", isOutput ? 1 : 0);
369 bean->Add("STREAMID", static_cast<int32_t>(sessionId));
370 bean->Add("APP_UID", streamVolume->second.GetAppUid());
371 bean->Add("APP_PID", streamVolume->second.GetAppPid());
372 bean->Add("STREAMTYPE", streamVolume->second.GetStreamType());
373 bean->Add("STREAM_TYPE", streamVolume->second.GetStreamUsage());
374 bean->Add("VOLUME", monVol != monitorVolume_.end() ? monVol->second.first : 0.0f);
375 bean->Add("SYSVOLUME", monVol != monitorVolume_.end() ? monVol->second.second : 0);
376 bean->Add("VOLUMEFACTOR", streamVolume->second.volume_);
377 bean->Add("POWERVOLUMEFACTOR", streamVolume->second.lowPowerFactor_);
378 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
379 } else {
380 AUDIO_ERR_LOG("stream volume not exist, sessionId:%{public}u", sessionId);
381 }
382 }
383 } // namespace AudioStandard
384 } // namespace OHOS
385
386 #ifdef __cplusplus
387 extern "C" {
388 #endif
389 using namespace OHOS::AudioStandard;
390
GetCurVolume(uint32_t sessionId, const char *streamType, const char *deviceClass)391 float GetCurVolume(uint32_t sessionId, const char *streamType, const char *deviceClass)
392 {
393 CHECK_AND_RETURN_RET_LOG(streamType != nullptr, 1.0f, "streamType is nullptr");
394 CHECK_AND_RETURN_RET_LOG(deviceClass != nullptr, 1.0f, "deviceClass is nullptr");
395 int32_t stream = AudioVolume::GetInstance()->ConvertStreamTypeStrToInt(streamType);
396 AudioStreamType volumeType = VolumeUtils::GetVolumeTypeFromStreamType(static_cast<AudioStreamType>(stream));
397 return AudioVolume::GetInstance()->GetVolume(sessionId, volumeType, deviceClass);
398 }
399
GetPreVolume(uint32_t sessionId)400 float GetPreVolume(uint32_t sessionId)
401 {
402 return AudioVolume::GetInstance()->GetHistoryVolume(sessionId);
403 }
404
SetPreVolume(uint32_t sessionId, float volume)405 void SetPreVolume(uint32_t sessionId, float volume)
406 {
407 AudioVolume::GetInstance()->SetHistoryVolume(sessionId, volume);
408 }
409
GetStreamVolumeFade(uint32_t sessionId, float *fadeBegin, float *fadeEnd)410 void GetStreamVolumeFade(uint32_t sessionId, float *fadeBegin, float *fadeEnd)
411 {
412 auto fade = AudioVolume::GetInstance()->GetStreamVolumeFade(sessionId);
413 *fadeBegin = fade.first;
414 *fadeEnd = fade.second;
415 }
416
SetStreamVolumeFade(uint32_t sessionId, float fadeBegin, float fadeEnd)417 void SetStreamVolumeFade(uint32_t sessionId, float fadeBegin, float fadeEnd)
418 {
419 AudioVolume::GetInstance()->SetStreamVolumeFade(sessionId, fadeBegin, fadeEnd);
420 }
421
IsSameVolume(float x, float y)422 bool IsSameVolume(float x, float y)
423 {
424 return AudioVolume::GetInstance()->IsSameVolume(x, y);
425 }
426
MonitorVolume(uint32_t sessionId, bool isOutput)427 void MonitorVolume(uint32_t sessionId, bool isOutput)
428 {
429 AudioVolume::GetInstance()->Monitor(sessionId, isOutput);
430 }
431 #ifdef __cplusplus
432 }
433 #endif