From 429c5a109e32c7ca9a97c4e3e477cbed5993e12c Mon Sep 17 00:00:00 2001 From: liyuhang Date: Fri, 3 May 2024 13:43:51 +0000 Subject: [PATCH] Bluetooth low latency support a2dp offload Signed-off-by: liyuhang Change-Id: If64ca95f64d1f5728dbcc4917418984ea48c9bfb --- .../src/service/audio_policy_service.cpp | 10 +++++ .../client/include/audio_manager_base.h | 23 +++++++---- .../client/include/audio_manager_proxy.h | 1 + .../include/pulseaudio_ipc_interface_code.h | 1 + .../client/src/audio_manager_proxy.cpp | 14 +++++++ .../server/include/audio_server.h | 2 + .../server/include/audio_service.h | 1 + .../server/src/audio_endpoint.cpp | 40 +++++++++++++++---- .../server/src/audio_manager_stub.cpp | 6 +++ .../audio_service/server/src/audio_server.cpp | 7 ++++ .../server/src/audio_service.cpp | 33 +++++++++++++++ .../audio_server_fuzzer.cpp | 17 ++++++++ 12 files changed, 139 insertions(+), 16 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 d7f473e734..6a9edeaa2f 100644 --- a/services/audio_policy/server/src/service/audio_policy_service.cpp +++ b/services/audio_policy/server/src/service/audio_policy_service.cpp @@ -1950,6 +1950,12 @@ void AudioPolicyService::FetchStreamForA2dpOffload(vectormacAddress_).c_str()); + if (rendererChangeInfo->rendererInfo.rendererFlags == AUDIO_FLAG_MMAP && + preA2dpOffloadFlag_ != A2DP_OFFLOAD && a2dpOffloadFlag_ == A2DP_OFFLOAD) { + const sptr gsp = GetAudioServerProxy(); + CHECK_AND_RETURN_LOG(gsp != nullptr, "Service proxy unavailable"); + gsp->ResetAudioEndpoint(); + } SelectNewOutputDevice(rendererChangeInfo, desc); } } @@ -4004,6 +4010,10 @@ void AudioPolicyService::UpdateDeviceInfo(DeviceInfo &deviceInfo, const sptrdisplayName_; deviceInfo.connectState = desc->connectState_; + if (deviceInfo.deviceType == DEVICE_TYPE_BLUETOOTH_A2DP) { + deviceInfo.a2dpOffloadFlag = a2dpOffloadFlag_; + } + if (hasBTPermission) { deviceInfo.deviceName = desc->deviceName_; deviceInfo.macAddress = desc->macAddress_; diff --git a/services/audio_service/client/include/audio_manager_base.h b/services/audio_service/client/include/audio_manager_base.h index 9897010c3a..ff2a20805f 100644 --- a/services/audio_service/client/include/audio_manager_base.h +++ b/services/audio_service/client/include/audio_manager_base.h @@ -241,7 +241,7 @@ public: * @param config the config of the AudioProcess * * @return Returns AudioProcess client. - */ + */ virtual sptr CreateAudioProcess(const AudioProcessConfig &config) = 0; /** @@ -293,7 +293,7 @@ public: * @param usage value of StreamUsage which support inner capturer. * * @return result of setting. 0 if success, error number else. - */ + */ virtual int32_t SetSupportStreamUsage(std::vector usage) = 0; /** @@ -302,7 +302,7 @@ public: * @param state identify the capture state * * @return result of setting. 0 if success, error number else. - */ + */ virtual int32_t SetCaptureSilentState(bool state) = 0; /** @@ -311,7 +311,7 @@ public: * @param state identify the enabled state * * @return result of setting. 0 if success, error number else. - */ + */ virtual int32_t UpdateSpatializationState(AudioSpatializationState spatializationState) = 0; /** @@ -321,7 +321,7 @@ public: * @param volume stream volume in float * * @return result of notify. 0 if success, error number else. - */ + */ virtual int32_t NotifyStreamVolumeChanged(AudioStreamType streamType, float volume) = 0; /** @@ -330,7 +330,7 @@ public: * @param spatializationSceneType identify the spatialization rendering scene type to be set. * * @return result of setting. 0 if success, error number else. - */ + */ virtual int32_t SetSpatializationSceneType(AudioSpatializationSceneType spatializationSceneType) = 0; virtual int32_t ResetRouteForDisconnect(DeviceType type) = 0; @@ -341,7 +341,7 @@ public: * @param sessionId the session ID value for the stream * * @return Returns the effect algorithmic latency in ms. - */ + */ virtual uint32_t GetEffectLatency(const std::string &sessionId) = 0; /** @@ -351,9 +351,14 @@ public: * @param deviceType specified deviceType to get max amplitude * * @return result of max amplitude. - */ + */ virtual float GetMaxAmplitude(bool isOutputDevice, int32_t deviceType) = 0; + /** + * Release old endpoint and re-create one. + */ + virtual void ResetAudioEndpoint() = 0; + virtual void UpdateLatencyTimestamp(std::string ×tamp, bool isRenderer) = 0; public: @@ -402,6 +407,7 @@ private: int HandleNotifyStreamVolumeChanged(MessageParcel &data, MessageParcel &reply); int HandleSetSpatializationSceneType(MessageParcel &data, MessageParcel &reply); int HandleGetMaxAmplitude(MessageParcel &data, MessageParcel &reply); + int HandleResetAudioEndpoint(MessageParcel &data, MessageParcel &reply); int HandleResetRouteForDisconnect(MessageParcel &data, MessageParcel &reply); int HandleGetEffectLatency(MessageParcel &data, MessageParcel &reply); int HandleUpdateLatencyTimestamp(MessageParcel &data, MessageParcel &reply); @@ -449,6 +455,7 @@ private: &AudioManagerStub::HandleGetRenderPresentationPosition, &AudioManagerStub::HandleSetSpatializationSceneType, &AudioManagerStub::HandleGetMaxAmplitude, + &AudioManagerStub::HandleResetAudioEndpoint, &AudioManagerStub::HandleResetRouteForDisconnect, &AudioManagerStub::HandleGetEffectLatency, &AudioManagerStub::HandleUpdateLatencyTimestamp, diff --git a/services/audio_service/client/include/audio_manager_proxy.h b/services/audio_service/client/include/audio_manager_proxy.h index 6f258944bb..a017496875 100644 --- a/services/audio_service/client/include/audio_manager_proxy.h +++ b/services/audio_service/client/include/audio_manager_proxy.h @@ -76,6 +76,7 @@ public: int32_t ResetRouteForDisconnect(DeviceType type) override; uint32_t GetEffectLatency(const std::string &sessionId) override; float GetMaxAmplitude(bool isOutputDevice, int32_t deviceType) override; + void ResetAudioEndpoint() override; void UpdateLatencyTimestamp(std::string ×tamp, bool isRenderer) override; int32_t SetAsrAecMode(AsrAecMode asrAecMode) override; int32_t GetAsrAecMode(AsrAecMode &asrAecMode) override; 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 56ef3186f7..4f32f54b24 100644 --- a/services/audio_service/client/include/pulseaudio_ipc_interface_code.h +++ b/services/audio_service/client/include/pulseaudio_ipc_interface_code.h @@ -58,6 +58,7 @@ namespace AudioStandard { GET_RENDER_PRESENTATION_POSITION, SET_SPATIALIZATION_SCENE_TYPE, GET_MAX_AMPLITUDE, + RESET_AUDIO_ENDPOINT, RESET_ROUTE_FOR_DISCONNECT, GET_EFFECT_LATENCY, UPDATE_LATENCY_TIMESTAMP, diff --git a/services/audio_service/client/src/audio_manager_proxy.cpp b/services/audio_service/client/src/audio_manager_proxy.cpp index afbf0e0a2a..de46130a0e 100644 --- a/services/audio_service/client/src/audio_manager_proxy.cpp +++ b/services/audio_service/client/src/audio_manager_proxy.cpp @@ -925,6 +925,20 @@ float AudioManagerProxy::GetMaxAmplitude(bool isOutputDevice, int32_t deviceType return reply.ReadFloat(); } +void AudioManagerProxy::ResetAudioEndpoint() +{ + int32_t error; + MessageParcel data; + MessageParcel reply; + MessageOption option; + + bool ret = data.WriteInterfaceToken(GetDescriptor()); + CHECK_AND_RETURN_LOG(ret, "WriteInterfaceToken failed"); + error = Remote()->SendRequest( + static_cast(AudioServerInterfaceCode::RESET_AUDIO_ENDPOINT), data, reply, option); + CHECK_AND_RETURN_LOG(error == ERR_NONE, "Send request failed, error:%{public}d", error); +} + void AudioManagerProxy::UpdateLatencyTimestamp(std::string ×tamp, bool isRenderer) { int32_t error; diff --git a/services/audio_service/server/include/audio_server.h b/services/audio_service/server/include/audio_server.h index d47d7b16ab..1a55e10698 100644 --- a/services/audio_service/server/include/audio_server.h +++ b/services/audio_service/server/include/audio_server.h @@ -132,6 +132,8 @@ public: float GetMaxAmplitude(bool isOutputDevice, int32_t deviceType) override; + void ResetAudioEndpoint() override; + void UpdateLatencyTimestamp(std::string ×tamp, bool isRenderer) override; protected: void OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override; diff --git a/services/audio_service/server/include/audio_service.h b/services/audio_service/server/include/audio_service.h index 41c0380e68..a6dc9c5d23 100644 --- a/services/audio_service/server/include/audio_service.h +++ b/services/audio_service/server/include/audio_service.h @@ -62,6 +62,7 @@ public: int32_t UnlinkProcessToEndpoint(sptr process, std::shared_ptr endpoint); void Dump(std::stringstream &dumpString); float GetMaxAmplitude(bool isOutputDevice); + void ResetAudioEndpoint(); void RemoveRenderer(uint32_t sessionId); diff --git a/services/audio_service/server/src/audio_endpoint.cpp b/services/audio_service/server/src/audio_endpoint.cpp index 45dae72d9a..3abf7c4abb 100644 --- a/services/audio_service/server/src/audio_endpoint.cpp +++ b/services/audio_service/server/src/audio_endpoint.cpp @@ -213,6 +213,19 @@ private: SLEEPING, INRUNNING }; + enum FastSinkType { + NONE_FAST_SINK = 0, + FAST_SINK_TYPE_NORMAL, + FAST_SINK_TYPE_REMOTE, + FAST_SINK_TYPE_VOIP, + FAST_SINK_TYPE_BLUETOOTH + }; + enum FastSourceType { + NONE_FAST_SOURCE = 0, + FAST_SOURCE_TYPE_NORMAL, + FAST_SOURCE_TYPE_REMOTE, + FAST_SOURCE_TYPE_VOIP + }; // SamplingRate EncodingType SampleFormat Channel DeviceInfo deviceInfo_; AudioStreamInfo dstStreamInfo_; @@ -236,6 +249,8 @@ private: IMmapAudioRendererSink *fastSink_ = nullptr; IMmapAudioCapturerSource *fastSource_ = nullptr; + FastSinkType fastSinkType_ = NONE_FAST_SINK; + FastSourceType fastSourceType_ = NONE_FAST_SOURCE; LinearPosTimeModel readTimeModel_; LinearPosTimeModel writeTimeModel_; @@ -541,6 +556,8 @@ void AudioEndpointInner::Dump(std::stringstream &dumpStringStream) dumpStringStream << " samplingRate:" << dstStreamInfo_.samplingRate << std::endl; dumpStringStream << " channels:" << dstStreamInfo_.channels << std::endl; dumpStringStream << " format:" << dstStreamInfo_.format << std::endl; + dumpStringStream << " sink type:" << fastSinkType_ << std::endl; + dumpStringStream << " source type:" << fastSourceType_ << std::endl; // dump status info dumpStringStream << " Current endpoint status:" << GetStatusStr(endpointStatus_) << std::endl; @@ -612,18 +629,21 @@ IMmapAudioCapturerSource *AudioEndpointInner::GetFastSource(const std::string &n IAudioSourceAttr &attr) { AUDIO_INFO_LOG("Network id %{public}s, endpoint type %{public}d", networkId.c_str(), type); - if (networkId == LOCAL_NETWORK_ID) { - attr.adapterName = "primary"; - if (type == AudioEndpoint::TYPE_MMAP) { - return FastAudioCapturerSource::GetInstance(); - } else if (type == AudioEndpoint::TYPE_VOIP_MMAP) { - return FastAudioCapturerSource::GetVoipInstance(); - } - } else { + if (networkId != LOCAL_NETWORK_ID) { attr.adapterName = "remote"; + fastSourceType_ = FAST_SOURCE_TYPE_REMOTE; // Distributed only requires a singleton because there won't be both voip and regular fast simultaneously return RemoteFastAudioCapturerSource::GetInstance(networkId); } + + attr.adapterName = "primary"; + if (type == AudioEndpoint::TYPE_MMAP) { + fastSourceType_ = FAST_SOURCE_TYPE_NORMAL; + return FastAudioCapturerSource::GetInstance(); + } else if (type == AudioEndpoint::TYPE_VOIP_MMAP) { + fastSourceType_ = FAST_SOURCE_TYPE_VOIP; + return FastAudioCapturerSource::GetVoipInstance(); + } return nullptr; } @@ -692,17 +712,21 @@ IMmapAudioRendererSink *AudioEndpointInner::GetFastSink(const DeviceInfo &device { AUDIO_INFO_LOG("Network id %{public}s, endpoint type %{public}d", deviceInfo.networkId.c_str(), type); if (deviceInfo.networkId != LOCAL_NETWORK_ID) { + fastSinkType_ = FAST_SINK_TYPE_REMOTE; // Distributed only requires a singleton because there won't be both voip and regular fast simultaneously return RemoteFastAudioRendererSink::GetInstance(deviceInfo.networkId); } if (deviceInfo.deviceType == DEVICE_TYPE_BLUETOOTH_A2DP && deviceInfo.a2dpOffloadFlag == A2DP_NOT_OFFLOAD) { + fastSinkType_ = FAST_SINK_TYPE_BLUETOOTH; return BluetoothRendererSink::GetMmapInstance(); } if (type == AudioEndpoint::TYPE_MMAP) { + fastSinkType_ = FAST_SINK_TYPE_NORMAL; return FastAudioRendererSink::GetInstance(); } else if (type == AudioEndpoint::TYPE_VOIP_MMAP) { + fastSinkType_ = FAST_SINK_TYPE_VOIP; return FastAudioRendererSink::GetVoipInstance(); } return nullptr; diff --git a/services/audio_service/server/src/audio_manager_stub.cpp b/services/audio_service/server/src/audio_manager_stub.cpp index 6ca0a572b2..71a41cd7f6 100644 --- a/services/audio_service/server/src/audio_manager_stub.cpp +++ b/services/audio_service/server/src/audio_manager_stub.cpp @@ -534,6 +534,12 @@ int AudioManagerStub::HandleGetMaxAmplitude(MessageParcel &data, MessageParcel & return AUDIO_OK; } +int AudioManagerStub::HandleResetAudioEndpoint(MessageParcel &data, MessageParcel &reply) +{ + ResetAudioEndpoint(); + return AUDIO_OK; +} + int AudioManagerStub::HandleUpdateLatencyTimestamp(MessageParcel &data, MessageParcel &reply) { std::string timestamp = data.ReadString(); diff --git a/services/audio_service/server/src/audio_server.cpp b/services/audio_service/server/src/audio_server.cpp index 5e9876c960..9354c335ce 100644 --- a/services/audio_service/server/src/audio_server.cpp +++ b/services/audio_service/server/src/audio_server.cpp @@ -1474,6 +1474,13 @@ float AudioServer::GetMaxAmplitude(bool isOutputDevice, int32_t deviceType) return 0; } +void AudioServer::ResetAudioEndpoint() +{ + int32_t callingUid = IPCSkeleton::GetCallingUid(); + CHECK_AND_RETURN_LOG(callingUid == audioUid_ || callingUid == ROOT_UID, "Refused for %{public}d", callingUid); + AudioService::GetInstance()->ResetAudioEndpoint(); +} + void AudioServer::UpdateLatencyTimestamp(std::string ×tamp, bool isRenderer) { if (isRenderer) { diff --git a/services/audio_service/server/src/audio_service.cpp b/services/audio_service/server/src/audio_service.cpp index 617e9065a8..01315b9477 100644 --- a/services/audio_service/server/src/audio_service.cpp +++ b/services/audio_service/server/src/audio_service.cpp @@ -350,6 +350,39 @@ sptr AudioService::GetAudioProcess(const AudioProcessConfi return process; } +void AudioService::ResetAudioEndpoint() +{ + std::lock_guard lock(processListMutex_); + AudioProcessConfig config; + sptr processInServer; + auto paired = linkedPairedList_.begin(); + while (paired != linkedPairedList_.end()) { + if ((*paired).second->GetEndpointType() == AudioEndpoint::TYPE_MMAP) { + linkedPairedList_.erase(paired); + config = (*paired).first->processConfig_; + int32_t ret = UnlinkProcessToEndpoint((*paired).first, (*paired).second); + CHECK_AND_RETURN_LOG(ret == SUCCESS, "Unlink process to old endpoint failed"); + std::string endpointName = (*paired).second->GetEndpointName(); + if (endpointList_.find(endpointName) != endpointList_.end()) { + (*paired).second->Release(); + endpointList_.erase(endpointName); + } + + DeviceInfo deviceInfo = GetDeviceInfoForProcess(config); + std::shared_ptr audioEndpoint = GetAudioEndpointForDevice(deviceInfo, config.streamType, + config.rendererInfo.streamUsage == STREAM_USAGE_VOICE_COMMUNICATION || + config.capturerInfo.sourceType == SOURCE_TYPE_VOICE_COMMUNICATION); + CHECK_AND_RETURN_LOG(audioEndpoint != nullptr, "Get new endpoint failed"); + + ret = LinkProcessToEndpoint((*paired).first, audioEndpoint); + CHECK_AND_RETURN_LOG(ret == SUCCESS, "LinkProcessToEndpoint failed"); + linkedPairedList_.push_back(std::make_pair((*paired).first, audioEndpoint)); + CheckInnerCapForProcess((*paired).first, audioEndpoint); + } + paired++; + } +} + void AudioService::CheckInnerCapForProcess(sptr process, std::shared_ptr endpoint) { Trace trace("AudioService::CheckInnerCapForProcess:" + std::to_string(process->processConfig_.appInfo.appPid)); diff --git a/test/fuzztest/audioserver_fuzzer/audio_server_fuzzer.cpp b/test/fuzztest/audioserver_fuzzer/audio_server_fuzzer.cpp index 18da436993..9dc803fd27 100644 --- a/test/fuzztest/audioserver_fuzzer/audio_server_fuzzer.cpp +++ b/test/fuzztest/audioserver_fuzzer/audio_server_fuzzer.cpp @@ -306,6 +306,22 @@ void AudioServerGetMaxAmplitudeTest(const uint8_t *rawData, size_t size) data, reply, option); } +void AudioServerResetAudioEndpointTest(const uint8_t *rawData, size_t size) +{ + if (rawData == nullptr || size < LIMITSIZE) { + return; + } + + MessageParcel data; + data.WriteInterfaceToken(FORMMGR_INTERFACE_TOKEN); + + std::shared_ptr AudioServerPtr = std::make_shared(SYSTEM_ABILITY_ID, RUN_ON_CREATE); + MessageParcel reply; + MessageOption option; + AudioServerPtr->OnRemoteRequest(static_cast(AudioServerInterfaceCode::RESET_AUDIO_ENDPOINT), + data, reply, option); +} + void AudioServerCreatePlaybackCapturerManagerTest(const uint8_t *rawData, size_t size) { if (rawData == nullptr || size < LIMITSIZE) { @@ -554,6 +570,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) OHOS::AudioStandard::AudioServerResetRouteForDisconnectFuzzTest(data, size); OHOS::AudioStandard::AudioServerGetEffectLatencyTest(data, size); OHOS::AudioStandard::AudioServerGetMaxAmplitudeTest(data, size); + OHOS::AudioStandard::AudioServerResetAudioEndpointTest(data, size); OHOS::AudioStandard::AudioServerCreatePlaybackCapturerManagerTest(data, size); OHOS::AudioStandard::AudioServerSetOutputDeviceSinkTest(data, size); OHOS::AudioStandard::AudioServerRequestThreadPriorityTest(data, size); -- Gitee