diff --git a/frameworks/native/audiopolicy/include/audio_policy_manager.h b/frameworks/native/audiopolicy/include/audio_policy_manager.h index 145ba780a205a970c1e3e8f2e08d5cee970aea24..156ddf7a5518c480334dc58dc56a1508a71d59c4 100644 --- a/frameworks/native/audiopolicy/include/audio_policy_manager.h +++ b/frameworks/native/audiopolicy/include/audio_policy_manager.h @@ -248,6 +248,9 @@ public: std::vector> GetAvailableMicrophones(); + int32_t SetDeviceAbsVolumeSupported(const std::string &macAddress, const bool support); + + int32_t SetA2dpDeviceVolume(const std::string &macAddress, const int32_t volume, const bool updateUi); private: AudioPolicyManager() { diff --git a/frameworks/native/bluetoothclient/audio_bluetooth_manager.cpp b/frameworks/native/bluetoothclient/audio_bluetooth_manager.cpp index 42c1a7219dff61dc0e83c63caf3c909a05c4edfa..263340c69cc3bcb862561b2790e85161662b3975 100644 --- a/frameworks/native/bluetoothclient/audio_bluetooth_manager.cpp +++ b/frameworks/native/bluetoothclient/audio_bluetooth_manager.cpp @@ -240,6 +240,23 @@ void AudioA2dpManager::UpdateDeviceListForConfiguration(const BluetoothRemoteDev std::replace_if(connectedA2dpDevices_.begin(), connectedA2dpDevices_.end(), isPresent, device); } +int32_t AudioA2dpManager::SetDeviceAbsVolume(const std::string& macAddress, int32_t volume) +{ + std::lock_guard a2dpDeviceListLock(g_a2dpDeviceListLock); + + // Make sure that the target BluetoothRemoteDevice is connected. + auto isPresent = [&macAddress](const BluetoothRemoteDevice& connectedA2dpDevice) { + return connectedA2dpDevice.GetDeviceAddr() == macAddress; + }; + auto iter = std::find_if(connectedA2dpDevices_.begin(), connectedA2dpDevices_.end(), isPresent); + if (iter == connectedA2dpDevices_.end()) { + AUDIO_ERR_LOG("SetDeviceAbsVolume: the configuring A2DP device doesn't exist."); + return ERROR; + } + + return AvrcpTarget::GetProfile()->SetDeviceAbsoluteVolume(*iter, volume); +} + void AudioA2dpListener::OnConnectionStateChanged(const BluetoothRemoteDevice &device, int state) { AUDIO_INFO_LOG("OnConnectionStateChanged: state: %{public}d", state); diff --git a/frameworks/native/bluetoothclient/audio_bluetooth_manager.h b/frameworks/native/bluetoothclient/audio_bluetooth_manager.h index 7e64586123c4fcd07990145919fcb0c421561770..7f91141986139e7e00e35b00729f3215bb87e2a4 100644 --- a/frameworks/native/bluetoothclient/audio_bluetooth_manager.h +++ b/frameworks/native/bluetoothclient/audio_bluetooth_manager.h @@ -18,6 +18,7 @@ #include "bluetooth_a2dp_src.h" #include "bluetooth_a2dp_codec.h" +#include "bluetooth_avrcp_tg.h" #include "bluetooth_hfp_ag.h" #include "idevice_status_observer.h" @@ -53,6 +54,7 @@ public: static void UpdateDeviceListWhenConnecting(const BluetoothRemoteDevice& device); static void UpdateDeviceListWhenDisconnecting(const BluetoothRemoteDevice& device); static void UpdateDeviceListForConfiguration(const BluetoothRemoteDevice& device); + static int32_t SetDeviceAbsVolume(const std::string& macAddress, int32_t volume); static void SetConnectionState(int state) { diff --git a/interfaces/inner_api/native/audiocommon/include/audio_info.h b/interfaces/inner_api/native/audiocommon/include/audio_info.h index 5fe40c9c74aebd61832afbdec1d6c3adfb4ef026..02020c1c590f7b2a4ef4cd05041d5b730b6319e1 100644 --- a/interfaces/inner_api/native/audiocommon/include/audio_info.h +++ b/interfaces/inner_api/native/audiocommon/include/audio_info.h @@ -244,6 +244,12 @@ struct AudioParameters { DeviceType deviceType; }; +struct A2dpDeviceConfigInfo { + AudioStreamInfo streamInfo; + bool absVolumeSupport; + int32_t volumeLevel; +}; + struct AudioRendererInfo { ContentType contentType = CONTENT_TYPE_UNKNOWN; StreamUsage streamUsage = STREAM_USAGE_UNKNOWN; diff --git a/interfaces/inner_api/native/audiomanager/include/audio_system_manager.h b/interfaces/inner_api/native/audiomanager/include/audio_system_manager.h index 17b72dea2b19d73a22d603904b8ca7ffcbf2c35d..6668150ed7469acc575b3662c9dda75754f027fc 100644 --- a/interfaces/inner_api/native/audiomanager/include/audio_system_manager.h +++ b/interfaces/inner_api/native/audiomanager/include/audio_system_manager.h @@ -963,6 +963,22 @@ public: int32_t SetWakeUpSourceCloseCallback(const std::shared_ptr &callback); + /** + * @brief Set whether or not absolute volume is supported for the specified Bluetooth device + * + * @return Returns success or not + * @since 11 + */ + int32_t SetDeviceAbsVolumeSupported(const std::string &macAddress, const bool support); + + /** + * @brief Set the absolute volume value for the specified Bluetooth device + * + * @return Returns success or not + * @since 11 + */ + int32_t SetA2dpDeviceVolume(const std::string &macAddress, const int32_t volume, const bool updateUi); + static void AudioServerDied(pid_t pid); private: class WakeUpCallbackImpl : public WakeUpSourceCallback { diff --git a/services/audio_policy/client/include/audio_policy_base.h b/services/audio_policy/client/include/audio_policy_base.h index be06c91372b062a4435e876ef1e2cc40f498649f..685b70422d73407065d5958c76b096bd460eee4c 100644 --- a/services/audio_policy/client/include/audio_policy_base.h +++ b/services/audio_policy/client/include/audio_policy_base.h @@ -223,6 +223,10 @@ public: virtual std::vector> GetAudioCapturerMicrophoneDescriptors(int32_t sessionId) = 0; virtual std::vector> GetAvailableMicrophones() = 0; + + virtual int32_t SetDeviceAbsVolumeSupported(const std::string &macAddress, const bool support) = 0; + + virtual int32_t SetA2dpDeviceVolume(const std::string &macAddress, const int32_t volume, bool updateUi) = 0; public: DECLARE_INTERFACE_DESCRIPTOR(u"IAudioPolicy"); }; diff --git a/services/audio_policy/client/include/audio_policy_manager_stub.h b/services/audio_policy/client/include/audio_policy_manager_stub.h index d9db2e4d47bcc6e571b02cbdae01398a6e88ada6..c2c2a6892a871f2a532fe5275741dee4d651e150 100644 --- a/services/audio_policy/client/include/audio_policy_manager_stub.h +++ b/services/audio_policy/client/include/audio_policy_manager_stub.h @@ -114,6 +114,8 @@ private: void GetHardwareOutputSamplingRateInternal(MessageParcel &data, MessageParcel &reply); void GetAudioCapturerMicrophoneDescriptorsInternal(MessageParcel &data, MessageParcel &reply); void GetAvailableMicrophonesInternal(MessageParcel &data, MessageParcel &reply); + void SetDeviceAbsVolumeSupportedInternal(MessageParcel &data, MessageParcel &reply); + void SetA2dpDeviceVolumeInternal(MessageParcel &data, MessageParcel &reply); void ReadStreamChangeInfo(MessageParcel &data, const AudioMode &mode, AudioStreamChangeInfo &streamChangeInfo); void WriteAudioFocusInfo(MessageParcel &data, const std::pair &focusInfo); @@ -208,6 +210,8 @@ private: &AudioPolicyManagerStub::GetHardwareOutputSamplingRateInternal, &AudioPolicyManagerStub::GetAudioCapturerMicrophoneDescriptorsInternal, &AudioPolicyManagerStub::GetAvailableMicrophonesInternal, + &AudioPolicyManagerStub::SetDeviceAbsVolumeSupportedInternal, + &AudioPolicyManagerStub::SetA2dpDeviceVolumeInternal, }; }; } // namespace AudioStandard diff --git a/services/audio_policy/client/include/audio_policy_proxy.h b/services/audio_policy/client/include/audio_policy_proxy.h index 0d77a0c8cbcf607b0b314c62b6318c40caee8a6d..a4eb26937681cace49e2ed668b79cb7c3ff1e144 100644 --- a/services/audio_policy/client/include/audio_policy_proxy.h +++ b/services/audio_policy/client/include/audio_policy_proxy.h @@ -215,6 +215,10 @@ public: std::vector> GetAudioCapturerMicrophoneDescriptors(int32_t sessionId) override; std::vector> GetAvailableMicrophones() override; + + int32_t SetDeviceAbsVolumeSupported(const std::string &macAddress, const bool support) override; + + int32_t SetA2dpDeviceVolume(const std::string &macAddress, const int32_t volume, const bool updateUi) override; private: static inline BrokerDelegator mDdelegator; void WriteStreamChangeInfo(MessageParcel &data, const AudioMode &mode, diff --git a/services/audio_policy/client/src/audio_policy_manager.cpp b/services/audio_policy/client/src/audio_policy_manager.cpp index ba528f82708e47400d703cc23532ea85fe63a4ec..f3ba49e48cd2f8443eed430dc4d37d2fb82f97d9 100644 --- a/services/audio_policy/client/src/audio_policy_manager.cpp +++ b/services/audio_policy/client/src/audio_policy_manager.cpp @@ -1300,5 +1300,26 @@ vector> AudioPolicyManager::GetAvailableMicrophones() } return gsp->GetAvailableMicrophones(); } + +int32_t AudioPolicyManager::SetDeviceAbsVolumeSupported(const std::string &macAddress, const bool support) +{ + const sptr gsp = GetAudioPolicyManagerProxy(); + if (gsp == nullptr) { + AUDIO_ERR_LOG("SetDeviceAbsVolumeSupported: audio policy manager proxy is NULL."); + return ERROR; + } + return gsp->SetDeviceAbsVolumeSupported(macAddress, support); +} + +int32_t AudioPolicyManager::SetA2dpDeviceVolume(const std::string &macAddress, const int32_t volume, + const bool updateUi) +{ + const sptr gsp = GetAudioPolicyManagerProxy(); + if (gsp == nullptr) { + AUDIO_ERR_LOG("SetA2dpDeviceVolume: audio policy manager proxy is NULL."); + return ERROR; + } + return gsp->SetA2dpDeviceVolume(macAddress, volume, updateUi); +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_policy/client/src/audio_policy_proxy.cpp b/services/audio_policy/client/src/audio_policy_proxy.cpp index 5221027b8cb81a07c48ef76fda78cb1268ac520c..69ae8cb998992c0f8fb1e5524b5b544d6530f67b 100644 --- a/services/audio_policy/client/src/audio_policy_proxy.cpp +++ b/services/audio_policy/client/src/audio_policy_proxy.cpp @@ -2177,5 +2177,51 @@ std::vector> AudioPolicyProxy::GetAvailableMicrophone return micDescs; } + +int32_t AudioPolicyProxy::SetDeviceAbsVolumeSupported(const std::string &macAddress, const bool support) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + AUDIO_ERR_LOG(" SetDeviceAbsVolumeSupported WriteInterfaceToken failed"); + return ERROR; + } + data.WriteString(macAddress); + data.WriteBool(support); + + int32_t error = Remote()->SendRequest( + static_cast(AudioPolicyInterfaceCode::SET_DEVICE_ABSOLUTE_VOLUME_SUPPORTED), data, reply, option); + if (error != ERR_NONE) { + AUDIO_ERR_LOG("SetDeviceAbsVolumeSupported failed, error: %d", error); + return ERROR; + } + return reply.ReadInt32(); +} + +int32_t AudioPolicyProxy::SetA2dpDeviceVolume(const std::string &macAddress, const int32_t volume, + const bool updateUi) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + AUDIO_ERR_LOG(" SetDeviceAbsVolumeSupported WriteInterfaceToken failed"); + return ERROR; + } + data.WriteString(macAddress); + data.WriteInt32(volume); + data.WriteBool(updateUi); + + int32_t error = Remote()->SendRequest( + static_cast(AudioPolicyInterfaceCode::SET_A2DP_DEVICE_VOLUME), data, reply, option); + if (error != ERR_NONE) { + AUDIO_ERR_LOG("SetDeviceAbsVolumeSupported failed, error: %d", error); + return ERROR; + } + return reply.ReadInt32(); +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_policy/common/include/audio_policy_ipc_interface_code.h b/services/audio_policy/common/include/audio_policy_ipc_interface_code.h index a4236952cfed248a1ee1374aa5a586eb92aac74d..9f4c8a77c5333172e2aa0780cd0b3c288f5fb62f 100644 --- a/services/audio_policy/common/include/audio_policy_ipc_interface_code.h +++ b/services/audio_policy/common/include/audio_policy_ipc_interface_code.h @@ -110,7 +110,9 @@ enum class AudioPolicyInterfaceCode { GET_HARDWARE_OUTPUT_SAMPLING_RATE, GET_AUDIO_CAPTURER_MICROPHONE_DESCRIPTORS, GET_AVAILABLE_MICROPHONE_DESCRIPTORS, - AUDIO_POLICY_MANAGER_CODE_MAX = GET_AVAILABLE_MICROPHONE_DESCRIPTORS, + SET_DEVICE_ABSOLUTE_VOLUME_SUPPORTED, + SET_A2DP_DEVICE_VOLUME, + AUDIO_POLICY_MANAGER_CODE_MAX = SET_A2DP_DEVICE_VOLUME, }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_policy/server/include/audio_policy_server.h b/services/audio_policy/server/include/audio_policy_server.h index 8581a62035aaa8956864ade22312039fbe08698b..dc1d1edb7dccaa9893cb14fa8869bc490dc51196 100644 --- a/services/audio_policy/server/include/audio_policy_server.h +++ b/services/audio_policy/server/include/audio_policy_server.h @@ -279,6 +279,10 @@ public: vector> GetAvailableMicrophones() override; + int32_t SetDeviceAbsVolumeSupported(const std::string &macAddress, const bool support) override; + + int32_t SetA2dpDeviceVolume(const std::string &macAddress, const int32_t volume, const bool updateUi) override; + class RemoteParameterCallback : public AudioParameterCallback { public: RemoteParameterCallback(sptr server); diff --git a/services/audio_policy/server/include/service/audio_policy_service.h b/services/audio_policy/server/include/service/audio_policy_service.h index e53bb485f3a22d0679fc6f18e5d3d42f93051861..56162e7e08d9290fe357c78fe17647da8b0af24d 100644 --- a/services/audio_policy/server/include/service/audio_policy_service.h +++ b/services/audio_policy/server/include/service/audio_policy_service.h @@ -305,6 +305,10 @@ public: vector> GetAudioCapturerMicrophoneDescriptors(int32_t sessionId); vector> GetAvailableMicrophones(); + + int32_t SetDeviceAbsVolumeSupported(const std::string &macAddress, const bool support); + + int32_t SetA2dpDeviceVolume(const std::string &macAddress, const int32_t volume); private: AudioPolicyService() :audioPolicyManager_(AudioPolicyManagerFactory::GetAudioPolicyManager()), @@ -517,6 +521,7 @@ private: std::string localDevicesType_ = ""; std::mutex routerMapMutex_; // unordered_map is not concurrently-secure + mutable std::mutex a2dpDeviceMapMutex_; std::mutex preferredInputMapMutex_; std::unordered_map> routerMap_; std::unordered_map> fastRouterMap_; // key:uid value: @@ -533,7 +538,7 @@ private: std::vector> connectedDevices_; std::vector> connectedMicrophones_; std::unordered_map> audioCaptureMicrophoneDescriptor_; - std::unordered_map connectedA2dpDeviceMap_; + std::unordered_map connectedA2dpDeviceMap_; std::string activeBTDevice_; std::map, sptr> deviceChangeCbsMap_; diff --git a/services/audio_policy/server/include/service/interface/iaudio_policy_interface.h b/services/audio_policy/server/include/service/interface/iaudio_policy_interface.h index 8dea4cc3d916580f4620742d6f42b294ade9c44e..5d8d3fcd985fe87830101a55d5f3856c702af6b2 100644 --- a/services/audio_policy/server/include/service/interface/iaudio_policy_interface.h +++ b/services/audio_policy/server/include/service/interface/iaudio_policy_interface.h @@ -106,6 +106,10 @@ public: virtual void GetStreamVolumeInfoMap(StreamVolumeInfoMap &streamVolumeInfos); + virtual void SetAbsVolumeScene(bool isAbsVolumeScene) = 0; + + virtual bool GetAbsVolumeScene() const = 0; + virtual float GetSystemVolumeInDb(AudioVolumeType volumeType, int32_t volumeLevel, DeviceType deviceType) = 0; }; } // namespace AudioStandard diff --git a/services/audio_policy/server/include/service/manager/audio_adapter_manager.h b/services/audio_policy/server/include/service/manager/audio_adapter_manager.h index c72597dd2562cebf78e3e30a9c40c6daa84179c0..263b40e853800dcc539a89058ef7573cffdc6fd9 100644 --- a/services/audio_policy/server/include/service/manager/audio_adapter_manager.h +++ b/services/audio_policy/server/include/service/manager/audio_adapter_manager.h @@ -132,6 +132,10 @@ public: float GetSystemVolumeInDb(AudioVolumeType volumeType, int32_t volumeLevel, DeviceType deviceType); bool IsUseNonlinearAlgo() { return useNonlinearAlgo_; } + + void SetAbsVolumeScene(bool isAbsVolumeScene); + + bool GetAbsVolumeScene() const; private: friend class PolicyCallbackImpl; @@ -222,6 +226,7 @@ private: bool testModeOn_ {false}; float getSystemVolumeInDb_; bool useNonlinearAlgo_; + bool isAbsVolumeScene_ = false; }; class PolicyCallbackImpl : public AudioServiceAdapterCallback { @@ -245,6 +250,12 @@ public: return 0.0f; } + bool isAbsVolumeScene = audioAdapterManager_->GetAbsVolumeScene(); + DeviceType activeDevice = audioAdapterManager_->GetActiveDevice(); + if (activeDevice == DEVICE_TYPE_BLUETOOTH_A2DP && isAbsVolumeScene) { + return 1.0f; + } + int32_t volumeLevel = audioAdapterManager_->volumeLevelMap_[streamForVolumeMap]; float volumeDb = 1.0f; if (audioAdapterManager_->IsUseNonlinearAlgo()) { diff --git a/services/audio_policy/server/src/audio_policy_manager_stub.cpp b/services/audio_policy/server/src/audio_policy_manager_stub.cpp index b6def0f78ea8dd6530b661f67254f24cfee6a7ee..d50e07ad14a084c61dbbf9451d8f4ecbe49fbc00 100644 --- a/services/audio_policy/server/src/audio_policy_manager_stub.cpp +++ b/services/audio_policy/server/src/audio_policy_manager_stub.cpp @@ -992,6 +992,23 @@ void AudioPolicyManagerStub::GetAvailableMicrophonesInternal(MessageParcel &data } } +void AudioPolicyManagerStub::SetDeviceAbsVolumeSupportedInternal(MessageParcel &data, MessageParcel &reply) +{ + std::string macAddress = data.ReadString(); + bool support = data.ReadBool(); + int32_t result = SetDeviceAbsVolumeSupported(macAddress, support); + reply.WriteInt32(result); +} + +void AudioPolicyManagerStub::SetA2dpDeviceVolumeInternal(MessageParcel &data, MessageParcel &reply) +{ + std::string macAddress = data.ReadString(); + int32_t volume = data.ReadInt32(); + bool updateUi = data.ReadBool(); + int32_t result = SetA2dpDeviceVolume(macAddress, volume, updateUi); + reply.WriteInt32(result); +} + int AudioPolicyManagerStub::OnRemoteRequest( uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { diff --git a/services/audio_policy/server/src/audio_policy_server.cpp b/services/audio_policy/server/src/audio_policy_server.cpp index 571825633c845de3f808362d1c06bb7c4097432d..a01aa438937d41400fc71c4f48ece1b102dc7cf1 100644 --- a/services/audio_policy/server/src/audio_policy_server.cpp +++ b/services/audio_policy/server/src/audio_policy_server.cpp @@ -70,6 +70,7 @@ constexpr uid_t UID_DISTRIBUTED_AUDIO_SA = 3055; constexpr uid_t UID_MEDIA_SA = 1013; constexpr uid_t UID_AUDIO = 1041; constexpr uid_t UID_FOUNDATION_SA = 5523; +constexpr uid_t UID_BLUETOOTH_SA = 1002; REGISTER_SYSTEM_ABILITY_BY_ID(AudioPolicyServer, AUDIO_POLICY_SERVICE_ID, true) @@ -2503,5 +2504,45 @@ vector> AudioPolicyServer::GetAvailableMicrophones() vector> micDescs = mPolicyService.GetAvailableMicrophones(); return micDescs; } + +int32_t AudioPolicyServer::SetDeviceAbsVolumeSupported(const std::string &macAddress, const bool support) +{ + auto callerUid = IPCSkeleton::GetCallingUid(); + if (callerUid != UID_BLUETOOTH_SA) { + AUDIO_ERR_LOG("SetDeviceAbsVolumeSupported: Error caller uid: %{public}d", callerUid); + return ERROR; + } + return mPolicyService.SetDeviceAbsVolumeSupported(macAddress, support); +} + +int32_t AudioPolicyServer::SetA2dpDeviceVolume(const std::string &macAddress, const int32_t volume, + const bool updateUi) +{ + auto callerUid = IPCSkeleton::GetCallingUid(); + if (callerUid != UID_BLUETOOTH_SA) { + AUDIO_ERR_LOG("SetA2dpDeviceVolume: Error caller uid: %{public}d", callerUid); + return ERROR; + } + int32_t ret = mPolicyService.SetA2dpDeviceVolume(macAddress, volume); + if (ret == SUCCESS) { + for (auto it = volumeChangeCbsMap_.begin(); it != volumeChangeCbsMap_.end(); ++it) { + std::shared_ptr volumeChangeCb = it->second; + if (volumeChangeCb == nullptr) { + AUDIO_ERR_LOG("volumeChangeCb: nullptr for client : %{public}d", it->first); + continue; + } + + AUDIO_DEBUG_LOG("SetA2dpDeviceVolume trigger volumeChangeCb clientPid : %{public}d", it->first); + VolumeEvent volumeEvent; + volumeEvent.volumeType = STREAM_MUSIC; + volumeEvent.volume = volume; + volumeEvent.updateUi = updateUi; + volumeEvent.volumeGroupId = 0; + volumeEvent.networkId = LOCAL_NETWORK_ID; + volumeChangeCb->OnVolumeKeyEvent(volumeEvent); + } + } + return ret; +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_policy/server/src/service/audio_policy_service.cpp b/services/audio_policy/server/src/service/audio_policy_service.cpp index 59a6df82cce95dc5d6821945de992b0faa2f466f..39cf305d97c91b0657c2ddbd67147bd7f984dcb2 100644 --- a/services/audio_policy/server/src/service/audio_policy_service.cpp +++ b/services/audio_policy/server/src/service/audio_policy_service.cpp @@ -60,6 +60,7 @@ const uint32_t PCM_16_BIT = 16; const uint32_t PCM_24_BIT = 24; const uint32_t PCM_32_BIT = 32; const uint32_t BT_BUFFER_ADJUSTMENT_FACTOR = 50; +const uint32_t ABS_VOLUME_SUPPORT_RETRY_INTERVAL_IN_MICROSECONDS = 10000; const std::string AUDIO_SERVICE_PKG = "audio_manager_service"; const uint32_t PRIORITY_LIST_OFFSET_POSTION = 1; std::shared_ptr g_dataShareHelper = nullptr; @@ -231,7 +232,20 @@ int32_t AudioPolicyService::GetMinVolumeLevel(AudioVolumeType volumeType) const int32_t AudioPolicyService::SetSystemVolumeLevel(AudioStreamType streamType, int32_t volumeLevel, bool isFromVolumeKey) { - int32_t result = audioPolicyManager_.SetSystemVolumeLevel(streamType, volumeLevel, isFromVolumeKey); + int32_t result = SUCCESS; + // if current active device's type is DEVICE_TYPE_BLUETOOTH_A2DP and it support absolute volume, set + // its absolute volume value. + if (currentActiveDevice_.deviceType_ == DEVICE_TYPE_BLUETOOTH_A2DP) { + result = SetA2dpDeviceVolume(activeBTDevice_, volumeLevel); + if (result != SUCCESS) { + AUDIO_ERR_LOG("AudioPolicyService::SetSystemVolumeLevel set abs volume failed"); + return result; + } + // set to avrcp device + return Bluetooth::AudioA2dpManager::SetDeviceAbsVolume(activeBTDevice_, volumeLevel); + } + + result = audioPolicyManager_.SetSystemVolumeLevel(streamType, volumeLevel, isFromVolumeKey); if (result == SUCCESS && streamType == STREAM_VOICE_CALL) { SetVoiceCallVolume(volumeLevel); } @@ -300,6 +314,20 @@ std::string AudioPolicyService::GetVolumeGroupType(DeviceType deviceType) int32_t AudioPolicyService::GetSystemVolumeLevel(AudioStreamType streamType, bool isFromVolumeKey) const { + { + // if current active device's type is DEVICE_TYPE_BLUETOOTH_A2DP and it support absolute volume, get + // its absolute volume value. + std::lock_guard lock(a2dpDeviceMapMutex_); + if (currentActiveDevice_.deviceType_ == DEVICE_TYPE_BLUETOOTH_A2DP) { + auto configInfoPos = connectedA2dpDeviceMap_.find(activeBTDevice_); + if (configInfoPos != connectedA2dpDeviceMap_.end() + && configInfoPos->second.absVolumeSupport) { + return configInfoPos->second.volumeLevel; + } else { + AUDIO_ERR_LOG("Get absolute volume failed for activeBTDevice :[%{public}s]", activeBTDevice_.c_str()); + } + } + } return audioPolicyManager_.GetSystemVolumeLevel(streamType, isFromVolumeKey); } @@ -2015,12 +2043,13 @@ void AudioPolicyService::OnUpdateRouteSupport(bool isSupported) bool AudioPolicyService::GetActiveDeviceStreamInfo(DeviceType deviceType, AudioStreamInfo &streamInfo) { + std::lock_guard lock(a2dpDeviceMapMutex_); if (deviceType == DEVICE_TYPE_BLUETOOTH_A2DP) { - auto streamInfoPos = connectedA2dpDeviceMap_.find(activeBTDevice_); - if (streamInfoPos != connectedA2dpDeviceMap_.end()) { - streamInfo.samplingRate = streamInfoPos->second.samplingRate; - streamInfo.format = streamInfoPos->second.format; - streamInfo.channels = streamInfoPos->second.channels; + auto configInfoPos = connectedA2dpDeviceMap_.find(activeBTDevice_); + if (configInfoPos != connectedA2dpDeviceMap_.end()) { + streamInfo.samplingRate = configInfoPos->second.streamInfo.samplingRate; + streamInfo.format = configInfoPos->second.streamInfo.format; + streamInfo.channels = configInfoPos->second.streamInfo.channels; return true; } } @@ -2161,9 +2190,13 @@ int32_t AudioPolicyService::HandleLocalDeviceConnected(DeviceType devType, const const std::string& deviceName, const AudioStreamInfo& streamInfo) { AUDIO_INFO_LOG("[%{public}s], macAddress:[%{public}s]", __func__, macAddress.c_str()); - if (devType == DEVICE_TYPE_BLUETOOTH_A2DP) { - connectedA2dpDeviceMap_.insert(make_pair(macAddress, streamInfo)); - activeBTDevice_ = macAddress; + { + std::lock_guard lock(a2dpDeviceMapMutex_); + if (devType == DEVICE_TYPE_BLUETOOTH_A2DP) { + A2dpDeviceConfigInfo configInfo = {streamInfo, false}; + connectedA2dpDeviceMap_.insert(make_pair(macAddress, configInfo)); + activeBTDevice_ = macAddress; + } } // new device found. If connected, add into active device list @@ -2229,6 +2262,7 @@ int32_t AudioPolicyService::HandleLocalDeviceDisconnected(DeviceType devType, co void AudioPolicyService::UpdateActiveA2dpDeviceWhenDisconnecting(const std::string& macAddress, bool& isActiveA2dpDevice) { + std::lock_guard lock(a2dpDeviceMapMutex_); connectedA2dpDeviceMap_.erase(macAddress); if (connectedA2dpDeviceMap_.size() == 0) { @@ -2335,9 +2369,9 @@ void AudioPolicyService::OnDeviceStatusUpdated(DeviceType devType, bool isConnec if (devType == DEVICE_TYPE_BLUETOOTH_A2DP && GetAudioScene() == AUDIO_SCENE_PHONE_CALL) { // If the A2DP device is connecting when calling, add it to connectedDevices_ and donot activate it now AUDIO_INFO_LOG("A2DP device should be used in non-call mode [%{public}d]", GetAudioScene()); - connectedA2dpDeviceMap_.insert(make_pair(macAddress, streamInfo)); + A2dpDeviceConfigInfo configInfo = {streamInfo, false}; + connectedA2dpDeviceMap_.insert(make_pair(macAddress, configInfo)); activeBTDevice_ = macAddress; - TriggerDeviceChangedCallback(deviceChangeDescriptor, isConnected); UpdateTrackerDeviceChange(deviceChangeDescriptor); return; @@ -2394,7 +2428,7 @@ void AudioPolicyService::OnDeviceConfigurationChanged(DeviceType deviceType, con = (streamInfo.samplingRate * GetSampleFormatValue(streamInfo.format) * streamInfo.channels) / (PCM_8_BIT * BT_BUFFER_ADJUSTMENT_FACTOR); AUDIO_DEBUG_LOG("Updated buffer size: %{public}d", bufferSize); - connectedA2dpDeviceMap_[macAddress] = streamInfo; + connectedA2dpDeviceMap_[macAddress].streamInfo = streamInfo; auto a2dpModulesPos = deviceClassInfo_.find(ClassType::TYPE_A2DP); if (a2dpModulesPos != deviceClassInfo_.end()) { @@ -3560,6 +3594,48 @@ void AudioPolicyService::UpdateDescWhenNoBTPermission(vector lock(a2dpDeviceMapMutex_); + // Maximum number of attempts, preventing situations where a2dp device has not yet finished coming online. + int maxRetries = 3; + int retryCount = 0; + while (retryCount < maxRetries) { + retryCount++; + auto configInfoPos = connectedA2dpDeviceMap_.find(macAddress); + if (configInfoPos != connectedA2dpDeviceMap_.end()) { + configInfoPos->second.absVolumeSupport = support; + + audioPolicyManager_.SetAbsVolumeScene(true); + break; + } + if (retryCount == maxRetries) { + AUDIO_ERR_LOG("SetDeviceAbsVolumeSupported failed, can't find device for macAddress:[%{public}s]", + macAddress.c_str()); + return ERROR; + } + usleep(ABS_VOLUME_SUPPORT_RETRY_INTERVAL_IN_MICROSECONDS); + } + + AUDIO_INFO_LOG("SetDeviceAbsVolumeSupported success for macAddress:[%{public}s], support: %{public}d", + macAddress.c_str(), support); + return SUCCESS; +} + +int32_t AudioPolicyService::SetA2dpDeviceVolume(const std::string &macAddress, const int32_t volumeLevel) +{ + std::lock_guard lock(a2dpDeviceMapMutex_); + auto configInfoPos = connectedA2dpDeviceMap_.find(macAddress); + if (configInfoPos == connectedA2dpDeviceMap_.end() || !configInfoPos->second.absVolumeSupport) { + AUDIO_ERR_LOG("SetA2dpDeviceVolume failed for macAddress:[%{public}s]", macAddress.c_str()); + return ERROR; + } + configInfoPos->second.volumeLevel = volumeLevel; + AUDIO_INFO_LOG("SetA2dpDeviceVolume success for macaddress:[%{public}s], volume value:[%{public}d]", + macAddress.c_str(), volumeLevel); + return SUCCESS; +} + void AudioPolicyService::TriggerDeviceChangedCallback(const vector> &desc, bool isConnected) { Trace trace("AudioPolicyService::TriggerDeviceChangedCallback"); diff --git a/services/audio_policy/server/src/service/manager/audio_adapter_manager.cpp b/services/audio_policy/server/src/service/manager/audio_adapter_manager.cpp index e34abb6ab0878271b63752559125c37e97255384..79b3368fb77250aeb6fcdb3d6a91e6a4a8398b39 100644 --- a/services/audio_policy/server/src/service/manager/audio_adapter_manager.cpp +++ b/services/audio_policy/server/src/service/manager/audio_adapter_manager.cpp @@ -1426,5 +1426,15 @@ DeviceType AudioAdapterManager::GetActiveDevice() { return currentActiveDevice_; } + +void AudioAdapterManager::SetAbsVolumeScene(bool isAbsVolumeScene) +{ + isAbsVolumeScene_ = isAbsVolumeScene; +} + +bool AudioAdapterManager::GetAbsVolumeScene() const +{ + return isAbsVolumeScene_; +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/client/src/audio_system_manager.cpp b/services/audio_service/client/src/audio_system_manager.cpp index 1cc03289bb0994b6256bff99d4df2dd46f141d13..08689ca2aec269232b90430924cfe0db392cf43e 100644 --- a/services/audio_service/client/src/audio_system_manager.cpp +++ b/services/audio_service/client/src/audio_system_manager.cpp @@ -1122,6 +1122,19 @@ void AudioSystemManager::RequestThreadPriority(uint32_t tid) gasp->RequestThreadPriority(tid, bundleName); } +int32_t AudioSystemManager::SetDeviceAbsVolumeSupported(const std::string &macAddress, const bool support) +{ + AUDIO_INFO_LOG("AudioSystemManager::SetDeviceAbsVolumeSupported"); + return AudioPolicyManager::GetInstance().SetDeviceAbsVolumeSupported(macAddress, support); +} + +int32_t AudioSystemManager::SetA2dpDeviceVolume(const std::string &macAddress, const int32_t volume, + const bool updateUi) +{ + AUDIO_INFO_LOG("AudioSystemManager::SetA2dpDeviceVolume"); + return AudioPolicyManager::GetInstance().SetA2dpDeviceVolume(macAddress, volume, updateUi); +} + AudioPin AudioSystemManager::GetPinValueFromType(DeviceType deviceType, DeviceRole deviceRole) const { AudioPin pin = AUDIO_PIN_NONE; diff --git a/test/fuzztest/audiopolicyanother_fuzzer/audio_policy_another_fuzzer.cpp b/test/fuzztest/audiopolicyanother_fuzzer/audio_policy_another_fuzzer.cpp index 712a3bc2650af770c9708c94a6edc01c4bb27b16..60fff14f2386f52b7c4ec6d081ca44615191eea5 100644 --- a/test/fuzztest/audiopolicyanother_fuzzer/audio_policy_another_fuzzer.cpp +++ b/test/fuzztest/audiopolicyanother_fuzzer/audio_policy_another_fuzzer.cpp @@ -195,6 +195,13 @@ void AudioPolicyFuzzTest(const uint8_t *rawData, size_t size) AudioPolicyServerPtr->GetHardwareOutputSamplingRate(deviceDescriptor); AudioPolicyServerPtr->GetAvailableMicrophones(); + + std::string macAddress(reinterpret_cast(rawData), size - 1); + bool support = *reinterpret_cast(rawData); + int32_t volume = *reinterpret_cast(rawData); + bool updateUi = *reinterpret_cast(rawData); + AudioPolicyServerPtr->SetDeviceAbsVolumeSupported(macAddress, support); + AudioPolicyServerPtr->SetA2dpDeviceVolume(macAddress, volume, updateUi); } void AudioVolumeKeyCallbackStub(const uint8_t *rawData, size_t size)