From c6116ba0cd681489696e0f9320ff2c0bfa55a1b0 Mon Sep 17 00:00:00 2001 From: "hezhiqiang19@huawei.com" Date: Wed, 21 Jun 2023 17:23:29 +0800 Subject: [PATCH 1/3] add policy provider 1.get device info for process 2.get real-time volume in audio_server Signed-off-by: hezhiqiang19@huawei.com Change-Id: I5565d18e9dafa5ff96b17c9a22434cda84d38d21 --- .../sink/fast/fast_audio_renderer_sink.cpp | 24 +++- .../native/audiocommon/include/audio_info.h | 6 + services/audio_policy/BUILD.gn | 1 + .../include/service/audio_policy_service.h | 17 ++- .../server/src/audio_policy_server.cpp | 2 + .../src/service/audio_policy_service.cpp | 110 ++++++++++++++ services/audio_service/BUILD.gn | 3 + .../client/include/audio_manager_base.h | 7 + .../client/include/audio_manager_proxy.h | 1 + .../client/include/policy_provider_stub.h | 41 ++++++ .../include/pulseaudio_ipc_interface_code.h | 1 + .../client/src/audio_manager_proxy.cpp | 28 +++- .../client/src/policy_provider_stub.cpp | 90 ++++++++++++ .../common/include/audio_process_config.h | 37 +++++ .../common/include/audio_shared_memory.h | 43 ++++++ .../common/include/i_audio_process.h | 5 +- .../common/include/i_audio_process_stream.h | 2 + .../common/include/i_policy_provider.h | 78 ++++++++++ .../common/include/i_policy_provider_ipc.h | 45 ++++++ .../common/include/oh_audio_buffer.h | 17 +-- .../common/src/audio_process_config.cpp | 36 ++++- .../server/include/audio_process_in_server.h | 1 + .../server/include/audio_server.h | 2 + .../server/include/policy_handler.h | 61 ++++++++ .../server/include/policy_provider_proxy.h | 37 +++++ .../server/src/audio_endpoint.cpp | 27 +++- .../server/src/audio_manager_stub.cpp | 12 +- .../server/src/audio_process_in_server.cpp | 6 + .../audio_service/server/src/audio_server.cpp | 22 +++ .../server/src/audio_service.cpp | 19 ++- .../server/src/policy_handler.cpp | 135 ++++++++++++++++++ .../server/src/policy_provider_proxy.cpp | 81 +++++++++++ 32 files changed, 956 insertions(+), 41 deletions(-) create mode 100644 services/audio_service/client/include/policy_provider_stub.h create mode 100644 services/audio_service/client/src/policy_provider_stub.cpp create mode 100644 services/audio_service/common/include/audio_process_config.h create mode 100644 services/audio_service/common/include/audio_shared_memory.h create mode 100644 services/audio_service/common/include/i_policy_provider.h create mode 100644 services/audio_service/common/include/i_policy_provider_ipc.h create mode 100644 services/audio_service/server/include/policy_handler.h create mode 100644 services/audio_service/server/include/policy_provider_proxy.h create mode 100644 services/audio_service/server/src/policy_handler.cpp create mode 100644 services/audio_service/server/src/policy_provider_proxy.cpp diff --git a/frameworks/native/hdiadapter/sink/fast/fast_audio_renderer_sink.cpp b/frameworks/native/hdiadapter/sink/fast/fast_audio_renderer_sink.cpp index 36f83d4ec7..d0cbadf83b 100644 --- a/frameworks/native/hdiadapter/sink/fast/fast_audio_renderer_sink.cpp +++ b/frameworks/native/hdiadapter/sink/fast/fast_audio_renderer_sink.cpp @@ -409,10 +409,30 @@ int32_t FastAudioRendererSinkInner::CreateRender(const struct AudioPort &renderP param.format = ConverToHdiFormat(attr_.format); param.frameSize = PcmFormatToBits(attr_.format) * param.channelCount / PCM_8_BIT; param.startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (param.frameSize); // not passed in hdi - AUDIO_INFO_LOG("FastAudioRendererSink Create render format: %{public}d", param.format); + AUDIO_INFO_LOG("FastAudioRendererSink Create render format: %{public}d and device:%{public}d", param.format, + attr_.deviceType); struct AudioDeviceDescriptor deviceDesc; deviceDesc.portId = renderPort.portId; - deviceDesc.pins = PIN_OUT_SPEAKER; + switch (static_cast(attr_.deviceType)) { + case DEVICE_TYPE_EARPIECE: + deviceDesc.pins = PIN_OUT_EARPIECE; + break; + case DEVICE_TYPE_SPEAKER: + deviceDesc.pins = PIN_OUT_SPEAKER; + break; + case DEVICE_TYPE_WIRED_HEADSET: + deviceDesc.pins = PIN_OUT_HEADSET; + break; + case DEVICE_TYPE_USB_HEADSET: + deviceDesc.pins = PIN_OUT_USB_EXT; + break; + case DEVICE_TYPE_BLUETOOTH_SCO: + deviceDesc.pins = PIN_OUT_BLUETOOTH_SCO; + break; + default: + deviceDesc.pins = PIN_OUT_SPEAKER; + break; + } char desc[] = ""; deviceDesc.desc = desc; ret = audioAdapter_->CreateRender(audioAdapter_, &deviceDesc, ¶m, &audioRender_, &renderId_); diff --git a/interfaces/inner_api/native/audiocommon/include/audio_info.h b/interfaces/inner_api/native/audiocommon/include/audio_info.h index 80992723db..ab6fe5d1c1 100644 --- a/interfaces/inner_api/native/audiocommon/include/audio_info.h +++ b/interfaces/inner_api/native/audiocommon/include/audio_info.h @@ -967,6 +967,12 @@ struct AudioStreamData { int32_t volumeEnd; }; +struct Volume { + bool isMute = false; + float volumeFloat = 1.0f; + uint32_t volumeInt = 0; +}; + struct DeviceInfo { DeviceType deviceType; DeviceRole deviceRole; diff --git a/services/audio_policy/BUILD.gn b/services/audio_policy/BUILD.gn index 5563fabee9..170ff5e7c8 100644 --- a/services/audio_policy/BUILD.gn +++ b/services/audio_policy/BUILD.gn @@ -173,6 +173,7 @@ ohos_shared_library("audio_policy_service") { "../audio_policy:audio_config.para.dac", "../audio_policy:audio_dump", "../audio_service:audio_client", + "../audio_service:audio_common", "//third_party/libxml2:xml2", ] 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 07412b39c0..b82253a342 100644 --- a/services/audio_policy/server/include/service/audio_policy_service.h +++ b/services/audio_policy/server/include/service/audio_policy_service.h @@ -41,11 +41,12 @@ #include "parser_factory.h" #include "audio_effect_manager.h" #include "audio_volume_config.h" +#include "policy_provider_stub.h" namespace OHOS { namespace AudioStandard { class AudioPolicyService : public IPortObserver, public IDeviceStatusObserver, - public IAudioAccessibilityConfigObserver { + public IAudioAccessibilityConfigObserver, public PolicyProviderStub { public: static AudioPolicyService& GetAudioPolicyService() { @@ -223,6 +224,17 @@ public: void SetParameterCallback(const std::shared_ptr& callback); + void RegiestPolicy(); + + // override for IPolicyProvider + int32_t GetProcessDeviceInfo(const AudioProcessConfig &config, DeviceInfo &deviceInfo); + + int32_t InitSharedVolume(std::shared_ptr &buffer); + + bool GetSharedVolume(AudioStreamType streamType, DeviceType deviceType, Volume &vol); + + bool SetSharedVolume(AudioStreamType streamType, DeviceType deviceType, Volume vol); + #ifdef BLUETOOTH_ENABLE static void BluetoothServiceCrashedCallback(pid_t pid); #endif @@ -447,6 +459,9 @@ private: std::unordered_map> deviceClassInfo_ = {}; std::unordered_map IOHandles_ = {}; + std::shared_ptr policyVolumeMap_ = nullptr; + volatile Volume *volumeVector_ = nullptr; + std::vector outputPriorityList_ = { DEVICE_TYPE_BLUETOOTH_SCO, DEVICE_TYPE_BLUETOOTH_A2DP, diff --git a/services/audio_policy/server/src/audio_policy_server.cpp b/services/audio_policy/server/src/audio_policy_server.cpp index 186989e007..3e122556ac 100644 --- a/services/audio_policy/server/src/audio_policy_server.cpp +++ b/services/audio_policy/server/src/audio_policy_server.cpp @@ -2144,6 +2144,8 @@ void AudioPolicyServer::RegisterParamCallback() AUDIO_INFO_LOG("RegisterParamCallback"); remoteParameterCallback_ = std::make_shared(this); mPolicyService.SetParameterCallback(remoteParameterCallback_); + // regiest policy provider in audio server + mPolicyService.RegiestPolicy(); } void AudioPolicyServer::RegisterBluetoothListener() 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 79321933a9..7fee9c7b30 100644 --- a/services/audio_policy/server/src/service/audio_policy_service.cpp +++ b/services/audio_policy/server/src/service/audio_policy_service.cpp @@ -116,6 +116,14 @@ bool AudioPolicyService::Init(void) (void)GetParameter("const.product.devicetype", " ", devicesType, sizeof(devicesType)); localDevicesType_ = devicesType; + if (policyVolumeMap_ == nullptr) { + size_t mapSize = IPolicyProvider::GetVolumeVectorSize() * sizeof(Volume); + AUDIO_INFO_LOG("InitSharedVolume create shared volume map with size %{public}zu", mapSize); + policyVolumeMap_ = AudioSharedMemory::CreateFormLocal(mapSize, "PolicyVolumeMap"); + CHECK_AND_RETURN_RET_LOG(policyVolumeMap_ != nullptr && policyVolumeMap_->GetBase() != nullptr, + false, "Get shared memory failed!"); + volumeVector_ = reinterpret_cast(policyVolumeMap_->GetBase()); + } return true; } @@ -180,6 +188,9 @@ void AudioPolicyService::Deinit(void) if (isBtListenerRegistered) { UnregisterBluetoothListener(); } + volumeVector_ = nullptr; + policyVolumeMap_ = nullptr; + return; } @@ -210,6 +221,10 @@ int32_t AudioPolicyService::SetSystemVolumeLevel(AudioStreamType streamType, int if (result == SUCCESS && streamType == STREAM_VOICE_CALL) { SetVoiceCallVolume(volumeLevel); } + // todo + Volume vol = {false, 1.0f, 0}; + vol.volumeFloat = GetSystemVolumeInDb(streamType, volumeLevel, currentActiveDevice_); + SetSharedVolume(streamType, currentActiveDevice_, vol); return result; } @@ -3019,6 +3034,101 @@ std::vector> AudioPolicyService::GetVolumeGroupInfos() return volumeGroupInfos; } +void AudioPolicyService::RegiestPolicy() +{ + AUDIO_INFO_LOG("Enter RegiestPolicy"); + const sptr gsp = GetAudioServerProxy(); + if (gsp == nullptr) { + AUDIO_ERR_LOG("RegiestPolicy g_adProxy null"); + return; + } + sptr object = this->AsObject(); + if (object == nullptr) { + AUDIO_ERR_LOG("RegiestPolicy AsObject is nullptr"); + return; + } + int32_t ret = gsp->RegiestPolicyProvider(object); + AUDIO_INFO_LOG("RegiestPolicy result:%{public}d", ret); +} + +int32_t AudioPolicyService::GetProcessDeviceInfo(const AudioProcessConfig &config, DeviceInfo &deviceInfo) +{ + AUDIO_INFO_LOG("%{public}s", ProcessConfig::DumpProcessConfig(config).c_str()); + // todo + // check process in routerMap, return target device for it + // put the currentActiveDevice_ in deviceinfo, so it can create with current using device. + // genarate the unique deviceid? + + if (config.audioMode == AUDIO_MODE_RECORD) { + deviceInfo.deviceId = 1; + if (config.isRemote) { + deviceInfo.networkId = "remote_mmap_dmic"; + } else { + deviceInfo.networkId = LOCAL_NETWORK_ID; + } + deviceInfo.deviceRole = INPUT_DEVICE; + deviceInfo.deviceType = DEVICE_TYPE_MIC; + } else { + deviceInfo.deviceId = 6; // 6 for test + if (config.isRemote) { + deviceInfo.networkId = REMOTE_NETWORK_ID; + deviceInfo.deviceType = DEVICE_TYPE_SPEAKER; + } else { + deviceInfo.networkId = LOCAL_NETWORK_ID; + deviceInfo.deviceType = currentActiveDevice_; + } + deviceInfo.deviceRole = OUTPUT_DEVICE; + } + + deviceInfo.audioStreamInfo = config.streamInfo; + deviceInfo.deviceName = "mmap_device"; + return SUCCESS; +} + +int32_t AudioPolicyService::InitSharedVolume(std::shared_ptr &buffer) +{ + CHECK_AND_RETURN_RET_LOG(policyVolumeMap_ != nullptr && policyVolumeMap_->GetBase() != nullptr, + ERR_OPERATION_FAILED, "Get shared memory failed!"); + + // init volume map + // todo device + for (size_t i = 0; i < IPolicyProvider::GetVolumeVectorSize(); i++) { + float volFloat = GetSystemVolumeDb(g_volumeIndexVector[i].first); + volumeVector_[i].isMute = false; + volumeVector_[i].volumeFloat = volFloat; + volumeVector_[i].volumeInt = 0; + } + buffer = policyVolumeMap_; + + return SUCCESS; +} + +bool AudioPolicyService::GetSharedVolume(AudioStreamType streamType, DeviceType deviceType, Volume &vol) +{ + size_t index = 0; + if (!IPolicyProvider::GetVolumeIndex(streamType, deviceType, index) || + index >= IPolicyProvider::GetVolumeVectorSize()) { + return false; + } + vol.isMute = volumeVector_[index].isMute; + vol.volumeFloat = volumeVector_[index].volumeFloat; + vol.volumeInt = volumeVector_[index].volumeInt; + return true; +} + +bool AudioPolicyService::SetSharedVolume(AudioStreamType streamType, DeviceType deviceType, Volume vol) +{ + size_t index = 0; + if (!IPolicyProvider::GetVolumeIndex(streamType, deviceType, index) || + index >= IPolicyProvider::GetVolumeVectorSize()) { + return false; + } + volumeVector_[index].isMute = vol.isMute; + volumeVector_[index].volumeFloat = vol.volumeFloat; + volumeVector_[index].volumeInt = vol.volumeInt; + return true; +} + void AudioPolicyService::SetParameterCallback(const std::shared_ptr& callback) { AUDIO_INFO_LOG("Enter SetParameterCallback"); diff --git a/services/audio_service/BUILD.gn b/services/audio_service/BUILD.gn index f91df910c3..fc09f8b284 100644 --- a/services/audio_service/BUILD.gn +++ b/services/audio_service/BUILD.gn @@ -121,6 +121,7 @@ ohos_shared_library("audio_client") { "client/src/audio_stream_manager.cpp", "client/src/audio_stream_tracker.cpp", "client/src/audio_system_manager.cpp", + "client/src/policy_provider_stub.cpp", ] public_configs = [ ":audio_client_public_config" ] @@ -220,6 +221,8 @@ ohos_shared_library("audio_process_service") { "server/src/audio_process_in_server.cpp", "server/src/audio_process_stub.cpp", "server/src/audio_service.cpp", + "server/src/policy_handler.cpp", + "server/src/policy_provider_proxy.cpp", ] configs = [ ":audio_service_config" ] diff --git a/services/audio_service/client/include/audio_manager_base.h b/services/audio_service/client/include/audio_manager_base.h index 3420ba5e81..db798833a9 100644 --- a/services/audio_service/client/include/audio_manager_base.h +++ b/services/audio_service/client/include/audio_manager_base.h @@ -202,6 +202,13 @@ public: */ virtual bool SetOutputDeviceSink(int32_t device, std::string &sinkName) = 0; + /** + * Regiest policy provider. + * + * @return result code. + */ + virtual int32_t RegiestPolicyProvider(const sptr &object) = 0; + /** * Request thread priority for client thread. */ diff --git a/services/audio_service/client/include/audio_manager_proxy.h b/services/audio_service/client/include/audio_manager_proxy.h index 4ed1d6b5c4..45a1504349 100644 --- a/services/audio_service/client/include/audio_manager_proxy.h +++ b/services/audio_service/client/include/audio_manager_proxy.h @@ -55,6 +55,7 @@ public: bool SetOutputDeviceSink(int32_t deviceType, std::string &sinkName) override; bool CreatePlaybackCapturerManager() override; int32_t SetSupportStreamUsage(std::vector usage) override; + int32_t RegiestPolicyProvider(const sptr &object) override; private: static inline BrokerDelegator delegator_; }; diff --git a/services/audio_service/client/include/policy_provider_stub.h b/services/audio_service/client/include/policy_provider_stub.h new file mode 100644 index 0000000000..0bc6d90819 --- /dev/null +++ b/services/audio_service/client/include/policy_provider_stub.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 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 POLICY_PROVIDER_STUB_H +#define POLICY_PROVIDER_STUB_H + +#include "i_policy_provider_ipc.h" + +namespace OHOS { +namespace AudioStandard { +class PolicyProviderStub : public IRemoteStub { +public: + virtual ~PolicyProviderStub() = default; + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +private: + static bool CheckInterfaceToken(MessageParcel &data); + + int32_t HandleGetProcessDeviceInfo(MessageParcel &data, MessageParcel &reply); + int32_t HandleInitSharedVolume(MessageParcel &data, MessageParcel &reply); + + using HandlerFunc = int32_t(PolicyProviderStub::*)(MessageParcel &data, MessageParcel &reply); + static inline HandlerFunc funcList_[IPolicyProviderMsg::POLICY_PROVIDER_MAX_MSG] = { + &PolicyProviderStub::HandleGetProcessDeviceInfo, + &PolicyProviderStub::HandleInitSharedVolume + }; +}; +} // namespace AudioStandard +} // namespace OHOS +#endif // POLICY_PROVIDER_STUB_H diff --git a/services/audio_service/client/include/pulseaudio_ipc_interface_code.h b/services/audio_service/client/include/pulseaudio_ipc_interface_code.h index 0f585b502c..46592942c0 100644 --- a/services/audio_service/client/include/pulseaudio_ipc_interface_code.h +++ b/services/audio_service/client/include/pulseaudio_ipc_interface_code.h @@ -48,6 +48,7 @@ namespace AudioStandard { SET_OUTPUT_DEVICE_SINK = 23, CREATE_PLAYBACK_CAPTURER_MANAGER = 24, SET_SUPPORT_STREAM_USAGE = 25, + REGISET_POLICY_PROVIDER = 26, }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/client/src/audio_manager_proxy.cpp b/services/audio_service/client/src/audio_manager_proxy.cpp index c4c03fde89..e221ad3d6a 100644 --- a/services/audio_service/client/src/audio_manager_proxy.cpp +++ b/services/audio_service/client/src/audio_manager_proxy.cpp @@ -386,6 +386,32 @@ int32_t AudioManagerProxy::SetParameterCallback(const sptr& objec return reply.ReadInt32(); } +int32_t AudioManagerProxy::RegiestPolicyProvider(const sptr &object) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + + if (object == nullptr) { + AUDIO_ERR_LOG("AudioManagerProxy: RegiestPolicyProvider object is null"); + return ERR_NULL_OBJECT; + } + if (!data.WriteInterfaceToken(GetDescriptor())) { + AUDIO_ERR_LOG("WriteInterfaceToken failed"); + return -1; + } + + (void)data.WriteRemoteObject(object); + int error = Remote()->SendRequest(static_cast(AudioServerInterfaceCode::REGISET_POLICY_PROVIDER), data, + reply, option); + if (error != ERR_NONE) { + AUDIO_ERR_LOG("RegiestPolicyProvider failed, error: %{public}d", error); + return error; + } + + return reply.ReadInt32(); +} + void AudioManagerProxy::SetAudioMonoState(bool audioMono) { MessageParcel data; @@ -434,7 +460,7 @@ sptr AudioManagerProxy::CreateAudioProcess(const AudioProcessConf AUDIO_ERR_LOG("WriteInterfaceToken failed"); return nullptr; } - IAudioProcess::WriteConfigToParcel(config, data); + ProcessConfig::WriteConfigToParcel(config, data); int error = Remote()->SendRequest( static_cast(AudioServerInterfaceCode::CREATE_AUDIOPROCESS), data, reply, option); if (error != ERR_NONE) { diff --git a/services/audio_service/client/src/policy_provider_stub.cpp b/services/audio_service/client/src/policy_provider_stub.cpp new file mode 100644 index 0000000000..aad9f3da32 --- /dev/null +++ b/services/audio_service/client/src/policy_provider_stub.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 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 "policy_provider_stub.h" +#include "audio_log.h" +#include "audio_errors.h" + +namespace OHOS { +namespace AudioStandard { +bool PolicyProviderStub::CheckInterfaceToken(MessageParcel &data) +{ + static auto locaDescriptor = IPolicyProviderIpc::GetDescriptor(); + auto remoteDescriptor = data.ReadInterfaceToken(); + if (remoteDescriptor != remoteDescriptor) { + AUDIO_ERR_LOG("CheckInterFfaceToken failed."); + return false; + } + return true; +} + +int PolicyProviderStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) +{ + if (!CheckInterfaceToken(data)) { + return AUDIO_ERR; + } + if (code >= IPolicyProviderMsg::POLICY_PROVIDER_MAX_MSG) { + AUDIO_WARNING_LOG("OnRemoteRequest unsupported request code:%{public}d.", code); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + return (this->*funcList_[code])(data, reply); +} + +int32_t PolicyProviderStub::HandleGetProcessDeviceInfo(MessageParcel &data, MessageParcel &reply) +{ + AudioProcessConfig config; + int32_t ret = ProcessConfig::ReadConfigFromParcel(config, data); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "ReadConfigFromParcel failed %{public}d", ret); + DeviceInfo deviceInfo; + ret = GetProcessDeviceInfo(config, deviceInfo); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "GetProcessDeviceInfo failed %{public}d", ret); + + reply.WriteInt32(deviceInfo.deviceType); + reply.WriteInt32(deviceInfo.deviceRole); + reply.WriteInt32(deviceInfo.deviceId); + reply.WriteInt32(deviceInfo.channelMasks); + reply.WriteString(deviceInfo.deviceName); + reply.WriteString(deviceInfo.macAddress); + + // AudioStreamInfo + reply.WriteInt32(deviceInfo.audioStreamInfo.samplingRate); + reply.WriteInt32(deviceInfo.audioStreamInfo.encoding); + reply.WriteInt32(deviceInfo.audioStreamInfo.format); + reply.WriteInt32(deviceInfo.audioStreamInfo.channels); + + reply.WriteString(deviceInfo.networkId); + reply.WriteString(deviceInfo.displayName); + reply.WriteInt32(deviceInfo.interruptGroupId); + reply.WriteInt32(deviceInfo.volumeGroupId); + + return AUDIO_OK; +} + +int32_t PolicyProviderStub::HandleInitSharedVolume(MessageParcel &data, MessageParcel &reply) +{ + (void)data; + std::shared_ptr buffer = nullptr; + int32_t ret = InitSharedVolume(buffer); + if (ret == SUCCESS && buffer != nullptr) { + ret = AudioSharedMemory::WriteToParcel(buffer, reply); + } else { + AUDIO_ERR_LOG("error: ResolveBuffer failed."); + return AUDIO_INVALID_PARAM; + } + return ret; +} +} // namespace AudioStandard +} // namespace OHOS diff --git a/services/audio_service/common/include/audio_process_config.h b/services/audio_service/common/include/audio_process_config.h new file mode 100644 index 0000000000..a2c3c33cd0 --- /dev/null +++ b/services/audio_service/common/include/audio_process_config.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 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 AUDIO_PROCESS_CONFIG_H +#define AUDIO_PROCESS_CONFIG_H + +#include + +#include "message_parcel.h" + +#include "audio_info.h" + +namespace OHOS { +namespace AudioStandard { +class ProcessConfig { +public: + static int32_t WriteConfigToParcel(const AudioProcessConfig &config, MessageParcel &parcel); + + static int32_t ReadConfigFromParcel(AudioProcessConfig &config, MessageParcel &parcel); + + static std::string DumpProcessConfig(const AudioProcessConfig &config); +}; +} // namespace AudioStandard +} // namespace OHOS +#endif // AUDIO_PROCESS_CONFIG_H diff --git a/services/audio_service/common/include/audio_shared_memory.h b/services/audio_service/common/include/audio_shared_memory.h new file mode 100644 index 0000000000..31976aee0c --- /dev/null +++ b/services/audio_service/common/include/audio_shared_memory.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 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 AUDIO_SHARED_MEMORY_H +#define AUDIO_SHARED_MEMORY_H + +#include +#include "stdint.h" + +#include "message_parcel.h" + +namespace OHOS { +namespace AudioStandard { +class AudioSharedMemory { +public: + virtual ~AudioSharedMemory() = default; + + virtual uint8_t *GetBase() = 0; + virtual size_t GetSize() = 0; + virtual int GetFd() = 0; + virtual std::string GetName() = 0; + + static std::shared_ptr CreateFormLocal(size_t size, const std::string &name); + static std::shared_ptr CreateFromRemote(int fd, size_t size, const std::string &name); + + static int32_t WriteToParcel(const std::shared_ptr &memory, MessageParcel &parcel); + static std::shared_ptr ReadFromParcel(MessageParcel &parcel); +}; +} // namespace AudioStandard +} // namespace OHOS +#endif // AUDIO_SHARED_MEMORY_H diff --git a/services/audio_service/common/include/i_audio_process.h b/services/audio_service/common/include/i_audio_process.h index 37d4d5a294..96716bb2dd 100644 --- a/services/audio_service/common/include/i_audio_process.h +++ b/services/audio_service/common/include/i_audio_process.h @@ -24,6 +24,7 @@ #include "iremote_stub.h" #include "audio_info.h" +#include "audio_process_config.h" #include "oh_audio_buffer.h" namespace OHOS { @@ -49,10 +50,6 @@ public: class IAudioProcess : public AudioProcess, public IRemoteBroker { public: - static int32_t WriteConfigToParcel(const AudioProcessConfig &config, MessageParcel &parcel); - - static int32_t ReadConfigFromParcel(AudioProcessConfig &config, MessageParcel &parcel); - virtual ~IAudioProcess() = default; // IPC code. diff --git a/services/audio_service/common/include/i_audio_process_stream.h b/services/audio_service/common/include/i_audio_process_stream.h index 4fbd11ea08..c506b339b0 100644 --- a/services/audio_service/common/include/i_audio_process_stream.h +++ b/services/audio_service/common/include/i_audio_process_stream.h @@ -32,6 +32,8 @@ public: virtual AudioStreamInfo GetStreamInfo() = 0; + virtual AudioStreamType GetAudioStreamType() = 0; + virtual ~IAudioProcessStream() = default; }; } // namespace AudioStandard diff --git a/services/audio_service/common/include/i_policy_provider.h b/services/audio_service/common/include/i_policy_provider.h new file mode 100644 index 0000000000..f90b68d8a2 --- /dev/null +++ b/services/audio_service/common/include/i_policy_provider.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 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 I_POLICY_PROVIDER_H +#define I_POLICY_PROVIDER_H + +#include +#include + +#include "audio_info.h" +#include "audio_shared_memory.h" + +namespace OHOS { +namespace AudioStandard { +namespace { + static const std::vector> g_volumeIndexVector = { + {STREAM_MUSIC, DEVICE_TYPE_SPEAKER}, + {STREAM_MUSIC, DEVICE_TYPE_WIRED_HEADSET}, + {STREAM_MUSIC, DEVICE_TYPE_USB_HEADSET}, + {STREAM_MUSIC, DEVICE_TYPE_WIRED_HEADPHONES}, + {STREAM_RING, DEVICE_TYPE_SPEAKER}, + {STREAM_RING, DEVICE_TYPE_WIRED_HEADSET}, + {STREAM_RING, DEVICE_TYPE_USB_HEADSET}, + {STREAM_RING, DEVICE_TYPE_WIRED_HEADPHONES}, + {STREAM_VOICE_ASSISTANT, DEVICE_TYPE_SPEAKER}, + {STREAM_VOICE_ASSISTANT, DEVICE_TYPE_WIRED_HEADSET}, + {STREAM_VOICE_ASSISTANT, DEVICE_TYPE_USB_HEADSET}, + {STREAM_VOICE_ASSISTANT, DEVICE_TYPE_WIRED_HEADPHONES}, + {STREAM_SYSTEM, DEVICE_TYPE_SPEAKER}, + {STREAM_SYSTEM, DEVICE_TYPE_WIRED_HEADSET}, + {STREAM_SYSTEM, DEVICE_TYPE_USB_HEADSET}, + {STREAM_SYSTEM, DEVICE_TYPE_WIRED_HEADPHONES}}; +} +class IPolicyProvider { +public: + virtual int32_t GetProcessDeviceInfo(const AudioProcessConfig &config, DeviceInfo &deviceInfo) = 0; + + virtual int32_t InitSharedVolume(std::shared_ptr &buffer) = 0; + + // virtual int32_t GetVolume(AudioStreamType streamType, DeviceType deviceType, Volume &vol) = 0; + + // virtual int32_t SetVolume(AudioStreamType streamType, DeviceType deviceType, Volume vol) = 0; + + virtual ~IPolicyProvider() = default; + + static bool GetVolumeIndex(AudioStreamType streamType, DeviceType deviceType, size_t &index) + { + bool isFind = false; + for (size_t tempIndex = 0; tempIndex < g_volumeIndexVector.size(); tempIndex++) { + if (g_volumeIndexVector[tempIndex].first == streamType && + g_volumeIndexVector[tempIndex].second == deviceType) { + isFind = true; + index = tempIndex; + break; + } + } + return isFind; + }; + static size_t GetVolumeVectorSize() + { + return g_volumeIndexVector.size(); + }; +}; +} // namespace AudioStandard +} // namespace OHOS +#endif // I_POLICY_PROVIDER_H diff --git a/services/audio_service/common/include/i_policy_provider_ipc.h b/services/audio_service/common/include/i_policy_provider_ipc.h new file mode 100644 index 0000000000..8304c32400 --- /dev/null +++ b/services/audio_service/common/include/i_policy_provider_ipc.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 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 I_POLICY_PROVIDER_IPC_H +#define I_POLICY_PROVIDER_IPC_H + +#include "i_policy_provider.h" + +#include "ipc_types.h" +#include "iremote_broker.h" +#include "iremote_proxy.h" +#include "iremote_stub.h" + +#include "audio_process_config.h" + +namespace OHOS { +namespace AudioStandard { +class IPolicyProviderIpc : public IPolicyProvider, public IRemoteBroker { +public: + virtual ~IPolicyProviderIpc() = default; + + // IPC code. + enum IPolicyProviderMsg : uint32_t { + GET_DEVICE_INFO = 0, + INIT_VOLUME_MAP, + POLICY_PROVIDER_MAX_MSG + }; + + DECLARE_INTERFACE_DESCRIPTOR(u"IPolicyProviderIpc"); +}; +} // namespace AudioStandard +} // namespace OHOS +#endif // I_POLICY_PROVIDER_IPC_H diff --git a/services/audio_service/common/include/oh_audio_buffer.h b/services/audio_service/common/include/oh_audio_buffer.h index 424d957250..f96870e7d0 100644 --- a/services/audio_service/common/include/oh_audio_buffer.h +++ b/services/audio_service/common/include/oh_audio_buffer.h @@ -22,6 +22,7 @@ #include "message_parcel.h" #include "audio_info.h" +#include "audio_shared_memory.h" namespace OHOS { namespace AudioStandard { @@ -94,22 +95,6 @@ struct SpanInfo { int32_t volumeEnd; }; -class AudioSharedMemory { -public: - virtual ~AudioSharedMemory() = default; - - virtual uint8_t *GetBase() = 0; - virtual size_t GetSize() = 0; - virtual int GetFd() = 0; - virtual std::string GetName() = 0; - - static std::shared_ptr CreateFormLocal(size_t size, const std::string &name); - static std::shared_ptr CreateFromRemote(int fd, size_t size, const std::string &name); - - static int32_t WriteToParcel(const std::shared_ptr &memory, MessageParcel &parcel); - static std::shared_ptr ReadFromParcel(MessageParcel &parcel); -}; - class OHAudioBuffer { public: static const int INVALID_BUFFER_FD = -1; diff --git a/services/audio_service/common/src/audio_process_config.cpp b/services/audio_service/common/src/audio_process_config.cpp index aba6bc6d49..2902a4f360 100644 --- a/services/audio_service/common/src/audio_process_config.cpp +++ b/services/audio_service/common/src/audio_process_config.cpp @@ -13,14 +13,16 @@ * limitations under the License. */ -#include "i_audio_process.h" +#include "audio_process_config.h" + +#include #include "audio_errors.h" #include "audio_log.h" namespace OHOS { namespace AudioStandard { -int32_t IAudioProcess::WriteConfigToParcel(const AudioProcessConfig &config, MessageParcel &parcel) +int32_t ProcessConfig::WriteConfigToParcel(const AudioProcessConfig &config, MessageParcel &parcel) { // AppInfo parcel.WriteInt32(config.appInfo.appUid); @@ -51,10 +53,10 @@ int32_t IAudioProcess::WriteConfigToParcel(const AudioProcessConfig &config, Mes return SUCCESS; } -int32_t IAudioProcess::ReadConfigFromParcel(AudioProcessConfig &config, MessageParcel &parcel) +int32_t ProcessConfig::ReadConfigFromParcel(AudioProcessConfig &config, MessageParcel &parcel) { // AppInfo - config.appInfo.appPid = parcel.ReadInt32(); + config.appInfo.appUid = parcel.ReadInt32(); config.appInfo.appTokenId = parcel.ReadUint32(); config.appInfo.appPid = parcel.ReadInt32(); @@ -81,6 +83,32 @@ int32_t IAudioProcess::ReadConfigFromParcel(AudioProcessConfig &config, MessageP return SUCCESS; } + +std::string ProcessConfig::DumpProcessConfig(const AudioProcessConfig &config) +{ + std::stringstream temp; + + // AppInfo + temp << "appInfo:pid<" << config.appInfo.appPid << "> uid<" << config.appInfo.appUid << "> tokenId<" << + config.appInfo.appTokenId << "> "; + + // streamInfo + temp << "streamInfo:format(" << config.streamInfo.format << ") encoding(" << config.streamInfo.encoding << + ") channels(" << config.streamInfo.channels << ") samplingRate(" << config.streamInfo.samplingRate << ") "; + + // audioMode + if (config.audioMode == AudioMode::AUDIO_MODE_PLAYBACK) { + temp << "[rendererInfo]:streamUsage(" << config.rendererInfo.streamUsage << ") contentType(" << + config.rendererInfo.contentType << ") flag(" << config.rendererInfo.rendererFlags << ") "; + } else { + temp << "[capturerInfo]:sourceType(" << config.capturerInfo.sourceType << ") flag(" << + config.capturerInfo.capturerFlags << ") "; + } + + temp << "isRemote<" << (config.isRemote ? "true" : "false") << ">"; + + return temp.str(); +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/include/audio_process_in_server.h b/services/audio_service/server/include/audio_process_in_server.h index e99284067e..9b90377dbc 100644 --- a/services/audio_service/server/include/audio_process_in_server.h +++ b/services/audio_service/server/include/audio_process_in_server.h @@ -56,6 +56,7 @@ public: // override for IAudioProcessStream, used in endpoint std::shared_ptr GetStreamBuffer() override; AudioStreamInfo GetStreamInfo() override; + AudioStreamType GetAudioStreamType() override; int Dump(int fd, const std::vector &args) override; void Dump(std::stringstream &dumpStringStream); diff --git a/services/audio_service/server/include/audio_server.h b/services/audio_service/server/include/audio_server.h index cbdc6b991b..cfe668c6a8 100644 --- a/services/audio_service/server/include/audio_server.h +++ b/services/audio_service/server/include/audio_server.h @@ -80,6 +80,8 @@ public: int32_t SetParameterCallback(const sptr& object) override; + int32_t RegiestPolicyProvider(const sptr &object) override; + void RequestThreadPriority(uint32_t tid, std::string bundleName) override; int32_t SetSupportStreamUsage(std::vector usage) override; diff --git a/services/audio_service/server/include/policy_handler.h b/services/audio_service/server/include/policy_handler.h new file mode 100644 index 0000000000..d302466ed1 --- /dev/null +++ b/services/audio_service/server/include/policy_handler.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 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 POLICY_HANDLER_H +#define POLICY_HANDLER_H + +#include +#include +#include +#include + +#include "audio_info.h" +#include "i_policy_provider_ipc.h" + +namespace OHOS { +namespace AudioStandard { +class PolicyHandler { +public: + static PolicyHandler& GetInstance(); + + ~PolicyHandler(); + + void Dump(std::stringstream &dumpString); + + // would be called only once + bool ConfigPolicyProvider(const sptr policyProvider); + + bool GetProcessDeviceInfo(const AudioProcessConfig &config, DeviceInfo &deviceInfo); + + bool InitVolumeMap(); + + bool GetSharedVolume(AudioStreamType streamType, DeviceType deviceType, Volume &vol); + + void SetActiveOutputDevice(DeviceType deviceType); + + DeviceType GetActiveOutPutDevice(); + +private: + PolicyHandler(); + sptr iPolicyProvider_ = nullptr; + +private: + std::shared_ptr policyVolumeMap_ = nullptr; + volatile Volume *volumeVector_ = nullptr; + DeviceType deviceType_ = DEVICE_TYPE_SPEAKER; +}; +} // namespace AudioStandard +} // namespace OHOS +#endif // POLICY_HANDLER_H diff --git a/services/audio_service/server/include/policy_provider_proxy.h b/services/audio_service/server/include/policy_provider_proxy.h new file mode 100644 index 0000000000..98b4287f01 --- /dev/null +++ b/services/audio_service/server/include/policy_provider_proxy.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 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 POLICY_PROVIDER_PROXY_H +#define POLICY_PROVIDER_PROXY_H + +#include "i_policy_provider_ipc.h" + +namespace OHOS { +namespace AudioStandard { +class PolicyProviderProxy : public IRemoteProxy { +public: + explicit PolicyProviderProxy(const sptr& impl); + virtual ~PolicyProviderProxy(); + + int32_t GetProcessDeviceInfo(const AudioProcessConfig &config, DeviceInfo &deviceInfo) override; + + int32_t InitSharedVolume(std::shared_ptr &buffer) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace AudioStandard +} // namespace OHOS +#endif // POLICY_PROVIDER_PROXY_H diff --git a/services/audio_service/server/src/audio_endpoint.cpp b/services/audio_service/server/src/audio_endpoint.cpp index 41a9e3fbb6..6aaf707aaa 100644 --- a/services/audio_service/server/src/audio_endpoint.cpp +++ b/services/audio_service/server/src/audio_endpoint.cpp @@ -32,6 +32,7 @@ #include "fast_audio_capturer_source.h" #include "i_audio_capturer_source.h" #include "linear_pos_time_model.h" +#include "policy_handler.h" #include "remote_fast_audio_renderer_sink.h" #include "remote_fast_audio_capturer_source.h" @@ -109,6 +110,7 @@ private: bool IsAnyProcessRunning(); bool CheckAllBufferReady(int64_t checkTime, uint64_t curWritePos); bool ProcessToEndpointDataHandle(uint64_t curWritePos); + void GetAllReadyProcessData(std::vector &audioDataList); std::string GetStatusStr(EndpointStatus status); @@ -341,6 +343,7 @@ bool AudioEndpointInner::Config(const DeviceInfo &deviceInfo) attr.format = dstStreamInfo_.format; // SAMPLE_S16LE = 1 attr.sampleFmt = dstStreamInfo_.format; attr.deviceNetworkId = deviceInfo.networkId.c_str(); + attr.deviceType = static_cast(deviceInfo.deviceType); fastSink_->Init(attr); if (!fastSink_->IsInited()) { @@ -864,11 +867,9 @@ void AudioEndpointInner::ProcessData(const std::vector &srcData } } -bool AudioEndpointInner::ProcessToEndpointDataHandle(uint64_t curWritePos) +// call with listLock_ hold +void AudioEndpointInner::GetAllReadyProcessData(std::vector &audioDataList) { - std::lock_guard lock(listLock_); - - std::vector audioDataList; for (size_t i = 0; i < processBufferList_.size(); i++) { uint64_t curRead = processBufferList_[i]->GetCurReadFrame(); Trace trace("AudioEndpoint::ReadProcessData->" + std::to_string(curRead)); @@ -878,7 +879,15 @@ bool AudioEndpointInner::ProcessToEndpointDataHandle(uint64_t curWritePos) continue; } AudioStreamData streamData; - streamData.volumeStart = curReadSpan->volumeStart; + Volume vol = {true, 1.0f, 0}; + AudioStreamType streamType = processList_[i]->GetAudioStreamType(); + DeviceType deviceType = PolicyHandler::GetInstance().GetActiveOutPutDevice(); + if (deviceInfo_.networkId == LOCAL_NETWORK_ID && + PolicyHandler::GetInstance().GetSharedVolume(streamType, deviceType, vol)) { + streamData.volumeStart = vol.isMute ? 0 : static_cast(curReadSpan->volumeStart * vol.volumeFloat); + } else { + streamData.volumeStart = curReadSpan->volumeStart; + } streamData.volumeEnd = curReadSpan->volumeEnd; streamData.streamInfo = processList_[i]->GetStreamInfo(); SpanStatus targetStatus = SpanStatus::SPAN_WRITE_DONE; @@ -893,6 +902,14 @@ bool AudioEndpointInner::ProcessToEndpointDataHandle(uint64_t curWritePos) #endif } } +} + +bool AudioEndpointInner::ProcessToEndpointDataHandle(uint64_t curWritePos) +{ + std::lock_guard lock(listLock_); + + std::vector audioDataList; + GetAllReadyProcessData(audioDataList); AudioStreamData dstStreamData; dstStreamData.streamInfo = dstStreamInfo_; diff --git a/services/audio_service/server/src/audio_manager_stub.cpp b/services/audio_service/server/src/audio_manager_stub.cpp index 8dfc5c7b44..f501dc2abc 100644 --- a/services/audio_service/server/src/audio_manager_stub.cpp +++ b/services/audio_service/server/src/audio_manager_stub.cpp @@ -197,7 +197,7 @@ int AudioManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Messag case static_cast(AudioServerInterfaceCode::CREATE_AUDIOPROCESS): { AUDIO_INFO_LOG("CREATE_AUDIOPROCESS AudioManagerStub"); AudioProcessConfig config; - IAudioProcess::ReadConfigFromParcel(config, data); + ProcessConfig::ReadConfigFromParcel(config, data); sptr process = CreateAudioProcess(config); if (process == nullptr) { AUDIO_ERR_LOG("CREATE_AUDIOPROCESS AudioManagerStub CreateAudioProcess failed"); @@ -308,6 +308,16 @@ int AudioManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Messag } int32_t ret = SetSupportStreamUsage(usage); reply.WriteInt32(ret); + } + case static_cast(AudioServerInterfaceCode::REGISET_POLICY_PROVIDER): { + AUDIO_DEBUG_LOG("REGISET_POLICY_PROVIDER AudioManagerStub"); + sptr object = data.ReadRemoteObject(); + if (object == nullptr) { + AUDIO_ERR_LOG("AudioManagerStub: REGISET_POLICY_PROVIDER obj is null"); + return AUDIO_ERR; + } + int32_t result = RegiestPolicyProvider(object); + reply.WriteInt32(result); return AUDIO_OK; } default: { diff --git a/services/audio_service/server/src/audio_process_in_server.cpp b/services/audio_service/server/src/audio_process_in_server.cpp index 58b370e382..e024a1086c 100644 --- a/services/audio_service/server/src/audio_process_in_server.cpp +++ b/services/audio_service/server/src/audio_process_in_server.cpp @@ -188,6 +188,12 @@ AudioStreamInfo AudioProcessInServer::GetStreamInfo() return processConfig_.streamInfo; } +AudioStreamType AudioProcessInServer::GetAudioStreamType() +{ + // todo + return STREAM_MUSIC; +} + inline uint32_t PcmFormatToBits(AudioSampleFormat format) { switch (format) { diff --git a/services/audio_service/server/src/audio_server.cpp b/services/audio_service/server/src/audio_server.cpp index 7d8d81994d..aca86f2b15 100644 --- a/services/audio_service/server/src/audio_server.cpp +++ b/services/audio_service/server/src/audio_server.cpp @@ -39,6 +39,7 @@ #include "i_standard_audio_server_manager_listener.h" #include "audio_effect_chain_manager.h" #include "playback_capturer_manager.h" +#include "policy_handler.h" #define PA #ifdef PA @@ -477,6 +478,9 @@ int32_t AudioServer::UpdateActiveDeviceRoute(DeviceType type, DeviceFlag flag) default: break; } + if (flag == ALL_DEVICES_FLAG || flag == OUTPUT_DEVICES_FLAG) { + PolicyHandler::GetInstance().SetActiveOutputDevice(type); + } return SUCCESS; } @@ -561,6 +565,24 @@ inline bool IsParamEnabled(std::string key, bool &isEnabled) return false; } +int32_t AudioServer::RegiestPolicyProvider(const sptr &object) +{ + int32_t callingUid = IPCSkeleton::GetCallingUid(); + if (callingUid != audioUid_ && callingUid != ROOT_UID) { + AUDIO_ERR_LOG("RegiestPolicyProvider refused for %{public}d", callingUid); + return ERR_NOT_SUPPORTED; + } + sptr policyProvider = iface_cast(object); + CHECK_AND_RETURN_RET_LOG(policyProvider != nullptr, ERR_INVALID_PARAM, + "AudioServer: policyProvider obj cast failed"); + bool ret = PolicyHandler::GetInstance().ConfigPolicyProvider(policyProvider); + if (!ret) { + AUDIO_ERR_LOG("ConfigPolicyProvider failed!"); + return ERR_OPERATION_FAILED; + } + return SUCCESS; +} + sptr AudioServer::CreateAudioProcess(const AudioProcessConfig &config) { if (!IsParamEnabled("persist.multimedia.audio.mmap.enable", isGetProcessEnabled_)) { diff --git a/services/audio_service/server/src/audio_service.cpp b/services/audio_service/server/src/audio_service.cpp index 5d7ccb16fe..89d8163fbe 100644 --- a/services/audio_service/server/src/audio_service.cpp +++ b/services/audio_service/server/src/audio_service.cpp @@ -20,6 +20,7 @@ #include "audio_errors.h" #include "audio_log.h" #include "remote_audio_renderer_sink.h" +#include "policy_handler.h" namespace OHOS { namespace AudioStandard { @@ -40,11 +41,6 @@ AudioService::~AudioService() AUDIO_INFO_LOG("~AudioService()"); } -inline void DumpProcessConfig(const AudioProcessConfig &config) -{ - AUDIO_INFO_LOG("Dump AudioProcessConfig: sample rate:%{public}d", config.streamInfo.samplingRate); -} - int32_t AudioService::OnProcessRelease(IAudioProcessStream *process) { std::lock_guard lock(processListMutex_); @@ -85,7 +81,7 @@ int32_t AudioService::OnProcessRelease(IAudioProcessStream *process) sptr AudioService::GetAudioProcess(const AudioProcessConfig &config) { - DumpProcessConfig(config); + AUDIO_INFO_LOG("GetAudioProcess dump %{public}s", ProcessConfig::DumpProcessConfig(config).c_str()); DeviceInfo deviceInfo = GetDeviceInfoForProcess(config); std::shared_ptr audioEndpoint = GetAudioEndpointForDevice(deviceInfo); @@ -172,6 +168,14 @@ DeviceInfo AudioService::GetDeviceInfoForProcess(const AudioProcessConfig &confi { // send the config to AudioPolicyServera and get the device info. DeviceInfo deviceInfo; + bool ret = PolicyHandler::GetInstance().GetProcessDeviceInfo(config, deviceInfo); + if (ret) { + AUDIO_INFO_LOG("Get DeviceInfo from policy server success, deviceType is%{public}d", deviceInfo.deviceType); + return deviceInfo; + } else { + AUDIO_WARNING_LOG("GetProcessDeviceInfo from audio policy server failed!"); + } + if (config.audioMode == AUDIO_MODE_RECORD) { deviceInfo.deviceId = 1; if (config.isRemote) { @@ -184,7 +188,7 @@ DeviceInfo AudioService::GetDeviceInfoForProcess(const AudioProcessConfig &confi } else { deviceInfo.deviceId = 6; // 6 for test if (config.isRemote) { - deviceInfo.networkId = REMOTE_NETWORK_ID; + deviceInfo.networkId = REMOTE_NETWORK_ID; } else { deviceInfo.networkId = LOCAL_NETWORK_ID; } @@ -228,6 +232,7 @@ void AudioService::Dump(std::stringstream &dumpStringStream) dumpStringStream << std::endl << "Endpoint device id:" << item.first << std::endl; item.second->Dump(dumpStringStream); } + PolicyHandler::GetInstance().Dump(dumpStringStream); } } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/src/policy_handler.cpp b/services/audio_service/server/src/policy_handler.cpp new file mode 100644 index 0000000000..770d67579f --- /dev/null +++ b/services/audio_service/server/src/policy_handler.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2023 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 "policy_handler.h" + +#include +#include + +#include "audio_errors.h" +#include "audio_log.h" + +namespace OHOS { +namespace AudioStandard { +PolicyHandler& PolicyHandler::GetInstance() +{ + static PolicyHandler PolicyHandler; + + return PolicyHandler; +} + +PolicyHandler::PolicyHandler() +{ + AUDIO_INFO_LOG("PolicyHandler()"); +} + +PolicyHandler::~PolicyHandler() +{ + volumeVector_ = nullptr; + policyVolumeMap_ = nullptr; + iPolicyProvider_ = nullptr; + AUDIO_INFO_LOG("~PolicyHandler()"); +} + +void PolicyHandler::Dump(std::stringstream &dumpStringStream) +{ + AUDIO_INFO_LOG("PolicyHandler dump begin"); + if (iPolicyProvider_ == nullptr || policyVolumeMap_ == nullptr || volumeVector_ == nullptr) { + dumpStringStream << "PolicyHandler is null..." << std::endl; + AUDIO_INFO_LOG("nothing to dump"); + return; + } + dumpStringStream << std::endl; + // dump active output device + dumpStringStream << "active output device:[" << deviceType_ << "]" << std::endl; + // dump volume + int formatSize = 2; + for (size_t i = 0; i < IPolicyProvider::GetVolumeVectorSize(); i++) { + dumpStringStream << "streamtype[" << g_volumeIndexVector[i].first << "] "; + dumpStringStream << "device[" << std::setw(formatSize) << g_volumeIndexVector[i].second << "]: "; + dumpStringStream << "isMute[" << (volumeVector_[i].isMute ? "true" : "false") << "] "; + dumpStringStream << "volFloat[" << volumeVector_[i].volumeFloat << "] "; + dumpStringStream << "volint[" << volumeVector_[i].volumeInt << "] "; + dumpStringStream << std::endl; + } +} + +bool PolicyHandler::ConfigPolicyProvider(const sptr policyProvider) +{ + CHECK_AND_RETURN_RET_LOG(policyProvider != nullptr, false, "ConfigPolicyProvider failed with null provider."); + if (iPolicyProvider_ == nullptr) { + iPolicyProvider_ = policyProvider; + } else { + AUDIO_ERR_LOG("Provider is already configed!"); + return false; + } + bool ret = InitVolumeMap(); + AUDIO_INFO_LOG("ConfigPolicyProvider end and InitVolumeMap %{public}s", (ret ? "SUCCESS" : "FAILED")); + return ret; +} + +bool PolicyHandler::GetProcessDeviceInfo(const AudioProcessConfig &config, DeviceInfo &deviceInfo) +{ + // send the config to AudioPolicyServer and get the device info. + CHECK_AND_RETURN_RET_LOG(iPolicyProvider_ != nullptr, false, "GetProcessDeviceInfo failed with null provider."); + int32_t ret = iPolicyProvider_->GetProcessDeviceInfo(config, deviceInfo); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "GetProcessDeviceInfo failed:%{public}d", ret); + return true; +} + +bool PolicyHandler::InitVolumeMap() +{ + CHECK_AND_RETURN_RET_LOG(iPolicyProvider_ != nullptr, false, "InitVolumeMap failed with null provider."); + iPolicyProvider_->InitSharedVolume(policyVolumeMap_); + CHECK_AND_RETURN_RET_LOG((policyVolumeMap_ != nullptr && policyVolumeMap_->GetBase() != nullptr), false, + "InitSharedVolume failed."); + size_t mapSize = IPolicyProvider::GetVolumeVectorSize() * sizeof(Volume); + if (policyVolumeMap_->GetSize() != mapSize) { + AUDIO_ERR_LOG("InitSharedVolume get error size:%{public}zu, target:%{public}zu", policyVolumeMap_->GetSize(), + mapSize); + return false; + } + volumeVector_ = reinterpret_cast(policyVolumeMap_->GetBase()); + AUDIO_INFO_LOG("InitSharedVolume success."); + return true; +} + +bool PolicyHandler::GetSharedVolume(AudioStreamType streamType, DeviceType deviceType, Volume &vol) +{ + CHECK_AND_RETURN_RET_LOG((iPolicyProvider_ != nullptr && volumeVector_ != nullptr), false, + "GetSharedVolume failed not configed"); + size_t index = 0; + if (!IPolicyProvider::GetVolumeIndex(streamType, deviceType, index) || + index >= IPolicyProvider::GetVolumeVectorSize()) { + return false; + } + vol.isMute = volumeVector_[index].isMute; + vol.volumeFloat = volumeVector_[index].volumeFloat; + vol.volumeInt = volumeVector_[index].volumeInt; + return true; +} + +void PolicyHandler::SetActiveOutputDevice(DeviceType deviceType) +{ + AUDIO_INFO_LOG("SetActiveOutputDevice to device[%{public}d].", deviceType); + deviceType_ = deviceType; +} + +DeviceType PolicyHandler::GetActiveOutPutDevice() +{ + return deviceType_; +} +} // namespace AudioStandard +} // namespace OHOS diff --git a/services/audio_service/server/src/policy_provider_proxy.cpp b/services/audio_service/server/src/policy_provider_proxy.cpp new file mode 100644 index 0000000000..7adbf39799 --- /dev/null +++ b/services/audio_service/server/src/policy_provider_proxy.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023 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 "policy_provider_proxy.h" +#include "audio_log.h" +#include "audio_errors.h" + +namespace OHOS { +namespace AudioStandard { +PolicyProviderProxy::PolicyProviderProxy(const sptr &impl) : IRemoteProxy(impl) +{ + AUDIO_INFO_LOG("PolicyProviderProxy()"); +} + +PolicyProviderProxy::~PolicyProviderProxy() +{ + AUDIO_INFO_LOG("~PolicyProviderProxy()"); +} + +int32_t PolicyProviderProxy::GetProcessDeviceInfo(const AudioProcessConfig &config, DeviceInfo &deviceInfo) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + CHECK_AND_RETURN_RET_LOG(data.WriteInterfaceToken(GetDescriptor()), ERROR, "Write descriptor failed!"); + + ProcessConfig::WriteConfigToParcel(config, data); + int ret = Remote()->SendRequest(IPolicyProviderMsg::GET_DEVICE_INFO, data, reply, option); + CHECK_AND_RETURN_RET_LOG(ret == AUDIO_OK, ERR_OPERATION_FAILED, "GetProcessDeviceInfo failed, error: %{public}d", + ret); + + deviceInfo.deviceType = static_cast(reply.ReadInt32()); + deviceInfo.deviceRole = static_cast(reply.ReadInt32()); + deviceInfo.deviceId = reply.ReadInt32(); + deviceInfo.channelMasks = reply.ReadInt32(); + deviceInfo.deviceName = reply.ReadString(); + deviceInfo.macAddress = reply.ReadString(); + + // AudioStreamInfo + deviceInfo.audioStreamInfo.samplingRate = static_cast(reply.ReadInt32()); + deviceInfo.audioStreamInfo.encoding = static_cast(reply.ReadInt32()); + deviceInfo.audioStreamInfo.format = static_cast(reply.ReadInt32()); + deviceInfo.audioStreamInfo.channels = static_cast(reply.ReadInt32()); + + deviceInfo.networkId = reply.ReadString(); + deviceInfo.displayName = reply.ReadString(); + deviceInfo.interruptGroupId = reply.ReadInt32(); + deviceInfo.volumeGroupId = reply.ReadInt32(); + + return SUCCESS; +} + +int32_t PolicyProviderProxy::InitSharedVolume(std::shared_ptr &buffer) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + CHECK_AND_RETURN_RET_LOG(data.WriteInterfaceToken(GetDescriptor()), ERROR, "Write descriptor failed!"); + + int ret = Remote()->SendRequest(IPolicyProviderMsg::INIT_VOLUME_MAP, data, reply, option); + CHECK_AND_RETURN_RET_LOG(ret == AUDIO_OK, ERR_OPERATION_FAILED, "InitSharedVolume failed, error: %{public}d", ret); + buffer = AudioSharedMemory::ReadFromParcel(reply); + CHECK_AND_RETURN_RET_LOG(buffer != nullptr, ERR_OPERATION_FAILED, "ReadFromParcel failed"); + return SUCCESS; +} +} // namespace AudioStandard +} // namespace OHOS -- Gitee From 2bc1496595277ccde51274e802208edc680b09e5 Mon Sep 17 00:00:00 2001 From: "hezhiqiang19@huawei.com" Date: Wed, 5 Jul 2023 20:51:50 +0800 Subject: [PATCH 2/3] add format convert in client Signed-off-by: hezhiqiang19@huawei.com Change-Id: I3cd56e7ea2a284a7c6b97f89347939975ec6e042 --- .../client/src/audio_process_in_client.cpp | 155 ++++++++++++++++-- 1 file changed, 144 insertions(+), 11 deletions(-) diff --git a/services/audio_service/client/src/audio_process_in_client.cpp b/services/audio_service/client/src/audio_process_in_client.cpp index 9939293b75..abb3aa96ef 100644 --- a/services/audio_service/client/src/audio_process_in_client.cpp +++ b/services/audio_service/client/src/audio_process_in_client.cpp @@ -68,8 +68,12 @@ public: static const sptr GetAudioServerProxy(); static void AudioServerDied(pid_t pid); + static bool CheckIfSupport(const AudioProcessConfig &config); private: + // move it to a common folder + static bool ChannelFormatConvert(const AudioStreamData &srcData, const AudioStreamData &dstData); + bool InitAudioBuffer(); bool PrepareCurrent(uint64_t curWritePos); @@ -96,6 +100,7 @@ private: static constexpr int64_t WRITE_BEFORE_DURATION_NANO = 2000000; // 2ms static constexpr int64_t RECORD_RESYNC_SLEEP_NANO = 2000000; // 2ms static constexpr int64_t RECORD_HANDLE_DELAY_NANO = 3000000; // 3ms + static constexpr AudioStreamInfo g_targetStreamInfo = {SAMPLE_RATE_48000, ENCODING_PCM, SAMPLE_S16LE, STEREO}; enum ThreadStatus : uint32_t { WAITTING = 0, SLEEPING, @@ -103,6 +108,9 @@ private: INVALID }; AudioProcessConfig processConfig_; + bool needConvert_ = false; + size_t clientByteSizePerFrame_ = 0; + size_t clientSpanSizeInByte_ = 0; sptr processProxy_ = nullptr; std::shared_ptr audioBuffer_ = nullptr; @@ -191,6 +199,10 @@ std::shared_ptr AudioProcessInClient::Create(const AudioPr { AUDIO_INFO_LOG("Create with config: render flag %{public}d, capturer flag %{public}d, isRemote %{public}d.", config.rendererInfo.rendererFlags, config.capturerInfo.capturerFlags, config.isRemote); + if (config.audioMode == AUDIO_MODE_PLAYBACK && !AudioProcessInClientInner::CheckIfSupport(config)) { + AUDIO_ERR_LOG("CheckIfSupport failed!"); + return nullptr; + } sptr gasp = AudioProcessInClientInner::GetAudioServerProxy(); CHECK_AND_RETURN_RET_LOG(gasp != nullptr, nullptr, "Create failed, can not get service."); sptr ipcProxy = gasp->CreateAudioProcess(config); @@ -242,12 +254,19 @@ bool AudioProcessInClientInner::InitAudioBuffer() audioBuffer_->GetSizeParameter(totalSizeInFrame_, spanSizeInFrame_, byteSizePerFrame_); spanSizeInByte_ = spanSizeInFrame_ * byteSizePerFrame_; + + if (processConfig_.audioMode == AUDIO_MODE_PLAYBACK && clientByteSizePerFrame_ != 0) { + clientSpanSizeInByte_ = spanSizeInFrame_ * clientByteSizePerFrame_; + } else { + clientSpanSizeInByte_ = spanSizeInByte_; + } + AUDIO_INFO_LOG("Using totalSizeInFrame_ %{public}d spanSizeInFrame_ %{public}d byteSizePerFrame_ %{public}d " "spanSizeInByte_ %{public}zu", totalSizeInFrame_, spanSizeInFrame_, byteSizePerFrame_, spanSizeInByte_); - callbackBuffer_ = std::make_unique(spanSizeInByte_); + callbackBuffer_ = std::make_unique(clientSpanSizeInByte_); CHECK_AND_RETURN_RET_LOG(callbackBuffer_ != nullptr, false, "Init callbackBuffer_ failed."); - memset_s(callbackBuffer_.get(), spanSizeInByte_, 0, spanSizeInByte_); + memset_s(callbackBuffer_.get(), clientSpanSizeInByte_, 0, clientSpanSizeInByte_); return true; } @@ -255,6 +274,13 @@ bool AudioProcessInClientInner::InitAudioBuffer() bool AudioProcessInClientInner::Init(const AudioProcessConfig &config) { AUDIO_INFO_LOG("Call Init."); + if (config.streamInfo.format != g_targetStreamInfo.format || + config.streamInfo.channels != g_targetStreamInfo.channels) { + needConvert_ = true; + } + size_t formatSize = (config.streamInfo.format == SAMPLE_S16LE ? 1 : 2); + size_t channelSize = (config.streamInfo.channels == MONO ? 1 : 2); + clientByteSizePerFrame_ = formatSize * channelSize; bool isBufferInited = InitAudioBuffer(); CHECK_AND_RETURN_RET_LOG(isBufferInited, isBufferInited, "%{public}s init audio buffer fail.", __func__); processConfig_ = config; @@ -364,19 +390,117 @@ int32_t AudioProcessInClientInner::GetBufferDesc(BufferDesc &bufDesc) const } bufDesc.buffer = callbackBuffer_.get(); - bufDesc.dataLength = spanSizeInByte_; - bufDesc.bufLength = spanSizeInByte_; + bufDesc.dataLength = clientSpanSizeInByte_; + bufDesc.bufLength = clientSpanSizeInByte_; return SUCCESS; } +bool AudioProcessInClientInner::CheckIfSupport(const AudioProcessConfig &config) +{ + if (config.streamInfo.encoding != ENCODING_PCM || config.streamInfo.samplingRate != SAMPLE_RATE_48000) { + return false; + } + + if (config.streamInfo.format != SAMPLE_S16LE && config.streamInfo.format != SAMPLE_S32LE) { + return false; + } + + if (config.streamInfo.channels != MONO && config.streamInfo.channels != STEREO) { + return false; + } + return true; +} + +inline bool S16MonoToS16Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc) +{ + size_t half = 2; + if (srcDesc.bufLength != dstDesc.bufLength / half || srcDesc.buffer == nullptr || dstDesc.buffer == nullptr) { + return false; + } + int16_t *stcPtr = reinterpret_cast(srcDesc.buffer); + int16_t *dstPtr = reinterpret_cast(dstDesc.buffer); + size_t count = srcDesc.bufLength / half; + for (size_t idx = 0; idx < count; idx++) { + *(dstPtr++) = *stcPtr; + *(dstPtr++) = *stcPtr++; + } + return true; +} + +inline bool S32MonoToS16Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc) +{ + size_t quarter = 4; + if (srcDesc.bufLength != dstDesc.bufLength || srcDesc.buffer == nullptr || dstDesc.buffer == nullptr || + srcDesc.bufLength % quarter != 0) { + return false; + } + int32_t *stcPtr = reinterpret_cast(srcDesc.buffer); + int16_t *dstPtr = reinterpret_cast(dstDesc.buffer); + size_t count = srcDesc.bufLength / quarter; + + double maxInt32 = INT32_MAX; + double maxInt16 = INT16_MAX; + for (size_t idx = 0; idx < count; idx++) { + int16_t temp = static_cast((static_cast(*stcPtr) / maxInt32) * maxInt16); + stcPtr++; + *(dstPtr++) = temp; + *(dstPtr++) = temp; + } + return true; +} + +inline bool S32StereoS16Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc) +{ + size_t half = 2; + if (srcDesc.bufLength / half != dstDesc.bufLength || srcDesc.buffer == nullptr || dstDesc.buffer == nullptr || + dstDesc.bufLength % half != 0) { + return false; + } + int32_t *stcPtr = reinterpret_cast(srcDesc.buffer); + int16_t *dstPtr = reinterpret_cast(dstDesc.buffer); + size_t count = srcDesc.bufLength / half / half; + double maxInt32 = INT32_MAX; + double maxInt16 = INT16_MAX; + for (size_t idx = 0; idx < count; idx++) { + int16_t temp = static_cast((static_cast(*stcPtr) / maxInt32) * maxInt16); + stcPtr++; + *(dstPtr++) = temp; + } + return true; +} + +// only support MONO to STEREO and SAMPLE_S32LE to SAMPLE_S16LE +bool AudioProcessInClientInner::ChannelFormatConvert(const AudioStreamData &srcData, const AudioStreamData &dstData) +{ + if (srcData.streamInfo.samplingRate != dstData.streamInfo.samplingRate || + srcData.streamInfo.encoding != dstData.streamInfo.encoding) { + return false; + } + if (srcData.streamInfo.format == SAMPLE_S16LE && srcData.streamInfo.channels == STEREO) { + return true; // no need convert + } + if (srcData.streamInfo.format == SAMPLE_S16LE && srcData.streamInfo.channels == MONO) { + return S16MonoToS16Stereo(srcData.bufferDesc, dstData.bufferDesc); + } + if (srcData.streamInfo.format == SAMPLE_S32LE && srcData.streamInfo.channels == MONO) { + return S32MonoToS16Stereo(srcData.bufferDesc, dstData.bufferDesc); + } + if (srcData.streamInfo.format == SAMPLE_S32LE && srcData.streamInfo.channels == STEREO) { + return S32StereoS16Stereo(srcData.bufferDesc, dstData.bufferDesc); + } + + return false; +} + int32_t AudioProcessInClientInner::Enqueue(const BufferDesc &bufDesc) const { Trace trace("AudioProcessInClient::Enqueue"); CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "%{public}s not inited!", __func__); - if (bufDesc.buffer == nullptr || bufDesc.bufLength != spanSizeInByte_ || bufDesc.dataLength != spanSizeInByte_) { + if (bufDesc.buffer == nullptr || bufDesc.bufLength != clientSpanSizeInByte_ || + bufDesc.dataLength != clientSpanSizeInByte_) { AUDIO_ERR_LOG("%{public}s bufDesc error, bufLen %{public}zu, dataLen %{public}zu, spanSize %{public}zu.", - __func__, bufDesc.bufLength, bufDesc.dataLength, spanSizeInByte_); + __func__, bufDesc.bufLength, bufDesc.dataLength, clientSpanSizeInByte_); return ERR_INVALID_PARAM; } // check if this buffer is form us. @@ -394,17 +518,26 @@ int32_t AudioProcessInClientInner::Enqueue(const BufferDesc &bufDesc) const return ERR_OPERATION_FAILED; } - ret = memcpy_s(static_cast(curWriteBuffer.buffer), spanSizeInByte_, static_cast(bufDesc.buffer), - spanSizeInByte_); - CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "Copy data failed!"); + if (!needConvert_) { + ret = memcpy_s(static_cast(curWriteBuffer.buffer), spanSizeInByte_, + static_cast(bufDesc.buffer), spanSizeInByte_); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "Copy data failed!"); + } else { + Trace traceConvert("AudioProcessInClient::ChannelFormatConvert"); + AudioStreamData srcData = {processConfig_.streamInfo, bufDesc, 0, 0}; + AudioStreamData dstData = {g_targetStreamInfo, curWriteBuffer, 0, 0}; + bool ret = ChannelFormatConvert(srcData, dstData); + CHECK_AND_RETURN_RET_LOG(ret == true, ERR_OPERATION_FAILED, "Convert data failed!"); + } + #ifdef DUMP_CLIENT if (dcp_ != nullptr) { - fwrite(static_cast(bufDesc.buffer), 1, spanSizeInByte_, dcp_); + fwrite(static_cast(bufDesc.buffer), 1, clientSpanSizeInByte_, dcp_); } #endif } - CHECK_AND_BREAK_LOG(memset_s(callbackBuffer_.get(), spanSizeInByte_, 0, spanSizeInByte_) == EOK, + CHECK_AND_BREAK_LOG(memset_s(callbackBuffer_.get(), clientSpanSizeInByte_, 0, clientSpanSizeInByte_) == EOK, "%{public}s reset callback buffer fail.", __func__); return SUCCESS; -- Gitee From 5e7f80e94b4a27fc8175a090bd52dd43ff160c21 Mon Sep 17 00:00:00 2001 From: "hezhiqiang19@huawei.com" Date: Thu, 6 Jul 2023 16:37:33 +0800 Subject: [PATCH 3/3] enable format convert in demo Signed-off-by: hezhiqiang19@huawei.com Change-Id: I47d07affc33cdf0d2f38853c1c3bfc578877b554 --- .../src/service/audio_policy_service.cpp | 4 +- .../client/src/audio_process_in_client.cpp | 57 ++++++++++++++++--- .../server/src/audio_service.cpp | 4 +- .../example/audio_process_client_test.cpp | 42 ++++++++++++-- 4 files changed, 90 insertions(+), 17 deletions(-) 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 7fee9c7b30..4244fe8930 100644 --- a/services/audio_policy/server/src/service/audio_policy_service.cpp +++ b/services/audio_policy/server/src/service/audio_policy_service.cpp @@ -3079,8 +3079,8 @@ int32_t AudioPolicyService::GetProcessDeviceInfo(const AudioProcessConfig &confi } deviceInfo.deviceRole = OUTPUT_DEVICE; } - - deviceInfo.audioStreamInfo = config.streamInfo; + AudioStreamInfo targetStreamInfo = {SAMPLE_RATE_48000, ENCODING_PCM, SAMPLE_S16LE, STEREO}; // note: read from xml + deviceInfo.audioStreamInfo = targetStreamInfo; deviceInfo.deviceName = "mmap_device"; return SUCCESS; } diff --git a/services/audio_service/client/src/audio_process_in_client.cpp b/services/audio_service/client/src/audio_process_in_client.cpp index abb3aa96ef..91b386242e 100644 --- a/services/audio_service/client/src/audio_process_in_client.cpp +++ b/services/audio_service/client/src/audio_process_in_client.cpp @@ -69,6 +69,7 @@ public: static const sptr GetAudioServerProxy(); static void AudioServerDied(pid_t pid); static bool CheckIfSupport(const AudioProcessConfig &config); + static constexpr AudioStreamInfo g_targetStreamInfo = {SAMPLE_RATE_48000, ENCODING_PCM, SAMPLE_S16LE, STEREO}; private: // move it to a common folder @@ -100,7 +101,6 @@ private: static constexpr int64_t WRITE_BEFORE_DURATION_NANO = 2000000; // 2ms static constexpr int64_t RECORD_RESYNC_SLEEP_NANO = 2000000; // 2ms static constexpr int64_t RECORD_HANDLE_DELAY_NANO = 3000000; // 3ms - static constexpr AudioStreamInfo g_targetStreamInfo = {SAMPLE_RATE_48000, ENCODING_PCM, SAMPLE_S16LE, STEREO}; enum ThreadStatus : uint32_t { WAITTING = 0, SLEEPING, @@ -205,7 +205,9 @@ std::shared_ptr AudioProcessInClient::Create(const AudioPr } sptr gasp = AudioProcessInClientInner::GetAudioServerProxy(); CHECK_AND_RETURN_RET_LOG(gasp != nullptr, nullptr, "Create failed, can not get service."); - sptr ipcProxy = gasp->CreateAudioProcess(config); + AudioProcessConfig resetConfig = config; + resetConfig.streamInfo = AudioProcessInClientInner::g_targetStreamInfo; + sptr ipcProxy = gasp->CreateAudioProcess(resetConfig); CHECK_AND_RETURN_RET_LOG(ipcProxy != nullptr, nullptr, "Create failed with null ipcProxy."); sptr iProcessProxy = iface_cast(ipcProxy); CHECK_AND_RETURN_RET_LOG(iProcessProxy != nullptr, nullptr, "Create failed when iface_cast."); @@ -271,6 +273,44 @@ bool AudioProcessInClientInner::InitAudioBuffer() return true; } +inline size_t GetFormatSize(const AudioStreamInfo &info) +{ + size_t result = 0; + size_t bitWidthSize = 0; + switch (info.format) { + case SAMPLE_U8: + bitWidthSize = 1; // size is 1 + break; + case SAMPLE_S16LE: + bitWidthSize = 2; // size is 2 + break; + case SAMPLE_S24LE: + bitWidthSize = 3; // size is 3 + break; + case SAMPLE_S32LE: + bitWidthSize = 4; // size is 4 + break; + default: + bitWidthSize = 2; // size is 2 + break; + } + + size_t channelSize = 0; + switch (info.channels) { + case MONO: + channelSize = 1; // size is 1 + break; + case STEREO: + channelSize = 2; // size is 2 + break; + default: + channelSize = 2; // size is 2 + break; + } + result = bitWidthSize * channelSize; + return result; +} + bool AudioProcessInClientInner::Init(const AudioProcessConfig &config) { AUDIO_INFO_LOG("Call Init."); @@ -278,9 +318,10 @@ bool AudioProcessInClientInner::Init(const AudioProcessConfig &config) config.streamInfo.channels != g_targetStreamInfo.channels) { needConvert_ = true; } - size_t formatSize = (config.streamInfo.format == SAMPLE_S16LE ? 1 : 2); - size_t channelSize = (config.streamInfo.channels == MONO ? 1 : 2); - clientByteSizePerFrame_ = formatSize * channelSize; + if (config.audioMode == AUDIO_MODE_PLAYBACK) { + clientByteSizePerFrame_ = GetFormatSize(config.streamInfo); + } + AUDIO_INFO_LOG("Using clientByteSizePerFrame_:%{public}zu", clientByteSizePerFrame_); bool isBufferInited = InitAudioBuffer(); CHECK_AND_RETURN_RET_LOG(isBufferInited, isBufferInited, "%{public}s init audio buffer fail.", __func__); processConfig_ = config; @@ -370,7 +411,7 @@ int32_t AudioProcessInClientInner::ReadFromProcessClient() const " spanSizeInByte %{public}zu.", __func__, ret, spanSizeInByte_); #ifdef DUMP_CLIENT if (dcp_ != nullptr) { - fwrite(static_cast(bufDesc.buffer), 1, spanSizeInByte_, dcp_); + fwrite(static_cast(readbufDesc.buffer), 1, spanSizeInByte_, dcp_); } #endif @@ -526,8 +567,8 @@ int32_t AudioProcessInClientInner::Enqueue(const BufferDesc &bufDesc) const Trace traceConvert("AudioProcessInClient::ChannelFormatConvert"); AudioStreamData srcData = {processConfig_.streamInfo, bufDesc, 0, 0}; AudioStreamData dstData = {g_targetStreamInfo, curWriteBuffer, 0, 0}; - bool ret = ChannelFormatConvert(srcData, dstData); - CHECK_AND_RETURN_RET_LOG(ret == true, ERR_OPERATION_FAILED, "Convert data failed!"); + bool succ = ChannelFormatConvert(srcData, dstData); + CHECK_AND_RETURN_RET_LOG(succ == true, ERR_OPERATION_FAILED, "Convert data failed!"); } #ifdef DUMP_CLIENT diff --git a/services/audio_service/server/src/audio_service.cpp b/services/audio_service/server/src/audio_service.cpp index 89d8163fbe..01a9800afd 100644 --- a/services/audio_service/server/src/audio_service.cpp +++ b/services/audio_service/server/src/audio_service.cpp @@ -195,8 +195,8 @@ DeviceInfo AudioService::GetDeviceInfoForProcess(const AudioProcessConfig &confi deviceInfo.deviceRole = OUTPUT_DEVICE; deviceInfo.deviceType = DEVICE_TYPE_SPEAKER; } - - deviceInfo.audioStreamInfo = config.streamInfo; + AudioStreamInfo targetStreamInfo = {SAMPLE_RATE_48000, ENCODING_PCM, SAMPLE_S16LE, STEREO}; // note: read from xml + deviceInfo.audioStreamInfo = targetStreamInfo; deviceInfo.deviceName = "mmap_device"; return deviceInfo; } diff --git a/services/audio_service/test/example/audio_process_client_test.cpp b/services/audio_service/test/example/audio_process_client_test.cpp index bf7faa10e0..5efd6594e2 100644 --- a/services/audio_service/test/example/audio_process_client_test.cpp +++ b/services/audio_service/test/example/audio_process_client_test.cpp @@ -38,6 +38,10 @@ namespace AudioStandard { namespace { static constexpr long WAV_HEADER_SIZE = 42; static constexpr int64_t SECOND_TO_NANOSECOND = 1000000000; + constexpr int32_t SAMPLE_FORMAT_U8 = 8; + constexpr int32_t SAMPLE_FORMAT_S16LE = 16; + constexpr int32_t SAMPLE_FORMAT_S24LE = 24; + constexpr int32_t SAMPLE_FORMAT_S32LE = 32; enum OperationCode : int32_t { INVALID_OPERATION = -1, INIT_LOCAL_SPK_PROCESS = 0, @@ -217,7 +221,6 @@ private: std::shared_ptr procClient_ = nullptr; int32_t loopCount_ = -1; // for loop AudioMode clientMode_ = AUDIO_MODE_PLAYBACK; - bool needSkipWavHeader_ = true; bool renderFinish_ = false; }; @@ -272,10 +275,6 @@ int32_t AudioProcessTestCallback::RenderFromFile(const BufferDesc &bufDesc) CHECK_AND_RETURN_RET_LOG(g_spkWavFile != nullptr, ERR_INVALID_HANDLE, "%{public}s g_spkWavFile is null.", __func__); - if (needSkipWavHeader_) { - fseek(g_spkWavFile, WAV_HEADER_SIZE, SEEK_SET); - needSkipWavHeader_ = false; - } if (feof(g_spkWavFile)) { if (loopCount_ < 0) { fseek(g_spkWavFile, WAV_HEADER_SIZE, SEEK_SET); // infinite loop @@ -326,6 +325,22 @@ void AudioProcessTestCallback::OnHandleData(size_t length) callBack.End(); } +inline AudioSampleFormat GetSampleFormat(int32_t wavSampleFormat) +{ + switch (wavSampleFormat) { + case SAMPLE_FORMAT_U8: + return AudioSampleFormat::SAMPLE_U8; + case SAMPLE_FORMAT_S16LE: + return AudioSampleFormat::SAMPLE_S16LE; + case SAMPLE_FORMAT_S24LE: + return AudioSampleFormat::SAMPLE_S24LE; + case SAMPLE_FORMAT_S32LE: + return AudioSampleFormat::SAMPLE_S32LE; + default: + return AudioSampleFormat::INVALID_WIDTH; + } +} + int32_t AudioProcessTest::InitSpk(int32_t loopCount, bool isRemote) { if (loopCount < 0) { @@ -353,6 +368,23 @@ int32_t AudioProcessTest::InitSpk(int32_t loopCount, bool isRemote) config.isRemote = isRemote; + if (!g_loopTest) { + wav_hdr wavHeader; + size_t headerSize = sizeof(wav_hdr); + size_t bytesRead = fread(&wavHeader, 1, headerSize, g_spkWavFile); + if (bytesRead != headerSize) { + AUDIO_ERR_LOG("RenderCallbackTest: File header reading error"); + } + + config.streamInfo.samplingRate = static_cast(wavHeader.SamplesPerSec); + config.streamInfo.format = GetSampleFormat(wavHeader.bitsPerSample); + config.streamInfo.channels = static_cast(wavHeader.NumOfChan); + + cout << endl << "samplingRate:" << config.streamInfo.samplingRate << endl; + cout << "format:" << config.streamInfo.format << endl; + cout << "channels:" << config.streamInfo.channels << endl; + } + spkProcessClient_ = AudioProcessInClient::Create(config); CHECK_AND_RETURN_RET_LOG(spkProcessClient_ != nullptr, ERR_INVALID_HANDLE, "Client test creat process client fail."); -- Gitee