diff --git a/frameworks/native/audioutils/include/audio_utils.h b/frameworks/native/audioutils/include/audio_utils.h index 614f9e399d45f3ee456ef0ab83664b1611f1d359..011d1ee775422421ed3a594acf29578d3a6ded80 100644 --- a/frameworks/native/audioutils/include/audio_utils.h +++ b/frameworks/native/audioutils/include/audio_utils.h @@ -21,6 +21,14 @@ namespace OHOS { namespace AudioStandard { int64_t GetNowTimeMs(); +void AdjustStereoToMonoForPCM8Bit(int8_t *data, uint64_t len); +void AdjustStereoToMonoForPCM16Bit(int16_t *data, uint64_t len); +void AdjustStereoToMonoForPCM24Bit(int8_t *data, uint64_t len); +void AdjustStereoToMonoForPCM32Bit(int32_t *data, uint64_t len); +void AdjustAudioBalanceForPCM8Bit(int8_t *data, uint64_t len, float left, float right); +void AdjustAudioBalanceForPCM16Bit(int16_t *data, uint64_t len, float left, float right); +void AdjustAudioBalanceForPCM24Bit(int8_t *data, uint64_t len, float left, float right); +void AdjustAudioBalanceForPCM32Bit(int32_t *data, uint64_t len, float left, float right); template bool GetSysPara(const char *key, T &value); diff --git a/frameworks/native/audioutils/src/audio_utils.cpp b/frameworks/native/audioutils/src/audio_utils.cpp index 30635c1f130334d2cf32da757dbf2bc5651bf31e..8711f7455c35d402a710a8d6cdd8d1fc01508698 100644 --- a/frameworks/native/audioutils/src/audio_utils.cpp +++ b/frameworks/native/audioutils/src/audio_utils.cpp @@ -22,6 +22,10 @@ #include "audio_log.h" namespace OHOS { namespace AudioStandard { +namespace { +const uint32_t STEREO_CHANNEL_COUNT = 2; +} // namespace + int64_t GetNowTimeMs() { std::chrono::milliseconds nowMs = @@ -29,6 +33,90 @@ int64_t GetNowTimeMs() return nowMs.count(); } +void AdjustStereoToMonoForPCM8Bit(int8_t *data, uint64_t len) +{ + for (unsigned i = len >> 1; i > 0; i--) { + data[0] = data[0] / STEREO_CHANNEL_COUNT + data[1] / STEREO_CHANNEL_COUNT; + data[1] = data[0]; + data += STEREO_CHANNEL_COUNT; + } +} + +void AdjustStereoToMonoForPCM16Bit(int16_t *data, uint64_t len) +{ + for (unsigned i = len >> 1; i > 0; i--) { + data[0] = data[0] / STEREO_CHANNEL_COUNT + data[1] / STEREO_CHANNEL_COUNT; + data[1] = data[0]; + data += STEREO_CHANNEL_COUNT; + } +} + +void AdjustStereoToMonoForPCM24Bit(int8_t *data, uint64_t len) +{ + // int8_t is used for reading data of PCM24BIT here. + // 24 / 8 = 3, so we need repeat the calculation three times. + for (unsigned i = len >> 1; i > 0; i--) { + data[0] = data[0] / STEREO_CHANNEL_COUNT + data[3] / STEREO_CHANNEL_COUNT; + data[3] = data[0]; + data[1] = data[1] / STEREO_CHANNEL_COUNT + data[4] / STEREO_CHANNEL_COUNT; + data[4] = data[1]; + data[2] = data[2] / STEREO_CHANNEL_COUNT + data[5] / STEREO_CHANNEL_COUNT; + data[5] = data[2]; + data += (STEREO_CHANNEL_COUNT * 3); + } +} + +void AdjustStereoToMonoForPCM32Bit(int32_t *data, uint64_t len) +{ + for (unsigned i = len >> 1; i > 0; i--) { + data[0] = data[0] / STEREO_CHANNEL_COUNT + data[1] / STEREO_CHANNEL_COUNT; + data[1] = data[0]; + data += STEREO_CHANNEL_COUNT; + } +} + +void AdjustAudioBalanceForPCM8Bit(int8_t *data, uint64_t len, float left, float right) +{ + for (unsigned i = len >> 1; i > 0; i--) { + data[0] *= left; + data[1] *= right; + data += STEREO_CHANNEL_COUNT; + } +} + +void AdjustAudioBalanceForPCM16Bit(int16_t *data, uint64_t len, float left, float right) +{ + for (unsigned i = len >> 1; i > 0; i--) { + data[0] *= left; + data[1] *= right; + data += STEREO_CHANNEL_COUNT; + } +} + +void AdjustAudioBalanceForPCM24Bit(int8_t *data, uint64_t len, float left, float right) +{ + for (unsigned i = len >> 1; i > 0; i--) { + // int8_t is used for reading data of PCM24BIT here. + // 24 / 8 = 3, so we need repeat the calculation three times. + data[0] *= left; + data[1] *= left; + data[2] *= left; + data[3] *= right; + data[4] *= right; + data[5] *= right; + data += (STEREO_CHANNEL_COUNT * 3); + } +} + +void AdjustAudioBalanceForPCM32Bit(int32_t *data, uint64_t len, float left, float right) +{ + for (unsigned i = len >> 1; i > 0; i--) { + data[0] *= left; + data[1] *= right; + data += STEREO_CHANNEL_COUNT; + } +} + template bool GetSysPara(const char *key, T &value) { diff --git a/frameworks/native/hdiadapter/sink/BUILD.gn b/frameworks/native/hdiadapter/sink/BUILD.gn index 1f990f9c6fb7b1da9686e47c0c9f3c0969be74b4..2be685b40a7e50ee680a0aa0034ad2c9a1668d2f 100644 --- a/frameworks/native/hdiadapter/sink/BUILD.gn +++ b/frameworks/native/hdiadapter/sink/BUILD.gn @@ -56,6 +56,7 @@ ohos_shared_library("bluetooth_renderer_sink") { include_dirs = [ "//foundation/multimedia/audio_framework/interfaces/inner_api/native/audiocommon/include", + "//foundation/multimedia/audio_framework/frameworks/native/audioutils/include", "//foundation/multimedia/audio_framework/frameworks/native/hdiadapter/sink/common", "//drivers/peripheral/bluetooth/audio/interfaces/include", "//drivers/peripheral/bluetooth/audio/hal/hdi_binder/proxy/include", @@ -63,6 +64,7 @@ ohos_shared_library("bluetooth_renderer_sink") { deps = [ "$hdf_uhdf_path/hdi:libhdi", + "//foundation/multimedia/audio_framework/frameworks/native/audioutils:audio_utils", "//third_party/bounds_checking_function:libsec_static", ] diff --git a/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink.cpp b/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink.cpp index 9d1c74acd262c9b4f18a4c821207c3192c577451..857152ac19638e1a5f69e73edf1631df15a5b9e2 100644 --- a/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink.cpp +++ b/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink.cpp @@ -24,6 +24,7 @@ #include "audio_errors.h" #include "audio_log.h" +#include "audio_utils.h" using namespace std; using namespace OHOS::HDI::Audio_Bluetooth; @@ -44,6 +45,7 @@ const uint32_t PCM_8_BIT = 8; const uint32_t PCM_16_BIT = 16; const uint32_t PCM_24_BIT = 24; const uint32_t PCM_32_BIT = 32; +const uint32_t STEREO_CHANNEL_COUNT = 2; } #ifdef BT_DUMPFILE @@ -293,6 +295,14 @@ int32_t BluetoothRendererSink::RenderFrame(char &data, uint64_t len, uint64_t &w return ERR_INVALID_HANDLE; } + if (audioMonoState_) { + AdjustStereoToMono(&data, len); + } + + if (audioBalanceState_) { + AdjustAudioBalance(&data, len); + } + #ifdef BT_DUMPFILE size_t writeResult = fwrite((void*)&data, 1, len, pfd); if (writeResult != len) { @@ -549,6 +559,111 @@ int32_t BluetoothRendererSink::Flush(void) return ERR_OPERATION_FAILED; } + +bool BluetoothRendererSink::GetAudioMonoState() +{ + return audioMonoState_; +} + +float BluetoothRendererSink::GetAudioBalanceValue() +{ + return audioBalanceValue_; +} + +void BluetoothRendererSink::SetAudioMonoState(bool audioMono) +{ + audioMonoState_ = audioMono; +} + +void BluetoothRendererSink::SetAudioBalanceValue(float audioBalance) +{ + // reset the balance coefficient value firstly + audioBalanceValue_ = 0.0f; + leftBalanceCoef_ = 1.0f; + rightBalanceCoef_ = 1.0f; + + if (std::abs(audioBalance) <= std::numeric_limits::epsilon()) { + // audioBalance is equal to 0.0f + audioBalanceState_ = false; + } else { + // audioBalance is not equal to 0.0f + audioBalanceState_ = true; + audioBalanceValue_ = audioBalance; + // calculate the balance coefficient + if (audioBalance > 0.0f) { + leftBalanceCoef_ -= audioBalance; + } else if (audioBalance < 0.0f) { + rightBalanceCoef_ += audioBalance; + } + } +} + +void BluetoothRendererSink::AdjustStereoToMono(char *data, uint64_t len) +{ + if (attr_.channel != STEREO_CHANNEL_COUNT) { + // only stereo is surpported now (stereo channel count is 2) + return; + } + switch (attr_.format) { + case AUDIO_FORMAT_PCM_8_BIT: { + // this function needs to be further tested for usability + AdjustStereoToMonoForPCM8Bit(reinterpret_cast(data), len); + break; + } + case AUDIO_FORMAT_PCM_16_BIT: { + AdjustStereoToMonoForPCM16Bit(reinterpret_cast(data), len); + break; + } + case AUDIO_FORMAT_PCM_24_BIT: { + // this function needs to be further tested for usability + AdjustStereoToMonoForPCM24Bit(reinterpret_cast(data), len); + break; + } + case AUDIO_FORMAT_PCM_32_BIT: { + AdjustStereoToMonoForPCM32Bit(reinterpret_cast(data), len); + break; + } + default: { + // if the audio format is unsupported, the audio data will not be changed + AUDIO_ERR_LOG("BluetoothRendererSink::AdjustStereoToMono: Unsupported audio format"); + break; + } + } +} + +void BluetoothRendererSink::AdjustAudioBalance(char *data, uint64_t len) +{ + if (attr_.channel != STEREO_CHANNEL_COUNT) { + // only stereo is surpported now (stereo channel count is 2) + return; + } + + switch (attr_.format) { + case AUDIO_FORMAT_PCM_8_BIT: { + // this function needs to be further tested for usability + AdjustAudioBalanceForPCM8Bit(reinterpret_cast(data), len, leftBalanceCoef_, rightBalanceCoef_); + break; + } + case AUDIO_FORMAT_PCM_16_BIT: { + AdjustAudioBalanceForPCM16Bit(reinterpret_cast(data), len, leftBalanceCoef_, rightBalanceCoef_); + break; + } + case AUDIO_FORMAT_PCM_24_BIT: { + // this function needs to be further tested for usability + AdjustAudioBalanceForPCM24Bit(reinterpret_cast(data), len, leftBalanceCoef_, rightBalanceCoef_); + break; + } + case AUDIO_FORMAT_PCM_32_BIT: { + AdjustAudioBalanceForPCM32Bit(reinterpret_cast(data), len, leftBalanceCoef_, rightBalanceCoef_); + break; + } + default: { + // if the audio format is unsupported, the audio data will not be changed + AUDIO_ERR_LOG("BluetoothRendererSink::AdjustAudioBalance: Unsupported audio format"); + break; + } + } +} } // namespace AudioStandard } // namespace OHOS @@ -642,6 +757,16 @@ int32_t BluetoothRendererRenderFrame(void *wapper, char &data, uint64_t len, uin return ERR_NOT_STARTED; } + if (bluetoothRendererSinkWapper->GetAudioMonoState() != g_bluetoothRendrSinkInstance->GetAudioMonoState()) { + // if the two mono states are not equal, use the value of g_bluetoothRendrSinkInstance + bluetoothRendererSinkWapper->SetAudioMonoState(g_bluetoothRendrSinkInstance->GetAudioMonoState()); + } + if (std::abs(bluetoothRendererSinkWapper->GetAudioBalanceValue() - + g_bluetoothRendrSinkInstance->GetAudioBalanceValue()) > std::numeric_limits::epsilon()) { + // if the two balance values are not equal, use the value of g_bluetoothRendrSinkInstance + bluetoothRendererSinkWapper->SetAudioBalanceValue(g_bluetoothRendrSinkInstance->GetAudioBalanceValue()); + } + ret = bluetoothRendererSinkWapper->RenderFrame(data, len, writeLen); return ret; } @@ -693,6 +818,24 @@ int32_t BluetoothRendererSinkGetTransactionId(uint64_t *transactionId) return g_bluetoothRendrSinkInstance->GetTransactionId(transactionId); } + +void BluetoothRendererSinkSetAudioMonoState(bool audioMonoState) +{ + if (g_bluetoothRendrSinkInstance == nullptr) { + AUDIO_ERR_LOG("BluetoothRendererSinkSetAudioMonoState failed, g_bluetoothRendrSinkInstance is null"); + } else { + g_bluetoothRendrSinkInstance->SetAudioMonoState(audioMonoState); + } +} + +void BluetoothRendererSinkSetAudioBalanceValue(float audioBalance) +{ + if (g_bluetoothRendrSinkInstance == nullptr) { + AUDIO_ERR_LOG("BluetoothRendererSinkSetAudioBalanceValue failed, g_bluetoothRendrSinkInstance is null"); + } else { + g_bluetoothRendrSinkInstance->SetAudioBalanceValue(audioBalance); + } +} #ifdef __cplusplus } #endif diff --git a/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink.h b/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink.h index 366f722d004d12f09f619458fd166214f3136077..74eb9b086a1618996a839d1343741cd96a36e88a 100644 --- a/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink.h +++ b/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink.h @@ -49,7 +49,12 @@ public: int32_t GetLatency(uint32_t *latency); int32_t GetTransactionId(uint64_t *transactionId); static BluetoothRendererSink *GetInstance(void); + bool GetAudioMonoState(); + float GetAudioBalanceValue(); + void SetAudioMonoState(bool audioMono); + void SetAudioBalanceValue(float audioBalance); bool rendererInited_; + private: BluetoothRendererSink(); ~BluetoothRendererSink(); @@ -63,11 +68,18 @@ private: struct HDI::Audio_Bluetooth::AudioRender *audioRender_; struct HDI::Audio_Bluetooth::AudioPort audioPort = {}; void *handle_; + bool audioMonoState_ = false; + bool audioBalanceState_ = false; + float audioBalanceValue_ = 0.0f; + float leftBalanceCoef_ = 1.0f; + float rightBalanceCoef_ = 1.0f; std::shared_ptr mKeepRunningLock; int32_t CreateRender(struct HDI::Audio_Bluetooth::AudioPort &renderPort); int32_t InitAudioManager(); + void AdjustStereoToMono(char *data, uint64_t len); + void AdjustAudioBalance(char *data, uint64_t len); #ifdef BT_DUMPFILE FILE *pfd; #endif // DUMPFILE diff --git a/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink_intf.h b/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink_intf.h index 0a9a7bf9e13c07cee094a12fb8cd0d9960d425f0..4285e3c065a9d0b55142883984039433506e1ceb 100644 --- a/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink_intf.h +++ b/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink_intf.h @@ -38,6 +38,8 @@ int32_t BluetoothRendererRenderFrame(void *wapper, char *data, uint64_t len, uin int32_t BluetoothRendererSinkSetVolume(void *wapper, float left, float right); int32_t BluetoothRendererSinkGetLatency(void *wapper, uint32_t *latency); int32_t BluetoothRendererSinkGetTransactionId(uint64_t *transactionId); +void BluetoothRendererSinkSetAudioMonoState(bool audioMonoState); +void BluetoothRendererSinkSetAudioBalanceValue(float audioBalance); #ifdef __cplusplus } #endif diff --git a/frameworks/native/hdiadapter/sink/primary/audio_renderer_sink.cpp b/frameworks/native/hdiadapter/sink/primary/audio_renderer_sink.cpp index b95c5ba42006d98bdb228ff7f7de7fcb78f616c5..97dbebb45a16fb5b65197aca95609d56398b548b 100644 --- a/frameworks/native/hdiadapter/sink/primary/audio_renderer_sink.cpp +++ b/frameworks/native/hdiadapter/sink/primary/audio_renderer_sink.cpp @@ -43,8 +43,10 @@ const uint32_t PCM_24_BIT = 24; const uint32_t PCM_32_BIT = 32; const uint32_t INTERNAL_OUTPUT_STREAM_ID = 0; const uint32_t PARAM_VALUE_LENTH = 10; +const uint32_t STEREO_CHANNEL_COUNT = 2; } #ifdef DUMPFILE +// Note: accessing to this directory requires selinux permission const char *g_audioOutTestFilePath = "/data/local/tmp/audioout_test.pcm"; #endif // DUMPFILE @@ -97,6 +99,102 @@ std::string AudioRendererSink::GetAudioParameter(const AudioParamKey key, const return value; } +void AudioRendererSink::SetAudioMonoState(bool audioMono) +{ + audioMonoState_ = audioMono; +} + +void AudioRendererSink::SetAudioBalanceValue(float audioBalance) +{ + // reset the balance coefficient value firstly + leftBalanceCoef_ = 1.0f; + rightBalanceCoef_ = 1.0f; + + if (std::abs(audioBalance - 0.0f) <= std::numeric_limits::epsilon()) { + // audioBalance is equal to 0.0f + audioBalanceState_ = false; + } else { + // audioBalance is not equal to 0.0f + audioBalanceState_ = true; + // calculate the balance coefficient + if (audioBalance > 0.0f) { + leftBalanceCoef_ -= audioBalance; + } else if (audioBalance < 0.0f) { + rightBalanceCoef_ += audioBalance; + } + } +} + +void AudioRendererSink::AdjustStereoToMono(char *data, uint64_t len) +{ + if (attr_.channel != STEREO_CHANNEL_COUNT) { + // only stereo is surpported now (stereo channel count is 2) + AUDIO_ERR_LOG("AudioRendererSink::AdjustStereoToMono: Unsupported channel"); + return; + } + + switch (attr_.format) { + case AUDIO_FORMAT_PCM_8_BIT: { + // this function needs to be further tested for usability + AdjustStereoToMonoForPCM8Bit(reinterpret_cast(data), len); + break; + } + case AUDIO_FORMAT_PCM_16_BIT: { + AdjustStereoToMonoForPCM16Bit(reinterpret_cast(data), len); + break; + } + case AUDIO_FORMAT_PCM_24_BIT: { + // this function needs to be further tested for usability + AdjustStereoToMonoForPCM24Bit(reinterpret_cast(data), len); + break; + } + case AUDIO_FORMAT_PCM_32_BIT: { + AdjustStereoToMonoForPCM32Bit(reinterpret_cast(data), len); + break; + } + default: { + // if the audio format is unsupported, the audio data will not be changed + AUDIO_ERR_LOG("AudioRendererSink::AdjustStereoToMono: Unsupported audio format"); + break; + } + } +} + +void AudioRendererSink::AdjustAudioBalance(char *data, uint64_t len) +{ + if (attr_.channel != STEREO_CHANNEL_COUNT) { + // only stereo is surpported now (stereo channel count is 2) + AUDIO_ERR_LOG("AudioRendererSink::AdjustAudioBalance: Unsupported channel"); + return; + } + + switch (attr_.format) { + case AUDIO_FORMAT_PCM_8_BIT: { + // this function needs to be further tested for usability + AdjustAudioBalanceForPCM8Bit(reinterpret_cast(data), len, leftBalanceCoef_, rightBalanceCoef_); + break; + } + case AUDIO_FORMAT_PCM_16_BIT: { + AdjustAudioBalanceForPCM16Bit(reinterpret_cast(data), len, leftBalanceCoef_, rightBalanceCoef_); + break; + } + case AUDIO_FORMAT_PCM_24_BIT: { + // this function needs to be further tested for usability + AdjustAudioBalanceForPCM24Bit(reinterpret_cast(data), len, leftBalanceCoef_, rightBalanceCoef_); + break; + } + case AUDIO_FORMAT_PCM_32_BIT: { + AdjustAudioBalanceForPCM32Bit(reinterpret_cast(data), len, leftBalanceCoef_, rightBalanceCoef_); + break; + } + default: { + // if the audio format is unsupported, the audio data will not be changed + AUDIO_ERR_LOG("AudioRendererSink::AdjustAudioBalance: Unsupported audio format"); + break; + } + } +} + void AudioRendererSink::DeInit() { AUDIO_INFO_LOG("DeInit."); @@ -295,6 +393,14 @@ int32_t AudioRendererSink::RenderFrame(char &data, uint64_t len, uint64_t &write return ERR_INVALID_HANDLE; } + if (audioMonoState_) { + AdjustStereoToMono(&data, len); + } + + if (audioBalanceState_) { + AdjustAudioBalance(&data, len); + } + #ifdef DUMPFILE size_t writeResult = fwrite((void*)&data, 1, len, pfd); if (writeResult != len) { diff --git a/frameworks/native/hdiadapter/sink/primary/audio_renderer_sink.h b/frameworks/native/hdiadapter/sink/primary/audio_renderer_sink.h index 0973e1a18347bf02d3e981dfb7449bbe35be597a..4f644e768e126ce7b77aa86153d8496ea4b937f9 100644 --- a/frameworks/native/hdiadapter/sink/primary/audio_renderer_sink.h +++ b/frameworks/native/hdiadapter/sink/primary/audio_renderer_sink.h @@ -57,9 +57,11 @@ public: int32_t SetOutputRoute(DeviceType deviceType, AudioPortPin &outputPortPin); int32_t SetOutputRoute(DeviceType deviceType); static AudioRendererSink *GetInstance(void); - bool rendererInited_; void SetAudioParameter(const AudioParamKey key, const std::string& condition, const std::string& value); std::string GetAudioParameter(const AudioParamKey key, const std::string& condition); + void SetAudioMonoState(bool audioMono); + void SetAudioBalanceValue(float audioBalance); + bool rendererInited_; private: AudioRendererSink(); @@ -76,11 +78,17 @@ private: struct AudioAdapter *audioAdapter_; struct AudioRender *audioRender_; struct AudioPort audioPort_ = {}; + bool audioMonoState_ = false; + bool audioBalanceState_ = false; + float leftBalanceCoef_ = 1.0f; + float rightBalanceCoef_ = 1.0f; std::shared_ptr mKeepRunningLock; int32_t CreateRender(struct AudioPort &renderPort); int32_t InitAudioManager(); + void AdjustStereoToMono(char *data, uint64_t len); + void AdjustAudioBalance(char *data, uint64_t len); #ifdef DUMPFILE FILE *pfd; #endif // DUMPFILE diff --git a/services/audio_policy/BUILD.gn b/services/audio_policy/BUILD.gn index 880036d28b0b4360346d94e0bedaed4b63e1e93f..89ef1902b38fd04e5b0a4a3dd933c47291e3347f 100644 --- a/services/audio_policy/BUILD.gn +++ b/services/audio_policy/BUILD.gn @@ -126,6 +126,7 @@ ohos_shared_library("audio_policy_service") { "server/src/service/config/audio_focus_parser.cpp", "server/src/service/config/audio_tone_parser.cpp", "server/src/service/config/xml_parser.cpp", + "server/src/service/listener/accessibility_config_listener.cpp", "server/src/service/listener/device_status_listener.cpp", "server/src/service/manager/audio_adapter_manager.cpp", ] @@ -134,6 +135,7 @@ ohos_shared_library("audio_policy_service") { deps = [ "$hdf_uhdf_path/hdi:libhdi", + "//foundation/barrierfree/accessibility/interfaces/innerkits/acfwk:accessibilityconfig", "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", "//foundation/multimedia/audio_framework/frameworks/native/audioadapter:pulse_audio_service_adapter", "//foundation/multimedia/audio_framework/services/audio_policy:audio_dump", diff --git a/services/audio_policy/server/include/audio_policy_server.h b/services/audio_policy/server/include/audio_policy_server.h index 83ba7af23de009ab253f341f705c1a4bee285a19..9aa446cfa626ec1c58bd210add651859669adec2 100644 --- a/services/audio_policy/server/include/audio_policy_server.h +++ b/services/audio_policy/server/include/audio_policy_server.h @@ -241,6 +241,7 @@ private: void InitKVStore(); void ConnectServiceAdapter(); void RegisterBluetoothListener(); + void SubscribeAccessibilityConfigObserver(); static float MapVolumeToHDI(int32_t volume); static int32_t ConvertVolumeToInt(float volume); 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 c24c2a45b7aaa6ad4ab1403b0383b5fb46bfc57b..e7ff799a9dd3f00e4f4fee2aa41bd7969c71c2a4 100644 --- a/services/audio_policy/server/include/service/audio_policy_service.h +++ b/services/audio_policy/server/include/service/audio_policy_service.h @@ -26,6 +26,7 @@ #include "audio_stream_collector.h" #include "audio_tone_parser.h" +#include "accessibility_config_listener.h" #include "device_status_listener.h" #include "iaudio_policy_interface.h" #include "iport_observer.h" @@ -33,7 +34,8 @@ namespace OHOS { namespace AudioStandard { -class AudioPolicyService : public IPortObserver, public IDeviceStatusObserver { +class AudioPolicyService : public IPortObserver, public IDeviceStatusObserver, + public IAudioAccessibilityConfigObserver { public: static AudioPolicyService& GetAudioPolicyService() { @@ -134,6 +136,10 @@ public: void OnServiceConnected(AudioServiceIndex serviceIndex); + void OnMonoAudioConfigChanged(bool audioMono); + + void OnAudioBalanceChanged(float audioBalance); + int32_t SetAudioSessionCallback(AudioSessionCallback *callback); int32_t SetDeviceChangeCallback(const int32_t clientId, const DeviceFlag flag, const sptr &object); @@ -183,12 +189,15 @@ public: void UnregisterBluetoothListener(); + void SubscribeAccessibilityConfigObserver(); + private: AudioPolicyService() : audioPolicyManager_(AudioPolicyManagerFactory::GetAudioPolicyManager()), configParser_(ParserFactory::GetInstance().CreateParser(*this)), streamCollector_(AudioStreamCollector::GetAudioStreamCollector()) { + accessibilityConfigListener_ = std::make_shared(*this); deviceStatusListener_ = std::make_unique(*this); } @@ -280,6 +289,7 @@ private: Parser& configParser_; std::unordered_map> toneDescriptorMap; AudioStreamCollector& streamCollector_; + std::shared_ptr accessibilityConfigListener_; std::unique_ptr deviceStatusListener_; std::vector> connectedDevices_; std::unordered_map connectedA2dpDeviceMap_; diff --git a/services/audio_policy/server/include/service/interface/iaudio_accessibility_config_observer.h b/services/audio_policy/server/include/service/interface/iaudio_accessibility_config_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..f77f865c1fe88da24ac3b545ded98e841a1ea540 --- /dev/null +++ b/services/audio_policy/server/include/service/interface/iaudio_accessibility_config_observer.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ST_AUDIO_ACCESSIBILITY_CONFIG_OBSERVER_H +#define ST_AUDIO_ACCESSIBILITY_CONFIG_OBSERVER_H + +#include "audio_info.h" + +namespace OHOS { +namespace AudioStandard { +class IAudioAccessibilityConfigObserver { +public: + virtual void OnMonoAudioConfigChanged(bool audioMono) = 0; + virtual void OnAudioBalanceChanged(float audioBalance) = 0; +}; +} // namespace AudioStandard +} // namespace OHOS +#endif // ST_AUDIO_ACCESSIBILITY_CONFIG_OBSERVER_H \ No newline at end of file diff --git a/services/audio_policy/server/include/service/listener/accessibility_config_listener.h b/services/audio_policy/server/include/service/listener/accessibility_config_listener.h new file mode 100644 index 0000000000000000000000000000000000000000..7876fe91ec94d4d3e6d16e090a11af9ebd41264f --- /dev/null +++ b/services/audio_policy/server/include/service/listener/accessibility_config_listener.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ST_ACCESSIBILITY_CONFIG_LISTENER_H +#define ST_ACCESSIBILITY_CONFIG_LISTENER_H + +#include + +#include "accessibility_config.h" +#include "iaudio_accessibility_config_observer.h" + +namespace OHOS { +namespace AudioStandard { +class AccessibilityConfigListener : public OHOS::AccessibilityConfig::AccessibilityConfigObserver, + public std::enable_shared_from_this { +public: + AccessibilityConfigListener(IAudioAccessibilityConfigObserver &observer); + ~AccessibilityConfigListener(); + + void OnConfigChanged(const AccessibilityConfig::CONFIG_ID configId, + const AccessibilityConfig::ConfigValue &value) override; + + void SubscribeObserver(); + void UnsubscribeObserver(); + +private: + IAudioAccessibilityConfigObserver &audioAccessibilityConfigObserver_; +}; +} // namespace AudioStandard +} // namespace OHOS + +#endif // ST_ACCESSIBILITY_CONFIG_LISTENER_H \ No newline at end of file diff --git a/services/audio_policy/server/src/audio_policy_server.cpp b/services/audio_policy/server/src/audio_policy_server.cpp index ecbcf93e86067b89ab253adab4c84de9b985f134..14461e91257de2c4051e36d85ce5bc090151d5fc 100644 --- a/services/audio_policy/server/src/audio_policy_server.cpp +++ b/services/audio_policy/server/src/audio_policy_server.cpp @@ -82,6 +82,7 @@ void AudioPolicyServer::OnStart() AddSystemAbilityListener(MULTIMODAL_INPUT_SERVICE_ID); AddSystemAbilityListener(AUDIO_DISTRIBUTED_SERVICE_ID); AddSystemAbilityListener(BLUETOOTH_HOST_SYS_ABILITY_ID); + AddSystemAbilityListener(ACCESSIBILITY_MANAGER_SERVICE_ID); mPolicyService.Init(); RegisterAudioServerDeathRecipient(); @@ -125,6 +126,10 @@ void AudioPolicyServer::OnAddSystemAbility(int32_t systemAbilityId, const std::s AUDIO_INFO_LOG("OnAddSystemAbility bluetooth service start"); RegisterBluetoothListener(); break; + case ACCESSIBILITY_MANAGER_SERVICE_ID: + AUDIO_INFO_LOG("OnAddSystemAbility accessibility service start"); + SubscribeAccessibilityConfigObserver(); + break; default: AUDIO_ERR_LOG("OnAddSystemAbility unhandled sysabilityId:%{public}d", systemAbilityId); break; @@ -1695,6 +1700,12 @@ void AudioPolicyServer::RegisterBluetoothListener() mPolicyService.RegisterBluetoothListener(); } +void AudioPolicyServer::SubscribeAccessibilityConfigObserver() +{ + AUDIO_INFO_LOG("AudioPolicyServer::SubscribeAccessibilityConfigObserver"); + mPolicyService.SubscribeAccessibilityConfigObserver(); +} + bool AudioPolicyServer::IsAudioRendererLowLatencySupported(const AudioStreamInfo &audioStreamInfo) { AUDIO_INFO_LOG("IsAudioRendererLowLatencySupported server call"); 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 2da802e4edef0861f3d56e47ed4e9074f5b7fb32..b4766f7a89f3545cc1044a305312a044294a3e04 100644 --- a/services/audio_policy/server/src/service/audio_policy_service.cpp +++ b/services/audio_policy/server/src/service/audio_policy_service.cpp @@ -131,6 +131,7 @@ void AudioPolicyService::Deinit(void) }); IOHandles_.clear(); + accessibilityConfigListener_->UnsubscribeObserver(); deviceStatusListener_->UnRegisterDeviceStatusListener(); if (isBtListenerRegistered) { @@ -1377,6 +1378,26 @@ void AudioPolicyService::OnServiceConnected(AudioServiceIndex serviceIndex) } } +void AudioPolicyService::OnMonoAudioConfigChanged(bool audioMono) +{ + AUDIO_INFO_LOG("AudioPolicyService::OnMonoAudioConfigChanged: audioMono = %{public}s", audioMono? "true": "false"); + if (g_sProxy == nullptr) { + AUDIO_ERR_LOG("Service proxy unavailable: g_sProxy null"); + return; + } + g_sProxy->SetAudioMonoState(audioMono); +} + +void AudioPolicyService::OnAudioBalanceChanged(float audioBalance) +{ + AUDIO_INFO_LOG("AudioPolicyService::OnAudioBalanceChanged: audioBalance = %{public}f", audioBalance); + if (g_sProxy == nullptr) { + AUDIO_ERR_LOG("Service proxy unavailable: g_sProxy null"); + return; + } + g_sProxy->SetAudioBalanceValue(audioBalance); +} + void AudioPolicyService::AddAudioDevice(AudioModuleInfo& moduleInfo, InternalDeviceType devType) { // add new device into active device list @@ -2094,5 +2115,10 @@ void AudioPolicyService::UnregisterBluetoothListener() isBtListenerRegistered = false; #endif } + +void AudioPolicyService::SubscribeAccessibilityConfigObserver() +{ + accessibilityConfigListener_->SubscribeObserver(); +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_policy/server/src/service/listener/accessibility_config_listener.cpp b/services/audio_policy/server/src/service/listener/accessibility_config_listener.cpp new file mode 100644 index 0000000000000000000000000000000000000000..690b6baff365f3ecf281715e186b3baa56c13b93 --- /dev/null +++ b/services/audio_policy/server/src/service/listener/accessibility_config_listener.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "accessibility_config_listener.h" + +#include "audio_log.h" + +using namespace OHOS::AccessibilityConfig; + +namespace OHOS { +namespace AudioStandard { +AccessibilityConfigListener::AccessibilityConfigListener(IAudioAccessibilityConfigObserver &observer) + : audioAccessibilityConfigObserver_(observer) {} + +AccessibilityConfigListener::~AccessibilityConfigListener() {} + +void AccessibilityConfigListener::OnConfigChanged(const CONFIG_ID configId, const ConfigValue &value) +{ + if (configId == CONFIG_AUDIO_MONO) { + audioAccessibilityConfigObserver_.OnMonoAudioConfigChanged(value.audioMono); + } else if (configId == CONFIG_AUDIO_BALANCE) { + // value.audioBalance should be in the range [-1.0, 1.0] + float balance = value.audioBalance; + if (balance < -1.0f || balance > 1.0f) { + AUDIO_ERR_LOG("AccessibilityConfigListener: audioBalance value is out of range [-1.0, 1.0]"); + } else { + audioAccessibilityConfigObserver_.OnAudioBalanceChanged(balance); + } + } +} + +void AccessibilityConfigListener::SubscribeObserver() +{ + auto &accessibilityConfig = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance(); + (void)accessibilityConfig.InitializeContext(); + accessibilityConfig.SubscribeConfigObserver(CONFIG_AUDIO_MONO, shared_from_this()); + accessibilityConfig.SubscribeConfigObserver(CONFIG_AUDIO_BALANCE, shared_from_this()); +} + +void AccessibilityConfigListener::UnsubscribeObserver() +{ + auto &accessibilityConfig = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance(); + (void)accessibilityConfig.InitializeContext(); + accessibilityConfig.UnsubscribeConfigObserver(CONFIG_AUDIO_MONO, shared_from_this()); + accessibilityConfig.UnsubscribeConfigObserver(CONFIG_AUDIO_BALANCE, shared_from_this()); +} +} // namespace AudioStandard +} // namespace OHOS \ No newline at end of file diff --git a/services/audio_service/BUILD.gn b/services/audio_service/BUILD.gn index 6798ea9e2847acf1f6a19db26471413bc6a1eb2c..400eb827093a93207c4c7061d5944be83bd739c8 100644 --- a/services/audio_service/BUILD.gn +++ b/services/audio_service/BUILD.gn @@ -144,6 +144,7 @@ ohos_shared_library("audio_service") { deps = [ "$pulseaudio_build_path/src/daemon:pulseaudio", "//foundation/multimedia/audio_framework/frameworks/native/hdiadapter/sink:audio_renderer_sink", + "//foundation/multimedia/audio_framework/frameworks/native/hdiadapter/sink:bluetooth_renderer_sink", "//foundation/multimedia/audio_framework/frameworks/native/hdiadapter/sink:remote_audio_renderer_sink", "//foundation/multimedia/audio_framework/frameworks/native/hdiadapter/sink:renderer_sink_adapter", "//foundation/multimedia/audio_framework/frameworks/native/hdiadapter/source:audio_capturer_source", diff --git a/services/audio_service/client/include/audio_manager_base.h b/services/audio_service/client/include/audio_manager_base.h index 7948a07f733e995f3d0442028e0f6cb498e5fa9f..79a270865dd97a0a9d62694640d2d58d86a21a74 100644 --- a/services/audio_service/client/include/audio_manager_base.h +++ b/services/audio_service/client/include/audio_manager_base.h @@ -167,6 +167,22 @@ public: */ virtual int32_t SetParameterCallback(const sptr& object) = 0; + /** + * Set audio mono state for accessibility + * + * @param audioMono the state of mono audio for accessibility + * @return none. + */ + virtual void SetAudioMonoState(bool audioMono) = 0; + + /** + * Set audio balance value for accessibility + * + * @param audioBalance the value of audio balance for accessibility + * @return none. + */ + virtual void SetAudioBalanceValue(float audioBalance) = 0; + enum { GET_MAX_VOLUME = 0, GET_MIN_VOLUME = 1, @@ -185,6 +201,8 @@ public: NOTIFY_DEVICE_INFO = 14, CHECK_REMOTE_DEVICE_STATE = 15, SET_VOICE_VOLUME = 16, + SET_AUDIO_MONO_STATE = 17, + SET_AUDIO_BALANCE_VALUE = 18, }; public: diff --git a/services/audio_service/client/include/audio_manager_proxy.h b/services/audio_service/client/include/audio_manager_proxy.h index 6089dc10f3928fdccc53c9817416a221e555adb5..78559211d809881762a82c28670207779a4b8a81 100644 --- a/services/audio_service/client/include/audio_manager_proxy.h +++ b/services/audio_service/client/include/audio_manager_proxy.h @@ -45,6 +45,8 @@ public: void NotifyDeviceInfo(std::string networkId, bool connected) override; int32_t CheckRemoteDeviceState(std::string networkId, DeviceRole deviceRole, bool isStartDevice) override; int32_t SetParameterCallback(const sptr& object) override; + void SetAudioMonoState(bool audioMono) override; + void SetAudioBalanceValue(float audioBalance) override; private: static inline BrokerDelegator delegator_; }; diff --git a/services/audio_service/client/src/audio_manager_proxy.cpp b/services/audio_service/client/src/audio_manager_proxy.cpp index d9806af6f6681c5193b29cb66eb8dc461ac464c8..a8f25f49554fd618f6c2ab603986b9c4083cc3a6 100644 --- a/services/audio_service/client/src/audio_manager_proxy.cpp +++ b/services/audio_service/client/src/audio_manager_proxy.cpp @@ -412,5 +412,41 @@ int32_t AudioManagerProxy::SetParameterCallback(const sptr& objec return reply.ReadInt32(); } + +void AudioManagerProxy::SetAudioMonoState(bool audioMono) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + AUDIO_ERR_LOG("AudioPolicyProxy: WriteInterfaceToken failed"); + return; + } + (void)data.WriteBool(audioMono); + int error = Remote()->SendRequest(SET_AUDIO_MONO_STATE, data, reply, option); + if (error != ERR_NONE) { + AUDIO_ERR_LOG("AudioPolicyProxy: SetAudioMonoState failed, error: %{public}d", error); + return; + } +} + +void AudioManagerProxy::SetAudioBalanceValue(float audioBalance) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + AUDIO_ERR_LOG("AudioPolicyProxy: WriteInterfaceToken failed"); + return; + } + (void)data.WriteFloat(audioBalance); + int error = Remote()->SendRequest(SET_AUDIO_BALANCE_VALUE, data, reply, option); + if (error != ERR_NONE) { + AUDIO_ERR_LOG("AudioPolicyProxy: SetAudioBalanceValue failed, error: %{public}d", error); + return; + } +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/include/audio_server.h b/services/audio_service/server/include/audio_server.h index cca2a59f01d722a846e940d10d343ea42ab5afa2..5fbe93fd6d319b0e59a4821280353f39102fab0d 100644 --- a/services/audio_service/server/include/audio_server.h +++ b/services/audio_service/server/include/audio_server.h @@ -56,6 +56,8 @@ public: const char *RetrieveCookie(int32_t &size) override; uint64_t GetTransactionId(DeviceType deviceType, DeviceRole deviceRole) override; int32_t UpdateActiveDeviceRoute(DeviceType type, DeviceFlag flag) override; + void SetAudioMonoState(bool audioMono) override; + void SetAudioBalanceValue(float audioBalance) override; void NotifyDeviceInfo(std::string networkId, bool connected) override; diff --git a/services/audio_service/server/src/audio_manager_stub.cpp b/services/audio_service/server/src/audio_manager_stub.cpp index 3f394632a1ca6ed1dad13fc29d283cdf6ccf59fc..a173bb9bc5a8d78c8f4168bcf80beeb45158c697 100644 --- a/services/audio_service/server/src/audio_manager_stub.cpp +++ b/services/audio_service/server/src/audio_manager_stub.cpp @@ -178,6 +178,18 @@ int AudioManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Messag reply.WriteInt32(result); return AUDIO_OK; } + case SET_AUDIO_MONO_STATE: { + AUDIO_DEBUG_LOG("SET_AUDIO_MONO_STATE AudioManagerStub"); + bool audioMonoState = data.ReadBool(); + SetAudioMonoState(audioMonoState); + return AUDIO_OK; + } + case SET_AUDIO_BALANCE_VALUE: { + AUDIO_DEBUG_LOG("SET_AUDIO_BALANCE_VALUE AudioManagerStub"); + float audioBalanceValue = data.ReadFloat(); + SetAudioBalanceValue(audioBalanceValue); + return AUDIO_OK; + } default: { AUDIO_ERR_LOG("default case, need check AudioManagerStub"); return IPCObjectStub::OnRemoteRequest(code, data, reply, option); diff --git a/services/audio_service/server/src/audio_server.cpp b/services/audio_service/server/src/audio_server.cpp index fe5e4aa447a3a1f5b6be6866d250da48f9e3017e..a8fd5c896ed08cc3f23737c7ff68f555d36e0c9f 100644 --- a/services/audio_service/server/src/audio_server.cpp +++ b/services/audio_service/server/src/audio_server.cpp @@ -24,6 +24,7 @@ #include "audio_log.h" #include "system_ability_definition.h" #include "audio_manager_listener_proxy.h" +#include "bluetooth_renderer_sink_intf.h" #include "audio_server.h" @@ -344,6 +345,38 @@ int32_t AudioServer::UpdateActiveDeviceRoute(DeviceType type, DeviceFlag flag) return SUCCESS; } +void AudioServer::SetAudioMonoState(bool audioMono) +{ + AUDIO_INFO_LOG("AudioServer::SetAudioMonoState: audioMono = %{public}s", audioMono? "true": "false"); + + // Set mono for audio_renderer_sink(primary sink) + AudioRendererSink *audioRendererSinkInstance = AudioRendererSink::GetInstance(); + if (!audioRendererSinkInstance->rendererInited_) { + AUDIO_WARNING_LOG("Renderer is not initialized."); + } else { + audioRendererSinkInstance->SetAudioMonoState(audioMono); + } + + // Set mono for bluetooth_renderer_sink + BluetoothRendererSinkSetAudioMonoState(audioMono); +} + +void AudioServer::SetAudioBalanceValue(float audioBalance) +{ + AUDIO_INFO_LOG("AudioServer::SetAudioBalanceValue: audioBalance = %{public}f", audioBalance); + + // Set balance for audio_renderer_sink(primary sink) + AudioRendererSink *audioRendererSinkInstance = AudioRendererSink::GetInstance(); + if (!audioRendererSinkInstance->rendererInited_) { + AUDIO_WARNING_LOG("Renderer is not initialized."); + } else { + audioRendererSinkInstance->SetAudioBalanceValue(audioBalance); + } + + // Set balance for bluetooth_renderer_sink + BluetoothRendererSinkSetAudioBalanceValue(audioBalance); +} + void AudioServer::NotifyDeviceInfo(std::string networkId, bool connected) { AUDIO_INFO_LOG("notify device info: networkId(%{public}s), connected(%{public}d)", networkId.c_str(), connected); diff --git a/test/fuzztest/audiopolicy_fuzzer/BUILD.gn b/test/fuzztest/audiopolicy_fuzzer/BUILD.gn index 5100bbcaa5e563457b43ff580cbaf5ce67f437f1..46dcd82043927dc3caa9a53a89842edfd801fd93 100644 --- a/test/fuzztest/audiopolicy_fuzzer/BUILD.gn +++ b/test/fuzztest/audiopolicy_fuzzer/BUILD.gn @@ -34,6 +34,7 @@ ohos_fuzztest("AudioPolicyFuzzTest") { deps = [ "$hdf_uhdf_path/hdi:libhdi", + "//foundation/barrierfree/accessibility/interfaces/innerkits/acfwk:accessibilityconfig", "//foundation/multimedia/audio_framework/services/audio_policy:audio_policy_client", "//foundation/multimedia/audio_framework/services/audio_policy:audio_policy_service", ]