From 7b8934a8d31875db726a23917417eebe2aaa2bf8 Mon Sep 17 00:00:00 2001 From: fengyulong Date: Fri, 15 Aug 2025 21:44:32 +0800 Subject: [PATCH] add loud volume Signed-off-by: fengyulong --- .../audiocommon/include/audio_stream_info.h | 13 ++ .../interrupt/src/audio_interrupt_service.cpp | 4 + .../volume/include/audio_adapter_manager.h | 1 + .../include/audio_safe_volume_notification.h | 18 ++ .../audio_safe_volume_notification_impl.h | 28 +++ .../volume/include/audio_volume_manager.h | 2 + .../volume/include/iaudio_policy_interface.h | 1 + .../volume/src/audio_adapter_manager.cpp | 22 ++ .../audio_safe_volume_notification_impl.cpp | 102 ++++++++++ .../volume/src/audio_volume_manager.cpp | 40 ++++ .../include/audio_policy_server.h | 16 ++ .../service_main/src/audio_policy_server.cpp | 192 +++++++++++++++++- .../audio_service/server/src/audio_server.cpp | 2 + 13 files changed, 439 insertions(+), 2 deletions(-) diff --git a/interfaces/inner_api/native/audiocommon/include/audio_stream_info.h b/interfaces/inner_api/native/audiocommon/include/audio_stream_info.h index 10e67b96d5..58145284df 100644 --- a/interfaces/inner_api/native/audiocommon/include/audio_stream_info.h +++ b/interfaces/inner_api/native/audiocommon/include/audio_stream_info.h @@ -553,6 +553,19 @@ const std::vector AUDIO_SUPPORTED_STREAM_USAGES { STREAM_USAGE_VOICE_CALL_ASSISTANT, }; +enum FunctionHoldType { + FUNCTION_HOLD_INVALID = -1, + FUNCTION_HOLD_MUSIC, + FUNCTION_HOLD_SYSTEM, +}; + +enum SetLoudVolMode { + LOUD_VOLUME_SWITCH_INVALID = -1, + LOUD_VOLUME_SWITCH_UNSET, + LOUD_VOLUME_SWITCH_OFF, + LOUD_VOLUME_SWITCH_ON, +}; + class AudioStreamInfo : public Parcelable { public: AudioSamplingRate samplingRate; diff --git a/services/audio_policy/server/domain/interrupt/src/audio_interrupt_service.cpp b/services/audio_policy/server/domain/interrupt/src/audio_interrupt_service.cpp index f59310c4a4..eab238d736 100644 --- a/services/audio_policy/server/domain/interrupt/src/audio_interrupt_service.cpp +++ b/services/audio_policy/server/domain/interrupt/src/audio_interrupt_service.cpp @@ -921,6 +921,10 @@ int32_t AudioInterruptService::ActivateAudioInterruptInternal(const int32_t zone incomingStreamId, currAudioInterrupt.pid, streamType, zoneId, currAudioInterrupt.streamUsage, (currAudioInterrupt.audioFocusType).sourceType); +#ifdef FEATURE_MULTIMODALINPUT_INPUT + CHECK_AND_RETURN_RET_LOG(policyServer_ != nullptr, ERR_FOCUS_DENIED, "policyServer nullptr"); + policyServer_->ReloadLoudVolumeMode(streamType); +#endif if (AudioInterruptIsActiveInFocusList(zoneId, incomingStreamId) && !isUpdatedAudioStrategy) { AUDIO_INFO_LOG("Stream is active in focus list, no need to active audio interrupt."); return SUCCESS; diff --git a/services/audio_policy/server/domain/volume/include/audio_adapter_manager.h b/services/audio_policy/server/domain/volume/include/audio_adapter_manager.h index 2836472bc2..3ea2897dd4 100644 --- a/services/audio_policy/server/domain/volume/include/audio_adapter_manager.h +++ b/services/audio_policy/server/domain/volume/include/audio_adapter_manager.h @@ -311,6 +311,7 @@ public: int32_t SetSystemVolumeDegree(AudioStreamType streamType, int32_t volumeDegree); int32_t GetSystemVolumeDegree(AudioStreamType streamType); int32_t GetMinVolumeDegree(AudioVolumeType volumeType); + void SendLoudVolumeModeToDsp(FunctionHoldType funcHoldType, bool state); private: friend class PolicyCallbackImpl; diff --git a/services/audio_policy/server/domain/volume/include/audio_safe_volume_notification.h b/services/audio_policy/server/domain/volume/include/audio_safe_volume_notification.h index e01cc7afc8..bca4787666 100644 --- a/services/audio_policy/server/domain/volume/include/audio_safe_volume_notification.h +++ b/services/audio_policy/server/domain/volume/include/audio_safe_volume_notification.h @@ -51,6 +51,24 @@ public: }; typedef AudioSafeVolumeNotification* CreateSafeVolumeNotification(); + +const int32_t LOUD_ICON_WIDTH = 24; +const int32_t LOUD_ICON_HEIGHT = 24; + +const std::string LOUD_VOLUME_ICON_ID = "loud_volume_notification_icon"; +const std::string LOUD_VOLUME_FEATURE_TITTLE_ID = "notification_feature_loud_volume_tittle"; +const std::string LOUD_VOLUME_ENABLE_TITTLE_ID = "notification_enable_loud_volume_tittle"; + +class AudioLoudVolumeNotification { +public: + AudioLoudVolumeNotification() = default; + virtual ~AudioLoudVolumeNotification() = default; + + virtual void PublishLoudVolumeNotification(int32_t notificationId) = 0; +}; + +typedef AudioLoudVolumeNotification* CreateLoudVolumeNotification(); + } // namespace AudioStandard } // namespace OHOS #endif // AUDIO_SAFE_VOLUME_NOTIFICATION_H diff --git a/services/audio_policy/server/domain/volume/include/audio_safe_volume_notification_impl.h b/services/audio_policy/server/domain/volume/include/audio_safe_volume_notification_impl.h index 2348803d2f..46c68a617e 100644 --- a/services/audio_policy/server/domain/volume/include/audio_safe_volume_notification_impl.h +++ b/services/audio_policy/server/domain/volume/include/audio_safe_volume_notification_impl.h @@ -58,6 +58,34 @@ extern "C" AudioSafeVolumeNotification *CreateSafeVolumeNotificationImpl() { return new AudioSafeVolumeNotificationImpl; } + +class AudioLoudVolumeNotificationImpl : public AudioLoudVolumeNotification { +public: + AudioLoudVolumeNotificationImpl() = default; + virtual ~AudioLoudVolumeNotificationImpl() = default; + + void PublishLoudVolumeNotification(int32_t notificationId) override; +private: + std::string GetSystemStringByName(const std::string &name); + bool SetTitleAndText(int32_t notificationId, Notification::NotificationCapsule &capsule); + bool GetPixelMap(); + Global::Resource::RState GetMediaDataByName(const std::string& name, size_t& len, + std::unique_ptr& outValue, uint32_t density = 0); + + std::string title_ {}; + std::string text_ {}; + std::string buttonName_ {}; + std::string iconPath_ {}; + + std::mutex mutex_ {}; + std::shared_ptr iconPixelMap_ {}; +}; + +extern "C" AudioLoudVolumeNotification *CreateLoudVolumeNotificationImpl() +{ + return new AudioLoudVolumeNotificationImpl; +} + } // namespace AudioStandard } // namespace OHOS #endif // AUDIO_SAFE_VOLUME_NOTIFICATION_IMPL_H diff --git a/services/audio_policy/server/domain/volume/include/audio_volume_manager.h b/services/audio_policy/server/domain/volume/include/audio_volume_manager.h index f05e5d57ba..b4fe7656ae 100644 --- a/services/audio_policy/server/domain/volume/include/audio_volume_manager.h +++ b/services/audio_policy/server/domain/volume/include/audio_volume_manager.h @@ -141,6 +141,7 @@ public: int32_t zoneId); int32_t GetSystemVolumeDegree(AudioStreamType streamType); int32_t GetMinVolumeDegree(AudioVolumeType volumeType) const; + void SendLoudVolumeMode(FunctionHoldType funcHoldType, bool state, bool repeatTrigNotif = false); private: AudioVolumeManager() : audioPolicyManager_(AudioPolicyManagerFactory::GetAudioPolicyManager()), @@ -167,6 +168,7 @@ private: DeviceType deviceType = DEVICE_TYPE_NONE); void PublishSafeVolumeNotification(int32_t notificationId); void CancelSafeVolumeNotification(int32_t notificationId); + void PublishLoudVolumeNotification(int32_t notificationId); bool IsWiredHeadSet(const DeviceType &deviceType); void CheckToCloseNotification(AudioStreamType streamType, int32_t volumeLevel); bool DeviceIsSupportSafeVolume(); diff --git a/services/audio_policy/server/domain/volume/include/iaudio_policy_interface.h b/services/audio_policy/server/domain/volume/include/iaudio_policy_interface.h index 2dc331e836..d697e21806 100644 --- a/services/audio_policy/server/domain/volume/include/iaudio_policy_interface.h +++ b/services/audio_policy/server/domain/volume/include/iaudio_policy_interface.h @@ -252,6 +252,7 @@ public: virtual int32_t SetSystemVolumeDegree(AudioStreamType streamType, int32_t volumeDegree) = 0; virtual int32_t GetSystemVolumeDegree(AudioStreamType streamType) = 0; virtual int32_t GetMinVolumeDegree(AudioVolumeType volumeType) = 0; + virtual void SendLoudVolumeModeToDsp(FunctionHoldType funcHoldType, bool state) = 0; }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_policy/server/domain/volume/src/audio_adapter_manager.cpp b/services/audio_policy/server/domain/volume/src/audio_adapter_manager.cpp index e77abcdccc..83730b96d4 100644 --- a/services/audio_policy/server/domain/volume/src/audio_adapter_manager.cpp +++ b/services/audio_policy/server/domain/volume/src/audio_adapter_manager.cpp @@ -415,6 +415,28 @@ void AudioAdapterManager::UpdateSafeVolumeByS4() SetVolumeDb(STREAM_MUSIC); } +void AudioAdapterManager::SendLoudVolumeModeToDsp(FunctionHoldType funcHoldType, bool state) +{ + std::string key = "LOUD_VOLUME_MODE"; + std::string value = "super_loudness_mode=voice_off"; + std::string identity = IPCSkeleton::ResetCallingIdentity(); + CHECK_AND_RETURN_LOG(audioServerProxy_ != nullptr, "audioServerProxy_ null"); + + if (FUNCTION_HOLD_SYSTEM == funcHoldType) { + value = state ? "super_loudness_mode=voice_on" : "super_loudness_mode=voice_off"; + } else if (FUNCTION_HOLD_MUSIC == funcHoldType) { + value = state ? "super_loudness_mode=music_on" : "super_loudness_mode=music_off"; + } else { + AUDIO_ERR_LOG("funcHoldType error : %{public}d", funcHoldType); + return; + } + + audioServerProxy_->SetAudioParameter(key, value); + IPCSkeleton::SetCallingIdentity(identity); + AUDIO_INFO_LOG("update LoudVolume [%{public}s]", value.c_str()); + return; +} + int32_t AudioAdapterManager::SetAppVolumeLevel(int32_t appUid, int32_t volumeLevel) { AUDIO_INFO_LOG("SetSystemVolumeLevel: appUid: %{public}d, deviceType: %{public}d, volumeLevel:%{public}d", diff --git a/services/audio_policy/server/domain/volume/src/audio_safe_volume_notification_impl.cpp b/services/audio_policy/server/domain/volume/src/audio_safe_volume_notification_impl.cpp index 219eb0b1a9..6e71918c0f 100644 --- a/services/audio_policy/server/domain/volume/src/audio_safe_volume_notification_impl.cpp +++ b/services/audio_policy/server/domain/volume/src/audio_safe_volume_notification_impl.cpp @@ -248,5 +248,107 @@ Global::Resource::RState AudioSafeVolumeNotificationImpl::GetMediaDataByName(con IPCSkeleton::SetCallingIdentity(identity); return rstate; } + +std::string AudioLoudVolumeNotificationImpl::GetSystemStringByName(const std::string &name) +{ + std::string identity = IPCSkeleton::ResetCallingIdentity(); + std::string result = ResourceManagerAdapter::GetInstance()->GetSystemStringByName(name); + IPCSkeleton::SetCallingIdentity(identity); + return result; +} + +bool AudioLoudVolumeNotificationImpl::SetTitleAndText(int32_t notificationId, + Notification::NotificationCapsule &capsule) +{ + capsule.SetTitle(GetSystemStringByName(LOUD_VOLUME_FEATURE_TITTLE_ID)); + capsule.SetContent(GetSystemStringByName(LOUD_VOLUME_ENABLE_TITTLE_ID)); + + return true; +} + +bool AudioLoudVolumeNotificationImpl::GetPixelMap() +{ + if (iconPixelMap_ != nullptr) { + AUDIO_ERR_LOG("icon pixel map already exists."); + return false; + } + + std::unique_ptr resourceData; + size_t resourceDataLength = 0; + auto ret = GetMediaDataByName(LOUD_VOLUME_ICON_ID.c_str(), resourceDataLength, resourceData); + if (ret != Global::Resource::RState::SUCCESS) { + AUDIO_ERR_LOG("get (%{public}s) failed, errorCode:%{public}d", LOUD_VOLUME_ICON_ID.c_str(), + static_cast(ret)); + return false; + } + + Media::SourceOptions opts; + uint32_t errorCode = 0; + std::unique_ptr imageSource = + Media::ImageSource::CreateImageSource(resourceData.get(), resourceDataLength, opts, errorCode); + Media::DecodeOptions decodeOpts; + decodeOpts.desiredSize = {LOUD_ICON_WIDTH, LOUD_ICON_HEIGHT}; + decodeOpts.desiredPixelFormat = Media::PixelFormat::BGRA_8888; + if (imageSource) { + AUDIO_INFO_LOG("GetPixelMap SUCCESS."); + std::unique_ptr pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode); + iconPixelMap_ = std::move(pixelMap); + } + if (errorCode != 0 || (iconPixelMap_ == nullptr)) { + AUDIO_ERR_LOG("get badge failed, errorCode:%{public}u", errorCode); + return false; + } + return true; +} + +void AudioLoudVolumeNotificationImpl::PublishLoudVolumeNotification(int32_t notificationId) +{ + const int TYPE_CODE = 16; + std::shared_ptr instantlLiveViewContent = + std::make_shared(); + if (instantlLiveViewContent == nullptr) { + AUDIO_ERR_LOG("instantlLiveViewContent is null"); + return; + } + + Notification::NotificationCapsule capsule; + if (!SetTitleAndText(notificationId, capsule)) { + AUDIO_ERR_LOG("error setting title and text"); + return; + } + GetPixelMap(); + if (iconPixelMap_ != nullptr) { + capsule.SetIcon(iconPixelMap_); + } + instantlLiveViewContent->SetCapsule(capsule); + instantlLiveViewContent->addFlag(Notification::NotificationLocalLiveViewContent::LiveViewContentInner::CAPSULE); + + instantlLiveViewContent->SetType(TYPE_CODE); + instantlLiveViewContent->SetLiveViewType( + Notification::NotificationLocalLiveViewContent::LiveViewTypes::LIVE_VIEW_INSTANT); + + std::shared_ptr instantContent = + std::make_shared(instantlLiveViewContent); + + Notification::NotificationRequest instantRequest; + instantRequest.SetNotificationId(notificationId); + instantRequest.SetCreatorUid(getuid()); + instantRequest.SetContent(instantContent); + instantRequest.SetSlotType(Notification::NotificationConstant::SlotType::LIVE_VIEW); + + int32_t result = Notification::NotificationHelper::PublishNotification(instantRequest); + AUDIO_INFO_LOG("AudioPolicyServer publish result:%{public}d", result); + return; +} + +Global::Resource::RState AudioLoudVolumeNotificationImpl::GetMediaDataByName(const std::string& name, size_t& len, + std::unique_ptr& outValue, uint32_t density) +{ + std::string identity = IPCSkeleton::ResetCallingIdentity(); + Global::Resource::RState rstate = + ResourceManagerAdapter::GetInstance()->GetMediaDataByName(name, len, outValue, density); + IPCSkeleton::SetCallingIdentity(identity); + return rstate; +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_policy/server/domain/volume/src/audio_volume_manager.cpp b/services/audio_policy/server/domain/volume/src/audio_volume_manager.cpp index ad94be2ebf..a45b685d0c 100644 --- a/services/audio_policy/server/domain/volume/src/audio_volume_manager.cpp +++ b/services/audio_policy/server/domain/volume/src/audio_volume_manager.cpp @@ -317,6 +317,46 @@ bool AudioVolumeManager::DeviceIsSupportSafeVolume() } } +void AudioVolumeManager::PublishLoudVolumeNotification(int32_t notificationId) +{ + void *libHandle = dlopen("libaudio_safe_volume_notification_impl.z.so", RTLD_LAZY); + if (libHandle == nullptr) { + AUDIO_ERR_LOG("dlopen failed %{public}s", __func__); + return; + } + CreateLoudVolumeNotification *createLoudVolumeNotificationImpl = + reinterpret_cast(dlsym(libHandle, "CreateLoudVolumeNotificationImpl")); + if (createLoudVolumeNotificationImpl == nullptr) { + AUDIO_ERR_LOG("createLoudVolumeNotificationImpl failed %{public}s", __func__); +#ifndef TEST_COVERAGE + dlclose(libHandle); +#endif + return; + } + AudioLoudVolumeNotification *audioLoudVolumeNotificationImpl = createLoudVolumeNotificationImpl(); + if (audioLoudVolumeNotificationImpl == nullptr) { + AUDIO_ERR_LOG("audioLoudVolumeNotificationImpl is nullptr %{public}s", __func__); +#ifndef TEST_COVERAGE + dlclose(libHandle); +#endif + return; + } + audioLoudVolumeNotificationImpl->PublishLoudVolumeNotification(notificationId); + delete audioLoudVolumeNotificationImpl; +#ifndef TEST_COVERAGE + dlclose(libHandle); +#endif +} + +void AudioVolumeManager::SendLoudVolumeMode(FunctionHoldType funcHoldType, bool state, bool repeatTrigNotif) +{ + if (state && repeatTrigNotif) { + const int INSTANT_NOTIFICATION_ID = 6; + PublishLoudVolumeNotification(INSTANT_NOTIFICATION_ID); + } + audioPolicyManager_.SendLoudVolumeModeToDsp(funcHoldType, state); +} + int32_t AudioVolumeManager::SetAppVolumeLevel(int32_t appUid, int32_t volumeLevel) { AUDIO_INFO_LOG("enter AudioVolumeManager::SetAppVolumeLevel"); diff --git a/services/audio_policy/server/service/service_main/include/audio_policy_server.h b/services/audio_policy/server/service/service_main/include/audio_policy_server.h index 9146d00906..2f3cd76338 100644 --- a/services/audio_policy/server/service/service_main/include/audio_policy_server.h +++ b/services/audio_policy/server/service/service_main/include/audio_policy_server.h @@ -682,6 +682,10 @@ public: int32_t SetSystemVolumeDegree(int32_t streamType, int32_t volumeDegree, int32_t volumeFlag, int32_t uid) override; int32_t GetSystemVolumeDegree(int32_t streamType, int32_t uid, int32_t &volumeDegree) override; int32_t GetMinVolumeDegree(int32_t volumeType, int32_t &volumeDegree) override; +#ifdef FEATURE_MULTIMODALINPUT_INPUT + bool ReloadLoudVolumeMode(const AudioStreamType streamInFocus, + SetLoudVolMode setVolMode = LOUD_VOLUME_SWITCH_UNSET); +#endif protected: void OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) override; void RegisterParamCallback(); @@ -776,6 +780,10 @@ private: bool IsContinueAddVol(); void TriggerMuteCheck(); int32_t ProcessVolumeKeyEvents(const int32_t keyType); + void SetLoudVolumeHoldMap(FunctionHoldType funcHoldType, bool state); + bool ClearLoudVolumeHoldMap(FunctionHoldType funcHoldType); + bool GetLoudVolumeHoldMap(FunctionHoldType funcHoldType, bool &state); + bool CheckLoudVolumeMode(const int32_t volLevel, const int32_t keyType, const AudioStreamType &streamInFocus); #endif void AddAudioServiceOnStart(); void SubscribeOsAccountChangeEvents(); @@ -864,6 +872,13 @@ private: std::mutex volUpHistoryMutex_; std::deque volUpHistory_; std::atomic hasSubscribedVolumeKeyEvents_ = false; + + int32_t triggerTime = 0; + int64_t upTriggerTimeMSec = 0; + std::mutex loudVolTrigTimeMutex_; + AudioStreamType lastReloadStreamType = STREAM_DEFAULT; + std::mutex setLoudVolHoldMutex_; + std::unordered_map loudVolumeHoldMap_; #endif std::vector clientDiedListenerState_; sptr powerStateListener_; @@ -881,6 +896,7 @@ private: bool volumeApplyToAll_ = false; bool screenOffAdjustVolumeEnable_ = false; bool supportVibrator_ = false; + bool loudVolumeModeEnable_ = false; bool isHighResolutionExist_ = false; std::mutex descLock_; diff --git a/services/audio_policy/server/service/service_main/src/audio_policy_server.cpp b/services/audio_policy/server/service/service_main/src/audio_policy_server.cpp index a600452866..24606dc0e7 100644 --- a/services/audio_policy/server/service/service_main/src/audio_policy_server.cpp +++ b/services/audio_policy/server/service/service_main/src/audio_policy_server.cpp @@ -169,6 +169,7 @@ AudioPolicyServer::AudioPolicyServer(int32_t systemAbilityId, bool runOnCreate) supportVibrator_ = system::GetBoolParameter("const.vibrator.support_vibrator", true); volumeApplyToAll_ = system::GetBoolParameter("const.audio.volume_apply_to_all", false); screenOffAdjustVolumeEnable_ = system::GetBoolParameter("const.audio.screenoff_adjust_volume_enable", false); + loudVolumeModeEnable_ = system::GetBoolParameter("const.audio.loudvolume", false); if (volumeApplyToAll_) { audioPolicyConfigManager_.SetNormalVoipFlag(true); } @@ -429,6 +430,161 @@ bool AudioPolicyServer::MaxOrMinVolumeOption(const int32_t &volLevel, const int3 } #endif +#ifdef FEATURE_MULTIMODALINPUT_INPUT +const std::map LOUD_VOL_STREAM_TYPE_ENABLE = { + {STREAM_VOICE_CALL, FUNCTION_HOLD_SYSTEM}, + {STREAM_MUSIC, FUNCTION_HOLD_MUSIC}, + {STREAM_MEDIA, FUNCTION_HOLD_MUSIC}, + {STREAM_MOVIE, FUNCTION_HOLD_MUSIC}, + {STREAM_GAME, FUNCTION_HOLD_MUSIC}, + {STREAM_SPEECH, FUNCTION_HOLD_MUSIC}, + {STREAM_VOICE_MESSAGE, FUNCTION_HOLD_MUSIC}, + {STREAM_NAVIGATION, FUNCTION_HOLD_MUSIC}, + {STREAM_SOURCE_VOICE_CALL, FUNCTION_HOLD_SYSTEM}, + {STREAM_VOICE_COMMUNICATION, FUNCTION_HOLD_SYSTEM}, +}; + +bool FindLoudVolStreamTypeEnable(AudioStreamType streamType, FunctionHoldType &funcHoldType) +{ + auto iter = LOUD_VOL_STREAM_TYPE_ENABLE.find(streamType); + if (iter != LOUD_VOL_STREAM_TYPE_ENABLE.end()) { + funcHoldType = iter->second; + return true; + } + return false; +} + +void AudioPolicyServer::SetLoudVolumeHoldMap(FunctionHoldType funcHoldType, bool state) +{ + std::lock_guard lock(setLoudVolHoldMutex_); + loudVolumeHoldMap_[funcHoldType] = state; +} + +bool AudioPolicyServer::ClearLoudVolumeHoldMap(FunctionHoldType funcHoldType) +{ + std::lock_guard lock(setLoudVolHoldMutex_); + auto it = loudVolumeHoldMap_.find(funcHoldType); + if (it != loudVolumeHoldMap_.end()) { + loudVolumeHoldMap_.erase(it); + return true; + } + return false; +} + +bool AudioPolicyServer::GetLoudVolumeHoldMap(FunctionHoldType funcHoldType, bool &state) +{ + std::lock_guard lock(setLoudVolHoldMutex_); + if (loudVolumeHoldMap_.count(funcHoldType) > 0) { + state = loudVolumeHoldMap_[funcHoldType]; + return true; + } + return false; +} + +bool AudioPolicyServer::ReloadLoudVolumeMode(const AudioStreamType streamInFocus, SetLoudVolMode setVolMode) +{ + if (!loudVolumeModeEnable_) { + return false; + } + FunctionHoldType funcHoldType = FUNCTION_HOLD_INVALID; + if (false == FindLoudVolStreamTypeEnable(streamInFocus, funcHoldType) || + (audioActiveDevice_.GetCurrentOutputDeviceType() != DeviceType::DEVICE_TYPE_SPEAKER)) { + audioVolumeManager_.SendLoudVolumeMode(FUNCTION_HOLD_MUSIC, false); + audioVolumeManager_.SendLoudVolumeMode(FUNCTION_HOLD_SYSTEM, false); + AUDIO_INFO_LOG("streamType = %{public}d, or deviceType = %{public}d not support loud volume mode.", + streamInFocus, audioActiveDevice_.GetCurrentOutputDeviceType()); + return false; + } + if (lastReloadStreamType != streamInFocus) { + if (FUNCTION_HOLD_SYSTEM == funcHoldType) { + audioVolumeManager_.SendLoudVolumeMode(FUNCTION_HOLD_MUSIC, false); + } else if (FUNCTION_HOLD_MUSIC == funcHoldType) { + audioVolumeManager_.SendLoudVolumeMode(FUNCTION_HOLD_SYSTEM, false); + ClearLoudVolumeHoldMap(FUNCTION_HOLD_SYSTEM); + } + } + + if (setVolMode == LOUD_VOLUME_SWITCH_ON) { + if (FUNCTION_HOLD_MUSIC == funcHoldType) { + SetLoudVolumeHoldMap(funcHoldType, true); + } else if (FUNCTION_HOLD_SYSTEM == funcHoldType) { + SetLoudVolumeHoldMap(funcHoldType, false); + } + audioVolumeManager_.SendLoudVolumeMode(funcHoldType, true, true); + } else if (setVolMode == LOUD_VOLUME_SWITCH_OFF) { + ClearLoudVolumeHoldMap(funcHoldType); + audioVolumeManager_.SendLoudVolumeMode(funcHoldType, false); + } else if (setVolMode == LOUD_VOLUME_SWITCH_UNSET) { + bool isHolding = false; + bool ret = GetLoudVolumeHoldMap(funcHoldType, isHolding); + if (ret && isHolding) { + audioVolumeManager_.SendLoudVolumeMode(funcHoldType, true); + } else { + AUDIO_INFO_LOG("no need load loud volume mode"); + } + } else { + AUDIO_ERR_LOG("setVolMode error : %{public}d", setVolMode); + return false; + } + + return true; +} + +bool AudioPolicyServer::CheckLoudVolumeMode(const int32_t volLevel, + const int32_t keyType, const AudioStreamType &streamInFocus) +{ + std::lock_guard lock(loudVolTrigTimeMutex_); + constexpr int32_t MAX_TRIGGER_TIMES = 2; + constexpr int32_t ENABLE_TRIGGER_TIMES = 1; + constexpr int32_t MAX_LOUD_VOLUME_MSEC = 3000; + constexpr int32_t MIN_LOUD_VOLUME_MSEC = 400; + bool isHolding = false; + FunctionHoldType funcHoldType = FUNCTION_HOLD_INVALID; + if (!loudVolumeModeEnable_ && !FindLoudVolStreamTypeEnable(streamInFocus, funcHoldType)) { + return false; + } + + struct timeval tv; + struct timezone tz; + gettimeofday(&tv, &tz); + int64_t mSec = static_cast(tv.tv_sec * 1000 + tv.tv_usec / AUDIO_MS_PER_SECOND); + + int32_t volumeLevelMax = -1; + int32_t streamInFocusInt = static_cast(streamInFocus); + GetMaxVolumeLevel(streamInFocusInt, volumeLevelMax); + int32_t volumeLevelInInt = (keyType == OHOS::MMI::KeyEvent::KEYCODE_VOLUME_UP) ? volLevel + 1 : volLevel - 1; + if (keyType == OHOS::MMI::KeyEvent::KEYCODE_VOLUME_UP && (volumeLevelInInt >= volumeLevelMax)) { + if (GetLoudVolumeHoldMap(funcHoldType, isHolding)) { + AUDIO_DEBUG_LOG("no need to repeatedly set loud volume mode."); + return false; + } + if (triggerTime == MAX_TRIGGER_TIMES && mSec - upTriggerTimeMSec < MAX_LOUD_VOLUME_MSEC) { + triggerTime = 0; + bool ret = ReloadLoudVolumeMode(streamInFocus, LOUD_VOLUME_SWITCH_ON); + CHECK_AND_RETURN_RET_LOG(ret != false, false, "set LoudVolume on error"); + lastReloadStreamType = streamInFocus; + return true; + } else if (triggerTime == ENABLE_TRIGGER_TIMES && (mSec - upTriggerTimeMSec < MAX_LOUD_VOLUME_MSEC) && + (mSec - upTriggerTimeMSec > MIN_LOUD_VOLUME_MSEC)) { + triggerTime++; + } else { + triggerTime = ENABLE_TRIGGER_TIMES; + } + upTriggerTimeMSec = mSec; + } else if (keyType == OHOS::MMI::KeyEvent::KEYCODE_VOLUME_DOWN && GetLoudVolumeHoldMap(funcHoldType, isHolding)) { + upTriggerTimeMSec = mSec; + triggerTime = ENABLE_TRIGGER_TIMES; + bool ret = ReloadLoudVolumeMode(streamInFocus, LOUD_VOLUME_SWITCH_OFF); + CHECK_AND_RETURN_RET_LOG(ret != false, false, "set LoudVolume off error"); + return true; + } else { + upTriggerTimeMSec = 0; + triggerTime = 0; + } + return false; +} +#endif + void AudioPolicyServer::ChangeVolumeOnVoiceAssistant(AudioStreamType &streamInFocus) { if (streamInFocus == AudioStreamType::STREAM_VOICE_ASSISTANT && @@ -584,14 +740,23 @@ int32_t AudioPolicyServer::ProcessVolumeKeyEvents(const int32_t keyType) int32_t AudioPolicyServer::SetVolumeInternalByKeyEvent(AudioStreamType streamInFocus, int32_t zoneId, const int32_t keyType) { + bool updateVol = true; int32_t volumeLevelInInt = GetSystemVolumeLevelInternal(streamInFocus, zoneId); - if (MaxOrMinVolumeOption(volumeLevelInInt, keyType, streamInFocus)) { + if (audioActiveDevice_.GetCurrentOutputDeviceType() == DeviceType::DEVICE_TYPE_SPEAKER && + CheckLoudVolumeMode(volumeLevelInInt, keyType, streamInFocus)) { + updateVol = false; + AUDIO_INFO_LOG("device %{public}d, stream %{public}d, loud volume mode operation", + audioActiveDevice_.GetCurrentOutputDeviceType(), streamInFocus); + } else if (MaxOrMinVolumeOption(volumeLevelInInt, keyType, streamInFocus)) { AUDIO_ERR_LOG("device %{public}d, stream %{public}d, volumelevel %{public}d invalid", audioActiveDevice_.GetCurrentOutputDeviceType(), streamInFocus, volumeLevelInInt); return ERROR_INVALID_PARAM; } - volumeLevelInInt = (keyType == OHOS::MMI::KeyEvent::KEYCODE_VOLUME_UP) ? ++volumeLevelInInt : --volumeLevelInInt; + if (updateVol) { + volumeLevelInInt = (keyType == OHOS::MMI::KeyEvent::KEYCODE_VOLUME_UP) + ? ++volumeLevelInInt : --volumeLevelInInt; + } int32_t ret = SetSystemVolumeLevelInternal(streamInFocus, volumeLevelInInt, true, zoneId); if (ret == ERR_SET_VOL_FAILED_BY_VOLUME_CONTROL_DISABLED) { SendVolumeKeyEventCbWithUpdateUiOrNot(streamInFocus, true); @@ -1532,6 +1697,18 @@ int32_t AudioPolicyServer::SetSystemVolumeLevelInternal(AudioStreamType streamTy return ERR_OPERATION_FAILED; } bool mute = GetStreamMuteInternal(streamType, zoneId); + int32_t volumeLevelMax = -1; + GetMaxVolumeLevel(static_cast(streamType), volumeLevelMax); + int32_t deviceType = audioActiveDevice_.GetCurrentOutputDeviceType(); + if (loudVolumeModeEnable_ && (mute || (isUpdateUi == false && deviceType == DeviceType::DEVICE_TYPE_SPEAKER))) { + int32_t keyCode = (volumeLevelMax > volumeLevel) ? OHOS::MMI::KeyEvent::KEYCODE_VOLUME_DOWN + : OHOS::MMI::KeyEvent::KEYCODE_VOLUME_UP; + keyCode = mute ? OHOS::MMI::KeyEvent::KEYCODE_VOLUME_DOWN : keyCode; + if (CheckLoudVolumeMode(volumeLevel, keyCode, streamType)) { + AUDIO_INFO_LOG("device %{public}d, stream %{public}d, loud volume mode operation", + deviceType, streamType); + } + } if (streamType == STREAM_ALL) { for (auto audioStreamType : GET_STREAM_ALL_VOLUME_TYPES) { AUDIO_INFO_LOG("SetVolume of STREAM_ALL, SteamType = %{public}d, mute = %{public}d, level = %{public}d", @@ -1558,6 +1735,17 @@ int32_t AudioPolicyServer::SetSystemVolumeLevelWithDeviceInternal(AudioStreamTyp AUDIO_ERR_LOG("Unadjustable device, not allow set volume"); return ERR_OPERATION_FAILED; } + + int32_t volumeLevelMax = -1; + GetMaxVolumeLevel(static_cast(streamType), volumeLevelMax); + if (loudVolumeModeEnable_ && isUpdateUi == false && deviceType == DeviceType::DEVICE_TYPE_SPEAKER) { + int32_t keyCode = (volumeLevelMax > volumeLevel) ? OHOS::MMI::KeyEvent::KEYCODE_VOLUME_DOWN + : OHOS::MMI::KeyEvent::KEYCODE_VOLUME_UP; + if (CheckLoudVolumeMode(volumeLevel, keyCode, streamType)) { + AUDIO_INFO_LOG("device %{public}d, stream %{public}d, loud volume mode operation", + deviceType, streamType); + } + } return SetSingleStreamVolumeWithDevice(streamType, volumeLevel, isUpdateUi, deviceType); } diff --git a/services/audio_service/server/src/audio_server.cpp b/services/audio_service/server/src/audio_server.cpp index f7db6667a1..5b77aca809 100644 --- a/services/audio_service/server/src/audio_server.cpp +++ b/services/audio_service/server/src/audio_server.cpp @@ -902,6 +902,8 @@ int32_t AudioServer::SetAudioParameter(const std::string &key, const std::string } else if (key == "mute_call") { deviceManager->SetAudioParameter("primary", parmKey, "", key + "=" + value); return SUCCESS; + } else if (key == "LOUD_VOLUMN_MODE") { + parmKey = AudioParamKey::NONE; } else { AUDIO_ERR_LOG("key %{public}s is invalid for hdi interface", key.c_str()); return SUCCESS; -- Gitee