• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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