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 <numeric>
21 #include "audio_volume.h"
22 #include "audio_common_log.h"
23 #include "audio_utils.h"
24 #include "audio_utils_c.h"
25 #include "audio_stream_info.h"
26 #include "media_monitor_manager.h"
27 #include "audio_stream_monitor.h"
28
29 namespace OHOS {
30 namespace AudioStandard {
31 static const std::unordered_map<std::string, AudioStreamType> STREAM_TYPE_STRING_ENUM_MAP = {
32 {"voice_call", STREAM_VOICE_CALL},
33 {"voice_call_assistant", STREAM_VOICE_CALL_ASSISTANT},
34 {"music", STREAM_MUSIC},
35 {"ring", STREAM_RING},
36 {"media", STREAM_MEDIA},
37 {"voice_assistant", STREAM_VOICE_ASSISTANT},
38 {"system", STREAM_SYSTEM},
39 {"alarm", STREAM_ALARM},
40 {"notification", STREAM_NOTIFICATION},
41 {"bluetooth_sco", STREAM_BLUETOOTH_SCO},
42 {"enforced_audible", STREAM_ENFORCED_AUDIBLE},
43 {"dtmf", STREAM_DTMF},
44 {"tts", STREAM_TTS},
45 {"accessibility", STREAM_ACCESSIBILITY},
46 {"recording", STREAM_RECORDING},
47 {"movie", STREAM_MOVIE},
48 {"game", STREAM_GAME},
49 {"speech", STREAM_SPEECH},
50 {"system_enforced", STREAM_SYSTEM_ENFORCED},
51 {"ultrasonic", STREAM_ULTRASONIC},
52 {"wakeup", STREAM_WAKEUP},
53 {"voice_message", STREAM_VOICE_MESSAGE},
54 {"navigation", STREAM_NAVIGATION}
55 };
56
57 uint64_t DURATION_TIME_DEFAULT = 40;
58 uint64_t DURATION_TIME_SHORT = 10;
59 static const float DEFAULT_APP_VOLUME = 1.0f;
60 uint32_t VOIP_CALL_VOICE_SERVICE = 5523;
61 uint32_t DISTURB_STATE_VOLUME_MUTE = 0;
62 uint32_t DISTURB_STATE_VOLUME_UNMUTE = 1;
63
GetInstance()64 AudioVolume *AudioVolume::GetInstance()
65 {
66 static AudioVolume instance;
67 return &instance;
68 }
69
AudioVolume()70 AudioVolume::AudioVolume()
71 {
72 AUDIO_INFO_LOG("AudioVolume construct");
73 }
74
~AudioVolume()75 AudioVolume::~AudioVolume()
76 {
77 appVolume_.clear();
78 streamVolume_.clear();
79 systemVolume_.clear();
80 doNotDisturbStatusWhiteListVolume_.clear();
81 }
82
83 // Note: Time-consuming logic operations cannot be performed on GetVolume.
GetVolume(uint32_t sessionId,int32_t streamType,const std::string & deviceClass,VolumeValues * volumes)84 float AudioVolume::GetVolume(uint32_t sessionId, int32_t streamType, const std::string &deviceClass,
85 VolumeValues *volumes)
86 {
87 Trace trace("AudioVolume::GetVolume");
88 // read or write volume must be called AudioVolume::volumeMutex_
89 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
90 AudioVolumeType volumeType = VolumeUtils::GetVolumeTypeFromStreamType(static_cast<AudioStreamType>(streamType));
91 int32_t volumeLevel = 0;
92 int32_t appUid = -1;
93 volumes->volumeStream = 1.0f;
94 auto it = streamVolume_.find(sessionId);
95 if (it != streamVolume_.end()) {
96 volumes->volumeStream = it->second.totalVolume_;
97 volumes->volumeHistory = it->second.historyVolume_;
98 volumes->volumeApp = it->second.appVolume_;
99 appUid = it->second.GetAppUid();
100 if (volumeType == STREAM_VOICE_ASSISTANT && !it->second.IsSystemApp()) {
101 volumeType = STREAM_MUSIC;
102 }
103 } else {
104 AUDIO_ERR_LOG("stream volume not exist, sessionId:%{public}u", sessionId);
105 }
106 volumes->volumeSystem = 1.0f;
107 std::string key = std::to_string(volumeType) + deviceClass;
108 auto itSV = systemVolume_.find(key);
109 if (itSV != systemVolume_.end()) {
110 volumes->volumeSystem = itSV->second.totalVolume_;
111 volumeLevel = itSV->second.volumeLevel_;
112 if ((streamType == STREAM_VOICE_CALL || streamType == STREAM_VOICE_COMMUNICATION) &&
113 IsVgsVolumeSupported() && volumes->volumeSystem > 0.0f) {
114 volumes->volumeSystem = 1.0f;
115 }
116 } else {
117 AUDIO_ERR_LOG("no system volume, volumeType:%{public}d deviceClass%{public}s", volumeType, deviceClass.c_str());
118 }
119 float sysVolume = volumes->volumeSystem;
120 if (it != streamVolume_.end() && it->second.IsVirtualKeyboard() && itSV != systemVolume_.end()) {
121 sysVolume = itSV->second.isMuted_ ? 0.0f : 1.0f;
122 }
123 int32_t doNotDisturbStatusVolume = static_cast<int32_t>(GetDoNotDisturbStatusVolume(streamType, appUid, sessionId));
124 volumes->volume = sysVolume * volumes->volumeStream * doNotDisturbStatusVolume;
125 if (it != streamVolume_.end() && !IsSameVolume(it->second.monitorVolume_, volumes->volume)) {
126 it->second.monitorVolume_ = volumes->volume;
127 it->second.monitorVolumeLevel_ = volumeLevel;
128 AUDIO_INFO_LOG("volume,sessionId:%{public}u,volume:%{public}f,volumeType:%{public}d,devClass:%{public}s,"
129 "volumeSystem:%{public}f,volumeStream:%{public}f,volumeApp:%{public}f,isVKB:%{public}d,isMuted:%{public}s,"
130 "doNotDisturbStatusVolume:%{public}d,", sessionId, volumes->volume, volumeType, deviceClass.c_str(),
131 volumes->volumeSystem, volumes->volumeStream, volumes->volumeApp, it->second.IsVirtualKeyboard(),
132 itSV != systemVolume_.end() ? (itSV->second.isMuted_ ? "T" : "F") : "null", doNotDisturbStatusVolume);
133 }
134 AudioStreamMonitor::GetInstance().UpdateMonitorVolume(sessionId, volumes->volume);
135 return volumes->volume;
136 }
137
GetDoNotDisturbStatusVolume(int32_t volumeType,int32_t appUid,uint32_t sessionId)138 uint32_t AudioVolume::GetDoNotDisturbStatusVolume(int32_t volumeType, int32_t appUid, uint32_t sessionId)
139 {
140 if (!isDoNotDisturbStatus_) {
141 return DISTURB_STATE_VOLUME_UNMUTE;
142 }
143 if (volumeType == STREAM_SYSTEM || volumeType == STREAM_DTMF) {
144 return DISTURB_STATE_VOLUME_MUTE;
145 }
146 auto it = streamVolume_.find(sessionId);
147 CHECK_AND_RETURN_RET_LOG(it != streamVolume_.end(), DISTURB_STATE_VOLUME_UNMUTE, "sessionId is null");
148 if (it->second.IsSystemApp() || static_cast<uint32_t>(appUid) == VOIP_CALL_VOICE_SERVICE) {
149 return DISTURB_STATE_VOLUME_UNMUTE;
150 }
151 AudioStreamType volumeMapType = VolumeUtils::GetVolumeTypeFromStreamType(static_cast<AudioStreamType>(volumeType));
152 if (doNotDisturbStatusWhiteListVolume_[static_cast<uint32_t>(appUid)] == 1) {
153 // this stream of app is in whiteList, unMute
154 return DISTURB_STATE_VOLUME_UNMUTE;
155 } else {
156 // this stream is STREAM_RING, mute
157 if (volumeMapType != STREAM_RING) {
158 return DISTURB_STATE_VOLUME_UNMUTE;
159 } else {
160 return DISTURB_STATE_VOLUME_MUTE;
161 }
162 }
163 }
164
SetDoNotDisturbStatusWhiteListVolume(std::vector<std::map<std::string,std::string>> doNotDisturbStatusWhiteList)165 void AudioVolume::SetDoNotDisturbStatusWhiteListVolume(std::vector<std::map<std::string, std::string>>
166 doNotDisturbStatusWhiteList)
167 {
168 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
169 doNotDisturbStatusWhiteListVolume_.clear();
170 for (const auto& obj : doNotDisturbStatusWhiteList) {
171 for (const auto& [key, val] : obj) {
172 doNotDisturbStatusWhiteListVolume_[atoi(key.c_str())] = 1;
173 }
174 }
175 }
176
SetDoNotDisturbStatus(bool isDoNotDisturb)177 void AudioVolume::SetDoNotDisturbStatus(bool isDoNotDisturb)
178 {
179 isDoNotDisturbStatus_ = isDoNotDisturb;
180 }
181
GetStreamVolume(uint32_t sessionId)182 float AudioVolume::GetStreamVolume(uint32_t sessionId)
183 {
184 Trace trace("AudioVolume::GetStreamVolume");
185 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
186 float volumeStream = 1.0f;
187 auto it = streamVolume_.find(sessionId);
188 if (it != streamVolume_.end()) {
189 // only stream volume factor
190 volumeStream =
191 it->second.isMuted_ ? 0.0f : it->second.volume_ * it->second.duckFactor_ * it->second.lowPowerFactor_;
192 } else {
193 AUDIO_ERR_LOG("stream volume not exist, sessionId:%{public}u", sessionId);
194 }
195 if (it != streamVolume_.end() && !IsSameVolume(it->second.monitorVolume_, volumeStream)) {
196 it->second.monitorVolume_ = volumeStream;
197 AUDIO_INFO_LOG("volume, sessionId:%{public}u, stream volume:%{public}f", sessionId, volumeStream);
198 }
199 return volumeStream;
200 }
201
GetHistoryVolume(uint32_t sessionId)202 float AudioVolume::GetHistoryVolume(uint32_t sessionId)
203 {
204 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
205 auto it = streamVolume_.find(sessionId);
206 if (it != streamVolume_.end()) {
207 return it->second.historyVolume_;
208 }
209 return 0.0f;
210 }
211
SetHistoryVolume(uint32_t sessionId,float volume)212 void AudioVolume::SetHistoryVolume(uint32_t sessionId, float volume)
213 {
214 AUDIO_INFO_LOG("history volume, sessionId:%{public}u, volume:%{public}f", sessionId, volume);
215 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
216 auto it = streamVolume_.find(sessionId);
217 if (it != streamVolume_.end()) {
218 it->second.historyVolume_ = volume;
219 }
220 }
221
AddStreamVolume(StreamVolumeParams & streamVolumeParams)222 void AudioVolume::AddStreamVolume(StreamVolumeParams &streamVolumeParams)
223 {
224 AUDIO_INFO_LOG("stream volume, sessionId:%{public}u", streamVolumeParams.sessionId);
225 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
226 auto it = streamVolume_.find(streamVolumeParams.sessionId);
227 if (it == streamVolume_.end()) {
228 streamVolume_.emplace(streamVolumeParams.sessionId,
229 StreamVolume(streamVolumeParams.sessionId, streamVolumeParams.streamType, streamVolumeParams.streamUsage,
230 streamVolumeParams.uid, streamVolumeParams.pid, streamVolumeParams.isSystemApp, streamVolumeParams.mode,
231 streamVolumeParams.isVKB));
232 } else {
233 AUDIO_ERR_LOG("stream volume already exist, sessionId:%{public}u", streamVolumeParams.sessionId);
234 }
235 }
236
RemoveStreamVolume(uint32_t sessionId)237 void AudioVolume::RemoveStreamVolume(uint32_t sessionId)
238 {
239 AUDIO_INFO_LOG("stream volume, sessionId:%{public}u", sessionId);
240 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
241 auto it = streamVolume_.find(sessionId);
242 if (it != streamVolume_.end()) {
243 streamVolume_.erase(sessionId);
244 } else {
245 AUDIO_ERR_LOG("stream volume already delete, sessionId:%{public}u", sessionId);
246 }
247 }
248
SetStreamVolume(uint32_t sessionId,float volume)249 void AudioVolume::SetStreamVolume(uint32_t sessionId, float volume)
250 {
251 AUDIO_INFO_LOG("stream volume, sessionId:%{public}u, volume:%{public}f", sessionId, volume);
252 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
253 auto it = streamVolume_.find(sessionId);
254 if (it != streamVolume_.end()) {
255 it->second.volume_ = volume;
256 it->second.appVolume_ = GetAppVolumeInternal(it->second.GetAppUid(), it->second.GetVolumeMode());
257 it->second.totalVolume_ = it->second.isMuted_ ? 0.0f :
258 it->second.volume_ * it->second.duckFactor_ * it->second.lowPowerFactor_ * it->second.appVolume_;
259 } else {
260 AUDIO_ERR_LOG("stream volume not exist, sessionId:%{public}u", sessionId);
261 }
262 }
263
SetStreamVolumeDuckFactor(uint32_t sessionId,float duckFactor)264 void AudioVolume::SetStreamVolumeDuckFactor(uint32_t sessionId, float duckFactor)
265 {
266 AUDIO_INFO_LOG("stream volume, sessionId:%{public}u, duckFactor:%{public}f", sessionId, duckFactor);
267 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
268 auto it = streamVolume_.find(sessionId);
269 if (it != streamVolume_.end()) {
270 it->second.duckFactor_ = duckFactor;
271 it->second.appVolume_ = GetAppVolumeInternal(it->second.GetAppUid(), it->second.GetVolumeMode());
272 it->second.totalVolume_ = it->second.isMuted_ ? 0.0f :
273 it->second.volume_ * it->second.duckFactor_ * it->second.lowPowerFactor_ * it->second.appVolume_;
274 } else {
275 AUDIO_ERR_LOG("stream volume not exist, sessionId:%{public}u", sessionId);
276 }
277 }
278
SetStreamVolumeLowPowerFactor(uint32_t sessionId,float lowPowerFactor)279 void AudioVolume::SetStreamVolumeLowPowerFactor(uint32_t sessionId, float lowPowerFactor)
280 {
281 AUDIO_INFO_LOG("stream volume, sessionId:%{public}u, lowPowerFactor:%{public}f", sessionId, lowPowerFactor);
282 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
283 auto it = streamVolume_.find(sessionId);
284 if (it != streamVolume_.end()) {
285 it->second.lowPowerFactor_ = lowPowerFactor;
286 it->second.appVolume_ = GetAppVolumeInternal(it->second.GetAppUid(), it->second.GetVolumeMode());
287 it->second.totalVolume_ = it->second.isMuted_ ? 0.0f :
288 it->second.volume_ * it->second.duckFactor_ * it->second.lowPowerFactor_ * it->second.appVolume_;
289 } else {
290 AUDIO_ERR_LOG("stream volume not exist, sessionId:%{public}u", sessionId);
291 }
292 }
293
SaveAdjustStreamVolumeInfo(float volume,uint32_t sessionId,std::string invocationTime,uint32_t code)294 void AudioVolume::SaveAdjustStreamVolumeInfo(float volume, uint32_t sessionId, std::string invocationTime,
295 uint32_t code)
296 {
297 AdjustStreamVolumeInfo adjustStreamVolumeInfo;
298 adjustStreamVolumeInfo.volume = volume;
299 adjustStreamVolumeInfo.sessionId = sessionId;
300 adjustStreamVolumeInfo.invocationTime = invocationTime;
301 switch (code) {
302 case static_cast<uint32_t>(AdjustStreamVolume::STREAM_VOLUME_INFO):
303 setStreamVolumeInfo_->Add(adjustStreamVolumeInfo);
304 break;
305 case static_cast<uint32_t>(AdjustStreamVolume::LOW_POWER_VOLUME_INFO):
306 setLowPowerVolumeInfo_->Add(adjustStreamVolumeInfo);
307 break;
308 case static_cast<uint32_t>(AdjustStreamVolume::DUCK_VOLUME_INFO):
309 setDuckVolumeInfo_->Add(adjustStreamVolumeInfo);
310 break;
311 default:
312 break;
313 }
314 }
315
GetStreamVolumeInfo(AdjustStreamVolume volumeType)316 std::vector<AdjustStreamVolumeInfo> AudioVolume::GetStreamVolumeInfo(AdjustStreamVolume volumeType)
317 {
318 switch (volumeType) {
319 case AdjustStreamVolume::STREAM_VOLUME_INFO:
320 return setStreamVolumeInfo_->GetData();
321 case AdjustStreamVolume::LOW_POWER_VOLUME_INFO:
322 return setLowPowerVolumeInfo_->GetData();
323 case AdjustStreamVolume::DUCK_VOLUME_INFO:
324 return setDuckVolumeInfo_->GetData();
325 default:
326 return {};
327 }
328 }
329
SetStreamVolumeMute(uint32_t sessionId,bool isMuted)330 void AudioVolume::SetStreamVolumeMute(uint32_t sessionId, bool isMuted)
331 {
332 AUDIO_INFO_LOG("stream volume, sessionId:%{public}u, isMuted:%{public}d", sessionId, isMuted);
333 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
334 auto it = streamVolume_.find(sessionId);
335 if (it != streamVolume_.end()) {
336 it->second.isMuted_ = isMuted;
337 it->second.appVolume_ = GetAppVolumeInternal(it->second.GetAppUid(), it->second.GetVolumeMode());
338 it->second.totalVolume_ = it->second.isMuted_ ? 0.0f :
339 it->second.volume_ * it->second.duckFactor_ * it->second.lowPowerFactor_ * it->second.appVolume_;
340 }
341 }
342
GetAppVolume(int32_t appUid,AudioVolumeMode mode)343 float AudioVolume::GetAppVolume(int32_t appUid, AudioVolumeMode mode)
344 {
345 AUDIO_DEBUG_LOG("Get app volume, appUid = %{public}d, mode = %{public}d", appUid, mode);
346 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
347 float appVolume = GetAppVolumeInternal(appUid, mode);
348 AUDIO_DEBUG_LOG("appVolume = %{public}f", appVolume);
349 return appVolume;
350 }
351
GetAppVolumeInternal(int32_t appUid,AudioVolumeMode mode)352 inline float AudioVolume::GetAppVolumeInternal(int32_t appUid, AudioVolumeMode mode)
353 {
354 float appVolume = 1.0f;
355 auto iter = appVolume_.find(appUid);
356 if (iter != appVolume_.end()) {
357 appVolume = iter->second.isMuted_ ? iter->second.totalVolume_ :
358 (mode == AUDIOSTREAM_VOLUMEMODE_SYSTEM_GLOBAL ? 1.0 : iter->second.totalVolume_);
359 }
360 return appVolume;
361 }
362
SetAppVolumeMute(int32_t appUid,bool isMuted)363 void AudioVolume::SetAppVolumeMute(int32_t appUid, bool isMuted)
364 {
365 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
366 float totalAppVolume = 1.0f;
367 auto it = appVolume_.find(appUid);
368 if (it != appVolume_.end()) {
369 it->second.isMuted_ = isMuted;
370 it->second.totalVolume_ = it->second.isMuted_ ? 0.0f : it->second.volume_;
371 totalAppVolume = it->second.totalVolume_;
372 } else {
373 AppVolume appVolume(appUid, DEFAULT_APP_VOLUME, defaultAppVolume_, isMuted);
374 appVolume.totalVolume_ = isMuted ? 0.0f : appVolume.volume_;
375 totalAppVolume = appVolume.totalVolume_;
376 appVolume_.emplace(appUid, appVolume);
377 }
378
379 AUDIO_INFO_LOG("set volume mute, appUId:%{public}d, isMuted:%{public}d, systemVolumeSize:%{public}zu",
380 appUid, isMuted, appVolume_.size());
381 for (auto &streamVolume : streamVolume_) {
382 auto &stream = streamVolume.second;
383 if (stream.GetAppUid() == appUid) {
384 stream.appVolume_ = isMuted ? totalAppVolume :
385 (stream.GetVolumeMode() == AUDIOSTREAM_VOLUMEMODE_SYSTEM_GLOBAL ? 1.0 : totalAppVolume);
386 stream.totalVolume_ = stream.isMuted_ ? 0.0f :
387 stream.volume_ * stream.duckFactor_ * stream.lowPowerFactor_ * stream.appVolume_;
388 }
389 }
390 }
391
SetAppRingMuted(int32_t appUid,bool isMuted)392 bool AudioVolume::SetAppRingMuted(int32_t appUid, bool isMuted)
393 {
394 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
395 float totalAppVolume = 1.0f;
396 auto it = appVolume_.find(appUid);
397 if (it != appVolume_.end()) {
398 it->second.totalVolume_ = it->second.isMuted_ ? 0.0f : it->second.volume_;
399 totalAppVolume = it->second.totalVolume_;
400 } else {
401 AppVolume appVolume(appUid, DEFAULT_APP_VOLUME, defaultAppVolume_, false);
402 appVolume.totalVolume_ = appVolume.volume_;
403 totalAppVolume = appVolume.totalVolume_;
404 appVolume_.emplace(appUid, appVolume);
405 }
406
407 AUDIO_INFO_LOG("appUid:%{public}d, isMuted:%{public}d", appUid, isMuted);
408 for (auto &streamVolume : streamVolume_) {
409 auto &stream = streamVolume.second;
410 AUDIO_INFO_LOG("appUid: %{public}d, streamType: %{public}d", stream.GetAppUid(), stream.GetStreamType());
411 if (stream.GetAppUid() == appUid && stream.GetStreamType() == static_cast<int32_t>(STREAM_RING)) {
412 bool isRingMuted = stream.isMuted_ || isMuted;
413 stream.appVolume_ = totalAppVolume;
414 stream.totalVolume_ = isRingMuted ? 0.0f :
415 stream.volume_ * stream.duckFactor_ * stream.lowPowerFactor_ * stream.appVolume_;
416 AUDIO_INFO_LOG("stream total volume: %{public}f", stream.totalVolume_);
417 return true;
418 }
419 }
420 return false;
421 }
422
SetAppVolume(AppVolume & appVolume)423 void AudioVolume::SetAppVolume(AppVolume &appVolume)
424 {
425 int32_t appUid = appVolume.GetAppUid();
426 appVolume.totalVolume_ = appVolume.isMuted_ ? 0.0f : appVolume.volume_;
427 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
428 auto it = appVolume_.find(appUid);
429 if (it != appVolume_.end()) {
430 it->second.volume_ = appVolume.volume_;
431 it->second.volumeLevel_ = appVolume.volumeLevel_;
432 it->second.isMuted_ = appVolume.isMuted_;
433 it->second.totalVolume_ = appVolume.totalVolume_;
434 } else {
435 appVolume_.emplace(appUid, appVolume);
436 }
437
438 AUDIO_INFO_LOG("system volume, appUId:%{public}d, "
439 " volume:%{public}f, volumeLevel:%{public}d, isMuted:%{public}d, systemVolumeSize:%{public}zu",
440 appUid, appVolume.volume_, appVolume.volumeLevel_, appVolume.isMuted_,
441 appVolume_.size());
442 for (auto &streamVolume : streamVolume_) {
443 auto &stream = streamVolume.second;
444 if (stream.GetAppUid() == appUid) {
445 stream.appVolume_ = appVolume.isMuted_ ? appVolume.totalVolume_ :
446 (stream.GetVolumeMode() == AUDIOSTREAM_VOLUMEMODE_SYSTEM_GLOBAL ? 1.0 : appVolume.totalVolume_);
447 stream.totalVolume_ = stream.isMuted_ ? 0.0f :
448 stream.volume_ * stream.duckFactor_ * stream.lowPowerFactor_ * stream.appVolume_;
449 }
450 }
451 }
452
SetDefaultAppVolume(int32_t level)453 void AudioVolume::SetDefaultAppVolume(int32_t level)
454 {
455 defaultAppVolume_ = level;
456 }
457
SetSystemVolume(SystemVolume & systemVolume)458 void AudioVolume::SetSystemVolume(SystemVolume &systemVolume)
459 {
460 auto volumeType = systemVolume.GetVolumeType();
461 auto deviceClass = systemVolume.GetDeviceClass();
462 systemVolume.totalVolume_ = systemVolume.isMuted_ ? 0.0f : systemVolume.volume_;
463 std::string key = std::to_string(volumeType) + deviceClass;
464 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
465 auto it = systemVolume_.find(key);
466 if (it != systemVolume_.end()) {
467 it->second.volume_ = systemVolume.volume_;
468 it->second.volumeLevel_ = systemVolume.volumeLevel_;
469 it->second.isMuted_ = systemVolume.isMuted_;
470 it->second.totalVolume_ = systemVolume.totalVolume_;
471 } else {
472 systemVolume_.emplace(key, systemVolume);
473 }
474
475 AUDIO_INFO_LOG("system volume, volumeType:%{public}d, deviceClass:%{public}s,"
476 " volume:%{public}f, volumeLevel:%{public}d, isMuted:%{public}d, systemVolumeSize:%{public}zu",
477 volumeType, deviceClass.c_str(), systemVolume.volume_, systemVolume.volumeLevel_, systemVolume.isMuted_,
478 systemVolume_.size());
479 }
480
SetSystemVolume(int32_t volumeType,const std::string & deviceClass,float volume,int32_t volumeLevel)481 void AudioVolume::SetSystemVolume(int32_t volumeType, const std::string &deviceClass,
482 float volume, int32_t volumeLevel)
483 {
484 std::string key = std::to_string(volumeType) + deviceClass;
485 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
486 auto it = systemVolume_.find(key);
487 if (it != systemVolume_.end()) {
488 it->second.volume_ = volume;
489 it->second.volumeLevel_ = volumeLevel;
490 it->second.totalVolume_ = it->second.isMuted_ ? 0.0f : it->second.volume_;
491 } else {
492 SystemVolume systemVolume(volumeType, deviceClass, volume, volumeLevel, false);
493 systemVolume.totalVolume_ = systemVolume.isMuted_ ? 0.0f : systemVolume.volume_;
494 systemVolume_.emplace(key, systemVolume);
495 }
496
497 AUDIO_INFO_LOG("system volume, volumeType:%{public}d, deviceClass:%{public}s,"
498 " volume:%{public}f, volumeLevel:%{public}d, systemVolumeSize:%{public}zu",
499 volumeType, deviceClass.c_str(), volume, volumeLevel, systemVolume_.size());
500 }
501
SetSystemVolumeMute(int32_t volumeType,const std::string & deviceClass,bool isMuted)502 void AudioVolume::SetSystemVolumeMute(int32_t volumeType, const std::string &deviceClass, bool isMuted)
503 {
504 AUDIO_INFO_LOG("system volume, volumeType:%{public}d, deviceClass:%{public}s, isMuted:%{public}d",
505 volumeType, deviceClass.c_str(), isMuted);
506 std::string key = std::to_string(volumeType) + deviceClass;
507 std::unique_lock<std::shared_mutex> lock(volumeMutex_);
508 auto it = systemVolume_.find(key);
509 if (it != systemVolume_.end()) {
510 it->second.isMuted_ = isMuted;
511 it->second.totalVolume_ = it->second.isMuted_ ? 0.0f : it->second.volume_;
512 } else {
513 SystemVolume systemVolume(volumeType, deviceClass, 0.0f, 0, isMuted);
514 systemVolume.totalVolume_ = systemVolume.isMuted_ ? 0.0f : systemVolume.volume_;
515 systemVolume_.emplace(key, systemVolume);
516 }
517 }
518
ConvertStreamTypeStrToInt(const std::string & streamType)519 int32_t AudioVolume::ConvertStreamTypeStrToInt(const std::string &streamType)
520 {
521 AudioStreamType stream = STREAM_MUSIC;
522 if (STREAM_TYPE_STRING_ENUM_MAP.find(streamType) != STREAM_TYPE_STRING_ENUM_MAP.end()) {
523 stream = STREAM_TYPE_STRING_ENUM_MAP.at(streamType);
524 } else {
525 AUDIO_WARNING_LOG("Invalid stream type [%{public}s]. Use default type", streamType.c_str());
526 }
527 return stream;
528 }
529
IsSameVolume(float x,float y)530 bool AudioVolume::IsSameVolume(float x, float y)
531 {
532 return (std::abs((x) - (y)) <= std::abs(FLOAT_EPS));
533 }
534
Dump(std::string & dumpString)535 void AudioVolume::Dump(std::string &dumpString)
536 {
537 AUDIO_INFO_LOG("AudioVolume dump begin");
538 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
539 // dump system volume
540 std::vector<SystemVolume> systemVolumeList;
541 for (auto &systemVolume : systemVolume_) {
542 systemVolumeList.push_back(systemVolume.second);
543 }
544 std::sort(systemVolumeList.begin(), systemVolumeList.end(), [](SystemVolume &a, SystemVolume &b) {
545 return a.GetVolumeType() < b.GetVolumeType();
546 });
547 AppendFormat(dumpString, "\n - audio system volume size: %zu\n", systemVolumeList.size());
548 for (auto &systemVolume : systemVolumeList) {
549 AppendFormat(dumpString, " streamtype: %d ", systemVolume.GetVolumeType());
550 AppendFormat(dumpString, " isMute: %s ", (systemVolume.isMuted_ ? "true" : "false"));
551 AppendFormat(dumpString, " volFloat: %f ", systemVolume.volume_);
552 AppendFormat(dumpString, " volInt: %d ", systemVolume.volumeLevel_);
553 AppendFormat(dumpString, " device class: %s \n", systemVolume.GetDeviceClass().c_str());
554 }
555
556 // dump stream volume
557 std::vector<StreamVolume> streamVolumeList;
558 for (auto &streamVolume : streamVolume_) {
559 streamVolumeList.push_back(streamVolume.second);
560 }
561 std::sort(streamVolumeList.begin(), streamVolumeList.end(), [](StreamVolume &a, StreamVolume &b) {
562 return a.GetSessionId() < b.GetSessionId();
563 });
564 AppendFormat(dumpString, "\n - audio stream volume size: %zu\n", streamVolumeList.size());
565 for (auto &streamVolume : streamVolumeList) {
566 AppendFormat(dumpString, " sessionId: %u ", streamVolume.GetSessionId());
567 AppendFormat(dumpString, " streamType: %d ", streamVolume.GetStreamType());
568 AppendFormat(dumpString, " streamUsage: %d ", streamVolume.GetStreamUsage());
569 AppendFormat(dumpString, " appUid: %d ", streamVolume.GetAppUid());
570 AppendFormat(dumpString, " appPid: %d ", streamVolume.GetAppPid());
571 AppendFormat(dumpString, " volume: %f ", streamVolume.monitorVolume_);
572 AppendFormat(dumpString, " volumeLevel: %d ", streamVolume.monitorVolumeLevel_);
573 AppendFormat(dumpString, " volFactor: %f ", streamVolume.volume_);
574 AppendFormat(dumpString, " duckFactor: %f ", streamVolume.duckFactor_);
575 AppendFormat(dumpString, " powerFactor: %f ", streamVolume.lowPowerFactor_);
576 AppendFormat(dumpString, " appVolume: %f \n", streamVolume.appVolume_);
577 }
578 }
579
Monitor(uint32_t sessionId,bool isOutput)580 void AudioVolume::Monitor(uint32_t sessionId, bool isOutput)
581 {
582 std::shared_lock<std::shared_mutex> lock(volumeMutex_);
583 auto streamVolume = streamVolume_.find(sessionId);
584 if (streamVolume != streamVolume_.end()) {
585 std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
586 Media::MediaMonitor::AUDIO, Media::MediaMonitor::VOLUME_CHANGE,
587 Media::MediaMonitor::BEHAVIOR_EVENT);
588 bean->Add("ISOUTPUT", isOutput ? 1 : 0);
589 bean->Add("STREAMID", static_cast<int32_t>(sessionId));
590 bean->Add("APP_UID", streamVolume->second.GetAppUid());
591 bean->Add("APP_PID", streamVolume->second.GetAppPid());
592 bean->Add("STREAMTYPE", streamVolume->second.GetStreamType());
593 bean->Add("STREAM_TYPE", streamVolume->second.GetStreamUsage());
594 bean->Add("VOLUME", streamVolume->second.monitorVolume_);
595 bean->Add("SYSVOLUME", streamVolume->second.monitorVolumeLevel_);
596 bean->Add("VOLUMEFACTOR", streamVolume->second.volume_);
597 bean->Add("POWERVOLUMEFACTOR", streamVolume->second.lowPowerFactor_);
598 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
599 } else {
600 AUDIO_ERR_LOG("stream volume not exist, sessionId:%{public}u", sessionId);
601 }
602 }
603
SetFadeoutState(uint32_t streamIndex,uint32_t fadeoutState)604 void AudioVolume::SetFadeoutState(uint32_t streamIndex, uint32_t fadeoutState)
605 {
606 std::unique_lock<std::shared_mutex> lock(fadeoutMutex_);
607 fadeoutState_.insert_or_assign(streamIndex, fadeoutState);
608 }
609
GetFadeoutState(uint32_t streamIndex)610 uint32_t AudioVolume::GetFadeoutState(uint32_t streamIndex)
611 {
612 std::shared_lock<std::shared_mutex> lock(fadeoutMutex_);
613 auto it = fadeoutState_.find(streamIndex);
614 if (it != fadeoutState_.end()) { return it->second; }
615 AUDIO_WARNING_LOG("No such streamIndex in map!");
616 return INVALID_STATE;
617 }
618
RemoveFadeoutState(uint32_t streamIndex)619 void AudioVolume::RemoveFadeoutState(uint32_t streamIndex)
620 {
621 std::unique_lock<std::shared_mutex> lock(fadeoutMutex_);
622 fadeoutState_.erase(streamIndex);
623 }
624
SetStopFadeoutState(uint32_t streamIndex,uint32_t fadeoutState)625 void AudioVolume::SetStopFadeoutState(uint32_t streamIndex, uint32_t fadeoutState)
626 {
627 std::unique_lock<std::shared_mutex> lock(fadeoutMutex_);
628 stopFadeoutState_.insert_or_assign(streamIndex, fadeoutState);
629 }
630
GetStopFadeoutState(uint32_t streamIndex)631 uint32_t AudioVolume::GetStopFadeoutState(uint32_t streamIndex)
632 {
633 std::shared_lock<std::shared_mutex> lock(fadeoutMutex_);
634 auto it = stopFadeoutState_.find(streamIndex);
635 if (it != stopFadeoutState_.end()) {
636 return it->second;
637 }
638 AUDIO_WARNING_LOG("No such streamIndex in map!");
639 return INVALID_STATE;
640 }
641
RemoveStopFadeoutState(uint32_t streamIndex)642 void AudioVolume::RemoveStopFadeoutState(uint32_t streamIndex)
643 {
644 std::unique_lock<std::shared_mutex> lock(fadeoutMutex_);
645 stopFadeoutState_.erase(streamIndex);
646 }
647
SetVgsVolumeSupported(bool isVgsSupported)648 void AudioVolume::SetVgsVolumeSupported(bool isVgsSupported)
649 {
650 isVgsVolumeSupported_ = isVgsSupported;
651 }
652
IsVgsVolumeSupported() const653 inline bool AudioVolume::IsVgsVolumeSupported() const
654 {
655 // solve bluetooth sco connneted then connect typec headset, the volume of typec headset can not be adjusted.
656 return isVgsVolumeSupported_ && currentActiveDevice_ == DEVICE_TYPE_BLUETOOTH_SCO;
657 }
658
SetCurrentActiveDevice(DeviceType currentActiveDevice)659 void AudioVolume::SetCurrentActiveDevice(DeviceType currentActiveDevice)
660 {
661 AUDIO_INFO_LOG("SetCurrentActiveDevice %{public}d", currentActiveDevice);
662 currentActiveDevice_ = currentActiveDevice;
663 }
664
SetOffloadType(uint32_t streamIndex,int32_t offloadType)665 void AudioVolume::SetOffloadType(uint32_t streamIndex, int32_t offloadType)
666 {
667 std::unique_lock<std::shared_mutex> lock(fadeoutMutex_);
668 offloadType_.insert_or_assign(streamIndex, offloadType);
669 }
670
GetOffloadType(uint32_t streamIndex)671 int32_t AudioVolume::GetOffloadType(uint32_t streamIndex)
672 {
673 std::shared_lock<std::shared_mutex> lock(fadeoutMutex_);
674 auto it = offloadType_.find(streamIndex);
675 if (it != offloadType_.end()) { return it->second; }
676 AUDIO_WARNING_LOG("No such streamIndex in map!");
677 return OFFLOAD_DEFAULT;
678 }
679 } // namespace AudioStandard
680 } // namespace OHOS
681
682 #ifdef __cplusplus
683 extern "C" {
684 #endif
685 using namespace OHOS::AudioStandard;
686
GetCurVolume(uint32_t sessionId,const char * streamType,const char * deviceClass,struct VolumeValues * volumes)687 float GetCurVolume(uint32_t sessionId, const char *streamType, const char *deviceClass,
688 struct VolumeValues *volumes)
689 {
690 CHECK_AND_RETURN_RET_LOG(streamType != nullptr, 1.0f, "streamType is nullptr");
691 CHECK_AND_RETURN_RET_LOG(deviceClass != nullptr, 1.0f, "deviceClass is nullptr");
692 int32_t stream = AudioVolume::GetInstance()->ConvertStreamTypeStrToInt(streamType);
693 return AudioVolume::GetInstance()->GetVolume(sessionId, stream, deviceClass, volumes);
694 }
695
GetStreamVolume(uint32_t sessionId)696 float GetStreamVolume(uint32_t sessionId)
697 {
698 return AudioVolume::GetInstance()->GetStreamVolume(sessionId);
699 }
700
GetPreVolume(uint32_t sessionId)701 float GetPreVolume(uint32_t sessionId)
702 {
703 return AudioVolume::GetInstance()->GetHistoryVolume(sessionId);
704 }
705
SetPreVolume(uint32_t sessionId,float volume)706 void SetPreVolume(uint32_t sessionId, float volume)
707 {
708 AudioVolume::GetInstance()->SetHistoryVolume(sessionId, volume);
709 }
710
IsSameVolume(float x,float y)711 bool IsSameVolume(float x, float y)
712 {
713 return AudioVolume::GetInstance()->IsSameVolume(x, y);
714 }
715
MonitorVolume(uint32_t sessionId,bool isOutput)716 void MonitorVolume(uint32_t sessionId, bool isOutput)
717 {
718 AudioVolume::GetInstance()->Monitor(sessionId, isOutput);
719 }
720
SetFadeoutState(uint32_t streamIndex,uint32_t fadeoutState)721 void SetFadeoutState(uint32_t streamIndex, uint32_t fadeoutState)
722 {
723 AudioVolume::GetInstance()->SetFadeoutState(streamIndex, fadeoutState);
724 }
725
GetFadeoutState(uint32_t streamIndex)726 uint32_t GetFadeoutState(uint32_t streamIndex)
727 {
728 return AudioVolume::GetInstance()->GetFadeoutState(streamIndex);
729 }
730
GetStopFadeoutState(uint32_t streamIndex)731 uint32_t GetStopFadeoutState(uint32_t streamIndex)
732 {
733 return AudioVolume::GetInstance()->GetStopFadeoutState(streamIndex);
734 }
735
RemoveStopFadeoutState(uint32_t streamIndex)736 void RemoveStopFadeoutState(uint32_t streamIndex)
737 {
738 AudioVolume::GetInstance()->RemoveStopFadeoutState(streamIndex);
739 }
740
GetSimpleBufferAvg(uint8_t * buffer,int32_t length)741 int32_t GetSimpleBufferAvg(uint8_t *buffer, int32_t length)
742 {
743 if (length <= 0) {
744 return -1;
745 }
746 int32_t sum = std::accumulate(buffer, buffer + length, 0);
747 return sum / length;
748 }
749
GetFadeStrategy(uint64_t expectedPlaybackDurationMs)750 FadeStrategy GetFadeStrategy(uint64_t expectedPlaybackDurationMs)
751 {
752 // 0 is default; duration > 40ms do default fade
753 if (expectedPlaybackDurationMs == 0 || expectedPlaybackDurationMs > DURATION_TIME_DEFAULT) {
754 return FADE_STRATEGY_DEFAULT;
755 }
756
757 // duration <= 10 ms no fade
758 if (expectedPlaybackDurationMs <= DURATION_TIME_SHORT && expectedPlaybackDurationMs > 0) {
759 return FADE_STRATEGY_NONE;
760 }
761
762 // duration > 10ms && duration <= 40ms do 5ms fade
763 if (expectedPlaybackDurationMs <= DURATION_TIME_DEFAULT && expectedPlaybackDurationMs > DURATION_TIME_SHORT) {
764 return FADE_STRATEGY_SHORTER;
765 }
766
767 return FADE_STRATEGY_DEFAULT;
768 }
769
SetOffloadType(uint32_t streamIndex,int32_t offloadType)770 void SetOffloadType(uint32_t streamIndex, int32_t offloadType)
771 {
772 AudioVolume::GetInstance()->SetOffloadType(streamIndex, offloadType);
773 }
774
GetOffloadType(uint32_t streamIndex)775 int32_t GetOffloadType(uint32_t streamIndex)
776 {
777 return AudioVolume::GetInstance()->GetOffloadType(streamIndex);
778 }
779 #ifdef __cplusplus
780 }
781 #endif