From 55270f9bc2f7f5cb67795944c78e889498d381ab Mon Sep 17 00:00:00 2001 From: liyuhang Date: Thu, 8 May 2025 09:35:51 +0000 Subject: [PATCH 1/3] Detach to join Signed-off-by: liyuhang Change-Id: I666a634aab6adf029da5ddb9b44ce4a700ef2577 --- .../include/audio_capturer_private.h | 1 + .../audiocapturer/src/audio_capturer.cpp | 55 ++++++--- .../include/audio_renderer_private.h | 1 + .../audiorenderer/src/audio_renderer.cpp | 110 +++++++++++++----- .../audiostream/include/fast_audio_stream.h | 4 + .../audiostream/include/i_audio_stream.h | 4 + .../include/renderer_in_client_private.h | 4 + .../client/src/audio_process_in_client.cpp | 16 +-- .../client/src/capturer_in_client.cpp | 17 ++- .../client/src/fast_audio_stream.cpp | 11 ++ .../client/src/renderer_in_client.cpp | 5 +- .../client/src/renderer_in_client_public.cpp | 20 +++- 12 files changed, 187 insertions(+), 61 deletions(-) diff --git a/frameworks/native/audiocapturer/include/audio_capturer_private.h b/frameworks/native/audiocapturer/include/audio_capturer_private.h index 7465c3c868..c8a0ba2ed5 100644 --- a/frameworks/native/audiocapturer/include/audio_capturer_private.h +++ b/frameworks/native/audiocapturer/include/audio_capturer_private.h @@ -188,6 +188,7 @@ private: std::mutex audioCapturerErrCallbackMutex_; std::mutex policyServiceDiedCallbackMutex_; std::mutex audioInterruptMutex_; + int32_t callbackLoopTid_ = -1; }; class AudioCapturerInterruptCallbackImpl : public AudioInterruptCallback { diff --git a/frameworks/native/audiocapturer/src/audio_capturer.cpp b/frameworks/native/audiocapturer/src/audio_capturer.cpp index e72e6851d0..d972b16da2 100644 --- a/frameworks/native/audiocapturer/src/audio_capturer.cpp +++ b/frameworks/native/audiocapturer/src/audio_capturer.cpp @@ -276,9 +276,10 @@ int32_t AudioCapturerPrivate::SetParams(const AudioCapturerParams params) { Trace trace("AudioCapturer::SetParams"); AUDIO_INFO_LOG("StreamClientState for Capturer::SetParams."); - - std::shared_lock lockShared(capturerMutex_); - + std::shared_lock lockShared; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lockShared = std::shared_lock(capturerMutex_); + } AudioStreamParams audioStreamParams = ConvertToAudioStreamParams(params); IAudioStream::StreamClass streamClass = SetCaptureInfo(audioStreamParams); @@ -309,6 +310,7 @@ int32_t AudioCapturerPrivate::SetParams(const AudioCapturerParams params) ret = InitAudioStream(audioStreamParams); CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Init normal audio stream failed"); audioStream_->SetCaptureMode(CAPTURE_MODE_CALLBACK); + callbackLoopTid_ = audioStream_->GetCallbackLoopTid(); } CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "InitAudioStream failed"); @@ -547,7 +549,10 @@ int32_t AudioCapturerPrivate::SetCapturerCallback(const std::shared_ptr errorCallback) { - std::shared_lock sharedLock(capturerMutex_); + std::shared_lock sharedLock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + sharedLock = std::shared_lock(capturerMutex_); + } std::lock_guard lock(audioCapturerErrCallbackMutex_); audioCapturerErrorCallback_ = errorCallback; } @@ -647,8 +652,10 @@ void AudioCapturerPrivate::UnsetCapturerPeriodPositionCallback() int32_t AudioCapturerPrivate::CheckAndRestoreAudioCapturer(std::string callingFunc) { - std::lock_guard lock(capturerMutex_); - + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(capturerMutex_); + } // Return in advance if there's no need for restore. CHECK_AND_RETURN_RET_LOG(audioStream_, ERR_ILLEGAL_STATE, "audioStream_ is nullptr"); RestoreStatus restoreStatus = audioStream_->CheckRestoreStatus(); @@ -691,7 +698,10 @@ int32_t AudioCapturerPrivate::CheckAndRestoreAudioCapturer(std::string callingFu bool AudioCapturerPrivate::Start() { CheckAndRestoreAudioCapturer("Start"); - std::lock_guard lock(capturerMutex_); + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(capturerMutex_); + } Trace trace("AudioCapturer::Start"); AUDIO_INFO_LOG("StreamClientState for Capturer::Start. id %{public}u, sourceType: %{public}d", sessionID_, audioInterrupt_.audioFocusType.sourceType); @@ -784,7 +794,10 @@ bool AudioCapturerPrivate::GetFirstPkgTimeStampInfo(int64_t &firstTs) const bool AudioCapturerPrivate::Pause() const { - std::lock_guard lock(capturerMutex_); + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(capturerMutex_); + } Trace trace("AudioCapturer::Pause"); AUDIO_INFO_LOG("StreamClientState for Capturer::Pause. id %{public}u", sessionID_); CHECK_AND_RETURN_RET_LOG(!isSwitching_, false, "Operation failed, in switching"); @@ -802,7 +815,10 @@ bool AudioCapturerPrivate::Pause() const bool AudioCapturerPrivate::Stop() const { - std::lock_guard lock(capturerMutex_); + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(capturerMutex_); + } Trace trace("AudioCapturer::Stop"); AUDIO_INFO_LOG("StreamClientState for Capturer::Stop. id %{public}u", sessionID_); CHECK_AND_RETURN_RET_LOG(!isSwitching_, false, "Operation failed, in switching"); @@ -830,8 +846,10 @@ bool AudioCapturerPrivate::Flush() const bool AudioCapturerPrivate::Release() { AUDIO_INFO_LOG("StreamClientState for Capturer::Release. id %{public}u", sessionID_); - std::lock_guard releaseLock(capturerMutex_); - + std::unique_lock releaseLock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + releaseLock = std::unique_lock(capturerMutex_); + } abortRestore_ = true; std::lock_guard lock(lock_); CHECK_AND_RETURN_RET_LOG(isValid_, false, "Release when capturer invalid"); @@ -1084,7 +1102,9 @@ int32_t AudioCapturerPrivate::SetCaptureMode(AudioCaptureMode captureMode) audioCaptureMode_ = captureMode; std::shared_ptr currentStream = GetInnerStream(); CHECK_AND_RETURN_RET_LOG(currentStream != nullptr, ERROR_ILLEGAL_STATE, "audioStream_ is nullptr"); - return currentStream->SetCaptureMode(captureMode); + int32_t ret = currentStream->SetCaptureMode(captureMode); + callbackLoopTid_ = audioStream_->GetCallbackLoopTid(); + return ret; } AudioCaptureMode AudioCapturerPrivate::GetCaptureMode() const @@ -1365,6 +1385,7 @@ int32_t AudioCapturerPrivate::SetSwitchInfo(IAudioStream::SwitchInfo info, std:: int32_t res = audioStream->SetAudioStreamInfo(info.params, capturerProxyObj_); CHECK_AND_RETURN_RET_LOG(res == SUCCESS, ERROR, "SetAudioStreamInfo failed"); audioStream->SetCaptureMode(info.captureMode); + callbackLoopTid_ = audioStream_->GetCallbackLoopTid(); // set callback if ((info.renderPositionCb != nullptr) && (info.frameMarkPosition > 0)) { @@ -1817,7 +1838,10 @@ void CapturerPolicyServiceDiedCallback::RestoreTheadLoop() void AudioCapturerPrivate::RestoreAudioInLoop(bool &restoreResult, int32_t &tryCounter) { - std::lock_guard lock(capturerMutex_); + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(capturerMutex_); + } CHECK_AND_RETURN_LOG(audioStream_, "audioStream_ is nullptr, no need for restore"); AUDIO_INFO_LOG("Restore AudioCapturer %{public}u when server died", sessionID_); RestoreInfo restoreInfo; @@ -1869,7 +1893,10 @@ CapturerState AudioCapturerPrivate::GetStatusInner() const std::shared_ptr AudioCapturerPrivate::GetInnerStream() const { - std::shared_lock lock(capturerMutex_); + std::shared_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::shared_lock(capturerMutex_); + } return audioStream_; } } // namespace AudioStandard diff --git a/frameworks/native/audiorenderer/include/audio_renderer_private.h b/frameworks/native/audiorenderer/include/audio_renderer_private.h index 2f72e4fbcc..07ec1c299f 100644 --- a/frameworks/native/audiorenderer/include/audio_renderer_private.h +++ b/frameworks/native/audiorenderer/include/audio_renderer_private.h @@ -240,6 +240,7 @@ private: mutable std::shared_mutex rendererMutex_; mutable std::shared_mutex streamMutex_; mutable AudioRenderMode audioRenderMode_ = RENDER_MODE_NORMAL; + int32_t callbackLoopTid_ = -1; bool isFastVoipSupported_ = false; bool isDirectVoipSupported_ = false; bool isEnableVoiceModemCommunicationStartStream_ = false; diff --git a/frameworks/native/audiorenderer/src/audio_renderer.cpp b/frameworks/native/audiorenderer/src/audio_renderer.cpp index 0eb9051772..2b7c55d783 100644 --- a/frameworks/native/audiorenderer/src/audio_renderer.cpp +++ b/frameworks/native/audiorenderer/src/audio_renderer.cpp @@ -553,8 +553,10 @@ int32_t AudioRendererPrivate::SetParams(const AudioRendererParams params) { Trace trace("AudioRenderer::SetParams"); AUDIO_INFO_LOG("StreamClientState for Renderer::SetParams."); - - std::shared_lock lockShared(rendererMutex_); + std::shared_lock lockShared; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lockShared = std::shared_lock(rendererMutex_); + } std::lock_guard lock(setParamsMutex_); AudioStreamParams audioStreamParams = ConvertToAudioStreamParams(params); @@ -582,6 +584,7 @@ int32_t AudioRendererPrivate::SetParams(const AudioRendererParams params) ret = InitAudioStream(audioStreamParams); CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "InitAudioStream failed"); audioStream_->SetRenderMode(RENDER_MODE_CALLBACK); + callbackLoopTid_ = audioStream_->GetCallbackLoopTid(); } CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "SetAudioStreamInfo Failed"); @@ -732,7 +735,10 @@ int32_t AudioRendererPrivate::GetStreamInfo(AudioStreamInfo &streamInfo) const int32_t AudioRendererPrivate::SetRendererCallback(const std::shared_ptr &callback) { - std::shared_lock lockShared(rendererMutex_); + std::shared_lock lockShared; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lockShared = std::shared_lock(rendererMutex_); + } std::lock_guard lock(setStreamCallbackMutex_); // If the client is using the deprecated SetParams API. SetRendererCallback must be invoked, after SetParams. // In general, callbacks can only be set after the renderer state is PREPARED. @@ -839,14 +845,19 @@ bool AudioRendererPrivate::GetStartStreamResult(StateChangeCmdType cmdType) std::shared_ptr AudioRendererPrivate::GetInnerStream() const { - std::shared_lock lock(rendererMutex_); + std::shared_lock lockShared; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lockShared = std::shared_lock(rendererMutex_); + } return audioStream_; } int32_t AudioRendererPrivate::CheckAndRestoreAudioRenderer(std::string callingFunc) { - std::lock_guard lock(rendererMutex_); - + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(rendererMutex_); + } // Return in advance if there's no need for restore. CHECK_AND_RETURN_RET_LOG(audioStream_, ERR_ILLEGAL_STATE, "audioStream_ is nullptr"); RestoreStatus restoreStatus = audioStream_->CheckRestoreStatus(); @@ -901,10 +912,12 @@ bool AudioRendererPrivate::Start(StateChangeCmdType cmdType) Trace trace("AudioRenderer::Start"); CheckAndRestoreAudioRenderer("Start"); AudioXCollie audioXCollie("AudioRendererPrivate::Start", START_TIME_OUT_SECONDS, - [](void *) { - AUDIO_ERR_LOG("Start timeout"); - }, nullptr, AUDIO_XCOLLIE_FLAG_LOG); - std::lock_guard lock(rendererMutex_); + [](void *) { AUDIO_ERR_LOG("Start timeout"); }, nullptr, AUDIO_XCOLLIE_FLAG_LOG); + + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(rendererMutex_); + } AUDIO_INFO_LOG("StreamClientState for Renderer::Start. id: %{public}u, streamType: %{public}d, "\ "volume: %{public}f, interruptMode: %{public}d", sessionID_, audioInterrupt_.audioFocusType.streamType, GetVolumeInner(), audioInterrupt_.mode); @@ -913,11 +926,9 @@ bool AudioRendererPrivate::Start(StateChangeCmdType cmdType) CHECK_AND_RETURN_RET_LOG((state == RENDERER_PREPARED) || (state == RENDERER_STOPPED) || (state == RENDERER_PAUSED), false, "Start failed. Illegal state:%{public}u", state); - CHECK_AND_RETURN_RET_LOG(!isSwitching_, false, - "Start failed. Switching state: %{public}d", isSwitching_); + CHECK_AND_RETURN_RET_LOG(!isSwitching_, false, "Start failed. Switching state: %{public}d", isSwitching_); - if (audioInterrupt_.audioFocusType.streamType == STREAM_DEFAULT || - audioInterrupt_.streamId == INVALID_SESSION_ID) { + if (audioInterrupt_.audioFocusType.streamType == STREAM_DEFAULT || audioInterrupt_.streamId == INVALID_SESSION_ID) { return false; } @@ -925,7 +936,7 @@ bool AudioRendererPrivate::Start(StateChangeCmdType cmdType) float duckVolume = audioStream_->GetDuckVolume(); bool isMute = audioStream_->GetMute(); - AUDIO_INFO_LOG("VolumeInfo for Renderer::Start. duckVolume: %{public}f, isMute: %{public}d, "\ + AUDIO_INFO_LOG("VolumeInfo for Renderer::Start. duckVolume: %{public}f, isMute: %{public}d, MinStreamVolume:"\ "MinStreamVolume: %{public}f, MaxStreamVolume: %{public}f", duckVolume, isMute, GetMinStreamVolume(), GetMaxStreamVolume()); @@ -1026,7 +1037,10 @@ bool AudioRendererPrivate::Flush() const bool AudioRendererPrivate::PauseTransitent(StateChangeCmdType cmdType) { Trace trace("AudioRenderer::PauseTransitent"); - std::lock_guard lock(rendererMutex_); + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(rendererMutex_); + } AUDIO_INFO_LOG("StreamClientState for Renderer::PauseTransitent. id: %{public}u", sessionID_); if (isSwitching_) { AUDIO_ERR_LOG("failed. Switching state: %{public}d", isSwitching_); @@ -1056,8 +1070,10 @@ bool AudioRendererPrivate::PauseTransitent(StateChangeCmdType cmdType) bool AudioRendererPrivate::Mute(StateChangeCmdType cmdType) const { Trace trace("AudioRenderer::Mute"); - std::shared_lock lock(rendererMutex_); - + std::shared_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::shared_lock(rendererMutex_); + } AUDIO_INFO_LOG("StreamClientState for Renderer::Mute. id: %{public}u", sessionID_); (void)audioStream_->SetMute(true); return true; @@ -1066,8 +1082,10 @@ bool AudioRendererPrivate::Mute(StateChangeCmdType cmdType) const bool AudioRendererPrivate::Unmute(StateChangeCmdType cmdType) const { Trace trace("AudioRenderer::Unmute"); - std::shared_lock lock(rendererMutex_); - + std::shared_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::shared_lock(rendererMutex_); + } AUDIO_INFO_LOG("StreamClientState for Renderer::Unmute. id: %{public}u", sessionID_); (void)audioStream_->SetMute(false); return true; @@ -1080,8 +1098,10 @@ bool AudioRendererPrivate::Pause(StateChangeCmdType cmdType) [](void *) { AUDIO_ERR_LOG("Pause timeout"); }, nullptr, AUDIO_XCOLLIE_FLAG_LOG); - std::lock_guard lock(rendererMutex_); - + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(rendererMutex_); + } AUDIO_INFO_LOG("StreamClientState for Renderer::Pause. id: %{public}u", sessionID_); CHECK_AND_RETURN_RET_LOG(!isSwitching_, false, "Pause failed. Switching state: %{public}d", isSwitching_); @@ -1116,7 +1136,10 @@ bool AudioRendererPrivate::Pause(StateChangeCmdType cmdType) bool AudioRendererPrivate::Stop() { AUDIO_INFO_LOG("StreamClientState for Renderer::Stop. id: %{public}u", sessionID_); - std::lock_guard lock(rendererMutex_); + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(rendererMutex_); + } CHECK_AND_RETURN_RET_LOG(!isSwitching_, false, "AudioRenderer::Stop failed. Switching state: %{public}d", isSwitching_); if (IsNoStreamRenderer()) { @@ -1144,7 +1167,10 @@ bool AudioRendererPrivate::Stop() bool AudioRendererPrivate::Release() { - std::unique_lock lock(rendererMutex_); + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(rendererMutex_); + } AUDIO_INFO_LOG("StreamClientState for Renderer::Release. id: %{public}u", sessionID_); bool result = audioStream_->ReleaseAudioStream(); @@ -1514,7 +1540,9 @@ int32_t AudioRendererPrivate::SetRenderMode(AudioRenderMode renderMode) audioRenderMode_ = renderMode; std::shared_ptr currentStream = GetInnerStream(); CHECK_AND_RETURN_RET_LOG(currentStream != nullptr, ERROR_ILLEGAL_STATE, "audioStream_ is nullptr"); - return currentStream->SetRenderMode(renderMode); + int32_t ret = currentStream->SetRenderMode(renderMode); + callbackLoopTid_ = audioStream_->GetCallbackLoopTid(); + return ret; } AudioRenderMode AudioRendererPrivate::GetRenderMode() const @@ -1589,7 +1617,10 @@ void AudioRendererPrivate::SetInterruptMode(InterruptMode mode) void AudioRendererPrivate::SetSilentModeAndMixWithOthers(bool on) { Trace trace(std::string("AudioRenderer::SetSilentModeAndMixWithOthers:") + (on ? "on" : "off")); - std::shared_lock sharedLockSwitch(rendererMutex_); + std::shared_lock sharedLockSwitch; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + sharedLockSwitch = std::shared_lock(rendererMutex_); + } std::lock_guard lock(silentModeAndMixWithOthersMutex_); if (audioStream_->GetSilentModeAndMixWithOthers() && !on) { audioInterrupt_.sessionStrategy.concurrencyMode = originalStrategy_.concurrencyMode; @@ -1711,7 +1742,10 @@ uint32_t AudioRendererPrivate::GetUnderflowCount() const void AudioRendererPrivate::SetAudioRendererErrorCallback(std::shared_ptr errorCallback) { - std::shared_lock sharedLock(rendererMutex_); + std::shared_lock sharedLock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + sharedLock = std::shared_lock(rendererMutex_); + } std::lock_guard lock(audioRendererErrCallbackMutex_); audioRendererErrorCallback_ = errorCallback; } @@ -1778,6 +1812,7 @@ bool AudioRendererPrivate::SetSwitchInfo(IAudioStream::SwitchInfo info, std::sha CHECK_AND_RETURN_RET_LOG(res == SUCCESS, false, "SetAudioStreamInfo failed"); audioStream->SetDefaultOutputDevice(info.defaultOutputDevice); audioStream->SetRenderMode(info.renderMode); + callbackLoopTid_ = audioStream_->GetCallbackLoopTid(); audioStream->SetAudioEffectMode(info.effectMode); audioStream->SetVolume(info.volume); audioStream->SetUnderflowCount(info.underFlowCount); @@ -2330,7 +2365,10 @@ void RendererPolicyServiceDiedCallback::RestoreTheadLoop() void AudioRendererPrivate::RestoreAudioInLoop(bool &restoreResult, int32_t &tryCounter) { - std::lock_guard lock(rendererMutex_); + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(rendererMutex_); + } CHECK_AND_RETURN_LOG(audioStream_, "audioStream_ is nullptr, no need for restore"); AUDIO_INFO_LOG("Restore audio renderer when server died, session %{public}u", sessionID_); RestoreInfo restoreInfo; @@ -2349,8 +2387,10 @@ int32_t AudioRendererPrivate::SetSpeed(float speed) AUDIO_INFO_LOG("set speed %{public}f", speed); CHECK_AND_RETURN_RET_LOG((speed >= MIN_STREAM_SPEED_LEVEL) && (speed <= MAX_STREAM_SPEED_LEVEL), ERR_INVALID_PARAM, "invaild speed index"); - - std::lock_guard lock(rendererMutex_); + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(rendererMutex_); + } #ifdef SONIC_ENABLE CHECK_AND_RETURN_RET_LOG(audioStream_ != nullptr, ERROR_ILLEGAL_STATE, "audioStream_ is nullptr"); audioStream_->SetSpeed(speed); @@ -2364,7 +2404,10 @@ int32_t AudioRendererPrivate::SetPitch(float pitch) AUDIO_INFO_LOG("set pitch %{public}f", pitch); CHECK_AND_RETURN_RET_LOG((pitch >= MIN_STREAM_SPEED_LEVEL) && (pitch <= MAX_STREAM_SPEED_LEVEL), ERR_INVALID_PARAM, "invaild pitch index"); - std::lock_guard lock(rendererMutex_); + std::unique_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::unique_lock(rendererMutex_); + } #ifdef SONIC_ENABLE CHECK_AND_RETURN_RET_LOG(audioStream_ != nullptr, ERROR_ILLEGAL_STATE, "audioStream_ is nullptr"); audioStream_->SetPitch(pitch); @@ -2375,7 +2418,10 @@ int32_t AudioRendererPrivate::SetPitch(float pitch) float AudioRendererPrivate::GetSpeed() { - std::shared_lock lock(rendererMutex_); + std::shared_lock lock; + if (callbackLoopTid_ != gettid()) { // No need to add lock in callback thread to prevent deadlocks + lock = std::shared_lock(rendererMutex_); + } #ifdef SONIC_ENABLE CHECK_AND_RETURN_RET_LOG(audioStream_ != nullptr, ERROR_ILLEGAL_STATE, "audioStream_ is nullptr"); return audioStream_->GetSpeed(); diff --git a/frameworks/native/audiostream/include/fast_audio_stream.h b/frameworks/native/audiostream/include/fast_audio_stream.h index f242e80446..c91878303f 100644 --- a/frameworks/native/audiostream/include/fast_audio_stream.h +++ b/frameworks/native/audiostream/include/fast_audio_stream.h @@ -202,6 +202,8 @@ public: RestoreStatus SetRestoreStatus(RestoreStatus restoreStatus) override; void FetchDeviceForSplitStream() override; void SetCallStartByUserTid(pid_t tid) override; + void SetCallbackLoopTid(int32_t tid) override; + int32_t GetCallbackLoopTid() override; private: void UpdateRegisterTrackerInfo(AudioRegisterTrackerInfo ®isterTrackerInfo); int32_t InitializeAudioProcessConfig(AudioProcessConfig &config, const AudioStreamParams &info); @@ -251,6 +253,8 @@ private: std::mutex lastCallStartByUserTidMutex_; std::optional lastCallStartByUserTid_ = std::nullopt; + int32_t callbackLoopTid_ = -1; + enum { STATE_CHANGE_EVENT = 0 }; diff --git a/frameworks/native/audiostream/include/i_audio_stream.h b/frameworks/native/audiostream/include/i_audio_stream.h index 1193b902b7..09eca68aee 100644 --- a/frameworks/native/audiostream/include/i_audio_stream.h +++ b/frameworks/native/audiostream/include/i_audio_stream.h @@ -302,6 +302,10 @@ public: virtual void FetchDeviceForSplitStream() = 0; virtual void SetCallStartByUserTid(pid_t tid) = 0; + + virtual void SetCallbackLoopTid(int32_t tid) = 0; + + virtual int32_t GetCallbackLoopTid() = 0; }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/client/include/renderer_in_client_private.h b/services/audio_service/client/include/renderer_in_client_private.h index e355b1e3c9..87d626a9b3 100644 --- a/services/audio_service/client/include/renderer_in_client_private.h +++ b/services/audio_service/client/include/renderer_in_client_private.h @@ -207,6 +207,8 @@ public: RestoreStatus SetRestoreStatus(RestoreStatus restoreStatus) override; void FetchDeviceForSplitStream() override; void SetCallStartByUserTid(pid_t tid) override; + void SetCallbackLoopTid(int32_t tid) override; + int32_t GetCallbackLoopTid() override; private: void RegisterTracker(const std::shared_ptr &proxyObj); @@ -315,6 +317,8 @@ private: // callback mode releated AudioRenderMode renderMode_ = RENDER_MODE_NORMAL; + std::thread callbackLoop_; // thread for callback to client and write. + int32_t callbackLoopTid_ = -1; std::atomic cbThreadReleased_ = true; std::mutex writeCbMutex_; std::condition_variable cbThreadCv_; 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 4df1e84353..6c450bb273 100644 --- a/services/audio_service/client/src/audio_process_in_client.cpp +++ b/services/audio_service/client/src/audio_process_in_client.cpp @@ -377,13 +377,6 @@ std::shared_ptr AudioProcessInClient::Create(const AudioPr AudioProcessInClientInner::~AudioProcessInClientInner() { AUDIO_INFO_LOG("AudioProcessInClient deconstruct."); - if (callbackLoop_.joinable()) { - std::unique_lock lock(loopThreadLock_); - isCallbackLoopEnd_ = true; // change it with lock to break the loop - threadStatusCV_.notify_all(); - lock.unlock(); // should call unlock before join - callbackLoop_.detach(); - } if (isInited_) { AudioProcessInClientInner::Release(); } @@ -655,6 +648,7 @@ void AudioProcessInClientInner::InitPlaybackThread(std::weak_ptr strongProcess = weakProcess.lock(); std::shared_ptr strongStream = weakStream.lock(); + strongStream->SetCallbackLoopTid(gettid()); if (strongProcess != nullptr) { AUDIO_INFO_LOG("Callback loop of session %{public}u start", strongProcess->sessionId_); strongProcess->processProxy_->RegisterThreadPriority(gettid(), @@ -1232,6 +1226,14 @@ int32_t AudioProcessInClientInner::Release(bool isSwitchStream) return ERR_OPERATION_FAILED; } + if (callbackLoop_.joinable()) { + std::unique_lock lock(loopThreadLock_); + isCallbackLoopEnd_ = true; // change it with lock to break the loop + threadStatusCV_.notify_all(); + lock.unlock(); // should call unlock before join + callbackLoop_.join(); + } + streamStatus_->store(StreamStatus::STREAM_RELEASED); AUDIO_INFO_LOG("Success release proc client mode %{public}d.", processConfig_.audioMode); isInited_ = false; diff --git a/services/audio_service/client/src/capturer_in_client.cpp b/services/audio_service/client/src/capturer_in_client.cpp index 2f4666e0b0..f6c590bd54 100644 --- a/services/audio_service/client/src/capturer_in_client.cpp +++ b/services/audio_service/client/src/capturer_in_client.cpp @@ -224,6 +224,8 @@ public: void FetchDeviceForSplitStream() override; void SetCallStartByUserTid(pid_t tid) override; + void SetCallbackLoopTid(int32_t tid) override; + int32_t GetCallbackLoopTid() override; private: void RegisterTracker(const std::shared_ptr &proxyObj); void UpdateTracker(const std::string &updateCase); @@ -273,6 +275,7 @@ private: // callback mode AudioCaptureMode capturerMode_ = CAPTURE_MODE_NORMAL; std::thread callbackLoop_; // thread for callback to client and write. + int32_t callbackLoopTid_ = -1; std::atomic cbThreadReleased_ = true; std::mutex readCbMutex_; // lock for change or use callback std::condition_variable cbThreadCv_; @@ -1064,6 +1067,7 @@ void CapturerInClientInner::InitCallbackLoop() callbackLoop_ = std::thread([weakRef] { bool keepRunning = true; std::shared_ptr strongRef = weakRef.lock(); + strongRef->SetCallbackLoopTid(gettid()); if (strongRef != nullptr) { strongRef->cbThreadCv_.notify_one(); AUDIO_INFO_LOG("Thread start, sessionID :%{public}d", strongRef->sessionId_); @@ -1531,7 +1535,7 @@ bool CapturerInClientInner::ReleaseAudioStream(bool releaseRunner, bool isSwitch cbThreadCv_.notify_all(); readDataCV_.notify_all(); if (callbackLoop_.joinable()) { - callbackLoop_.detach(); + callbackLoop_.join(); } } paramsIsSet_ = false; @@ -2062,6 +2066,17 @@ void CapturerInClientInner::SetCallStartByUserTid(pid_t tid) { AUDIO_WARNING_LOG("not supported in capturer"); } + +void CapturerInClientInner::SetCallbackLoopTid(int32_t tid) +{ + AUDIO_INFO_LOG("Callback loop tid: %{public}d", tid); + callbackLoopTid_ = tid; +} + +int32_t CapturerInClientInner::GetCallbackLoopTid() +{ + return callbackLoopTid_; +} } // namespace AudioStandard } // namespace OHOS #endif // FAST_AUDIO_STREAM_H diff --git a/services/audio_service/client/src/fast_audio_stream.cpp b/services/audio_service/client/src/fast_audio_stream.cpp index 89e7b30510..c64c609a00 100644 --- a/services/audio_service/client/src/fast_audio_stream.cpp +++ b/services/audio_service/client/src/fast_audio_stream.cpp @@ -1137,5 +1137,16 @@ void FastAudioStream::SetCallStartByUserTid(pid_t tid) std::lock_guard lock(lastCallStartByUserTidMutex_); lastCallStartByUserTid_ = tid; } + +void FastAudioStream::SetCallbackLoopTid(int32_t tid) +{ + AUDIO_INFO_LOG("Callback loop tid: %{public}d", tid); + callbackLoopTid_ = tid; +} + +int32_t FastAudioStream::GetCallbackLoopTid() +{ + return callbackLoopTid_; +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/client/src/renderer_in_client.cpp b/services/audio_service/client/src/renderer_in_client.cpp index 29783f3e27..fb5ef5a876 100644 --- a/services/audio_service/client/src/renderer_in_client.cpp +++ b/services/audio_service/client/src/renderer_in_client.cpp @@ -388,10 +388,7 @@ int32_t RendererInClientInner::ProcessWriteInner(BufferDesc &bufferDesc) bool RendererInClientInner::WriteCallbackFunc() { - if (cbThreadReleased_) { - AUDIO_INFO_LOG("Callback thread released"); - return false; - } + CHECK_AND_RETURN_RET_LOG(!cbThreadReleased_, false, "Callback thread released"); Trace traceLoop("RendererInClientInner::WriteCallbackFunc"); if (!WaitForRunning()) { return true; diff --git a/services/audio_service/client/src/renderer_in_client_public.cpp b/services/audio_service/client/src/renderer_in_client_public.cpp index f61873b9b5..73f795f867 100644 --- a/services/audio_service/client/src/renderer_in_client_public.cpp +++ b/services/audio_service/client/src/renderer_in_client_public.cpp @@ -616,9 +616,10 @@ void RendererInClientInner::InitCallbackLoop() cbThreadReleased_ = false; auto weakRef = weak_from_this(); // OS_AudioWriteCB - std::thread callbackLoop = std::thread([weakRef] { + callbackLoop_ = std::thread([weakRef] { bool keepRunning = true; std::shared_ptr strongRef = weakRef.lock(); + strongRef->SetCallbackLoopTid(gettid()); if (strongRef != nullptr) { strongRef->cbThreadCv_.notify_one(); AUDIO_INFO_LOG("WriteCallbackFunc start, sessionID :%{public}d", strongRef->sessionId_); @@ -639,8 +640,7 @@ void RendererInClientInner::InitCallbackLoop() AUDIO_INFO_LOG("CBThread end sessionID :%{public}d", strongRef->sessionId_); } }); - pthread_setname_np(callbackLoop.native_handle(), "OS_AudioWriteCB"); - callbackLoop.detach(); + pthread_setname_np(callbackLoop_.native_handle(), "OS_AudioWriteCB"); } int32_t RendererInClientInner::SetRenderMode(AudioRenderMode renderMode) @@ -1084,6 +1084,9 @@ bool RendererInClientInner::ReleaseAudioStream(bool releaseRunner, bool isSwitch cbThreadReleased_ = true; // stop loop cbThreadCv_.notify_all(); FutexTool::FutexWake(clientBuffer_->GetFutex(), IS_PRE_EXIT); + if (callbackLoop_.joinable()) { + callbackLoop_.join(); + } } paramsIsSet_ = false; @@ -1807,5 +1810,16 @@ void RendererInClientInner::SetCallStartByUserTid(pid_t tid) std::lock_guard lock(lastCallStartByUserTidMutex_); lastCallStartByUserTid_ = tid; } + +void RendererInClientInner::SetCallbackLoopTid(int32_t tid) +{ + AUDIO_INFO_LOG("Callback loop tid: %{public}d", tid); + callbackLoopTid_ = tid; +} + +int32_t RendererInClientInner::GetCallbackLoopTid() +{ + return callbackLoopTid_; +} } // namespace AudioStandard } // namespace OHOS \ No newline at end of file -- Gitee From d484836d30d21cb6521b06e371129b34afdae11c Mon Sep 17 00:00:00 2001 From: liyuhang Date: Thu, 8 May 2025 15:02:47 +0000 Subject: [PATCH 2/3] Use cv Signed-off-by: liyuhang Change-Id: Id54761e20ab0d382df60d0655fc97c1c1268a054 --- .../audiostream/include/fast_audio_stream.h | 3 +++ .../include/renderer_in_client_private.h | 3 +++ .../client/src/audio_process_in_client.cpp | 3 +++ .../client/src/capturer_in_client.cpp | 20 +++++++++++++++++++ .../client/src/fast_audio_stream.cpp | 16 +++++++++++++++ .../client/src/renderer_in_client.cpp | 6 ++++++ .../client/src/renderer_in_client_public.cpp | 11 ++++++++++ 7 files changed, 62 insertions(+) diff --git a/frameworks/native/audiostream/include/fast_audio_stream.h b/frameworks/native/audiostream/include/fast_audio_stream.h index c91878303f..aab74fa9ae 100644 --- a/frameworks/native/audiostream/include/fast_audio_stream.h +++ b/frameworks/native/audiostream/include/fast_audio_stream.h @@ -204,6 +204,7 @@ public: void SetCallStartByUserTid(pid_t tid) override; void SetCallbackLoopTid(int32_t tid) override; int32_t GetCallbackLoopTid() override; + void ResetCallbackLoopTid(); private: void UpdateRegisterTrackerInfo(AudioRegisterTrackerInfo ®isterTrackerInfo); int32_t InitializeAudioProcessConfig(AudioProcessConfig &config, const AudioStreamParams &info); @@ -254,6 +255,8 @@ private: std::optional lastCallStartByUserTid_ = std::nullopt; int32_t callbackLoopTid_ = -1; + std::mutex callbackLoopTidMutex_; + std::condition_variable callbackLoopTidCv_; enum { STATE_CHANGE_EVENT = 0 diff --git a/services/audio_service/client/include/renderer_in_client_private.h b/services/audio_service/client/include/renderer_in_client_private.h index 87d626a9b3..8d39ef56bc 100644 --- a/services/audio_service/client/include/renderer_in_client_private.h +++ b/services/audio_service/client/include/renderer_in_client_private.h @@ -269,6 +269,7 @@ private: void RegisterThreadPriorityOnStart(StateChangeCmdType cmdType); + void ResetCallbackLoopTid() private: AudioStreamType eStreamType_ = AudioStreamType::STREAM_DEFAULT; int32_t appUid_ = 0; @@ -319,6 +320,8 @@ private: AudioRenderMode renderMode_ = RENDER_MODE_NORMAL; std::thread callbackLoop_; // thread for callback to client and write. int32_t callbackLoopTid_ = -1; + std::mutex callbackLoopTidMutex_; + std::condition_variable callbackLoopTidCv_; std::atomic cbThreadReleased_ = true; std::mutex writeCbMutex_; std::condition_variable cbThreadCv_; 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 6c450bb273..7ab67fa918 100644 --- a/services/audio_service/client/src/audio_process_in_client.cpp +++ b/services/audio_service/client/src/audio_process_in_client.cpp @@ -640,6 +640,9 @@ void AudioProcessInClientInner::InitPlaybackThread(std::weak_ptr fastStream = weakStream.lock(); + CHECK_AND_RETURN_LOG(fastStream != nullptr, "fast stream is null"); + fastStream->ResetCallbackLoopTid(); callbackLoop_ = std::thread([weakStream, weakProcess] { bool keepRunning = true; uint64_t curWritePos = 0; diff --git a/services/audio_service/client/src/capturer_in_client.cpp b/services/audio_service/client/src/capturer_in_client.cpp index f6c590bd54..56f54342c9 100644 --- a/services/audio_service/client/src/capturer_in_client.cpp +++ b/services/audio_service/client/src/capturer_in_client.cpp @@ -253,6 +253,7 @@ private: int32_t HandleCapturerRead(size_t &readSize, size_t &userSize, uint8_t &buffer, bool isBlockingRead); int32_t RegisterCapturerInClientPolicyServerDiedCb(); int32_t UnregisterCapturerInClientPolicyServerDiedCb(); + void ResetCallbackLoopTid(); private: AudioStreamType eStreamType_; int32_t appUid_; @@ -276,6 +277,8 @@ private: AudioCaptureMode capturerMode_ = CAPTURE_MODE_NORMAL; std::thread callbackLoop_; // thread for callback to client and write. int32_t callbackLoopTid_ = -1; + std::mutex callbackLoopTidMutex_; + std::condition_variable callbackLoopTidCv_; std::atomic cbThreadReleased_ = true; std::mutex readCbMutex_; // lock for change or use callback std::condition_variable cbThreadCv_; @@ -1064,6 +1067,7 @@ void CapturerInClientInner::InitCallbackLoop() auto weakRef = weak_from_this(); // OS_AudioWriteCB + ResetCallbackLoopTid(); callbackLoop_ = std::thread([weakRef] { bool keepRunning = true; std::shared_ptr strongRef = weakRef.lock(); @@ -2071,12 +2075,28 @@ void CapturerInClientInner::SetCallbackLoopTid(int32_t tid) { AUDIO_INFO_LOG("Callback loop tid: %{public}d", tid); callbackLoopTid_ = tid; + callbackLoopTidCv_.notify_all(); } int32_t CapturerInClientInner::GetCallbackLoopTid() { + std::unique_lock waitLock(callbackLoopTidMutex_); + bool stopWaiting = callbackLoopTidCv_.wait_for(waitLock, std::chrono::seconds(1), [this] { + return callbackLoopTid_ != -1; // callbackLoopTid_ will change when got notified. + }); + + if (!stopWaiting) { + AUDIO_WARNING_LOG("Wait timeout"); + callbackLoopTid_ = 0; // set tid to prevent get operation from getting stuck + } return callbackLoopTid_; } + +void CapturerInClientInner::ResetCallbackLoopTid() +{ + AUDIO_INFO_LOG("Reset callback loop tid to -1"); + callbackLoopTid_ = -1; +} } // namespace AudioStandard } // namespace OHOS #endif // FAST_AUDIO_STREAM_H diff --git a/services/audio_service/client/src/fast_audio_stream.cpp b/services/audio_service/client/src/fast_audio_stream.cpp index c64c609a00..e050e885e4 100644 --- a/services/audio_service/client/src/fast_audio_stream.cpp +++ b/services/audio_service/client/src/fast_audio_stream.cpp @@ -1142,11 +1142,27 @@ void FastAudioStream::SetCallbackLoopTid(int32_t tid) { AUDIO_INFO_LOG("Callback loop tid: %{public}d", tid); callbackLoopTid_ = tid; + callbackLoopTidCv_.notify_all(); } int32_t FastAudioStream::GetCallbackLoopTid() { + std::unique_lock waitLock(callbackLoopTidMutex_); + bool stopWaiting = callbackLoopTidCv_.wait_for(waitLock, std::chrono::seconds(1), [this] { + return callbackLoopTid_ != -1; // callbackLoopTid_ will change when got notified. + }); + + if (!stopWaiting) { + AUDIO_WARNING_LOG("Wait timeout"); + callbackLoopTid_ = 0; // set tid to prevent get operation from getting stuck + } return callbackLoopTid_; } + +void FastAudioStream::ResetCallbackLoopTid() +{ + AUDIO_INFO_LOG("Reset callback loop tid to -1"); + callbackLoopTid_ = -1; +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/client/src/renderer_in_client.cpp b/services/audio_service/client/src/renderer_in_client.cpp index fb5ef5a876..a8f2247d3e 100644 --- a/services/audio_service/client/src/renderer_in_client.cpp +++ b/services/audio_service/client/src/renderer_in_client.cpp @@ -904,6 +904,12 @@ void RendererInClientInner::RegisterThreadPriorityOnStart(StateChangeCmdType cmd AudioSystemManager::GetInstance()->GetSelfBundleName(clientConfig_.appInfo.appUid), METHOD_START); } +void RendererInClientInner::ResetCallbackLoopTid() +{ + AUDIO_INFO_LOG("Reset callback loop tid to -1"); + callbackLoopTid_ = -1; +} + SpatializationStateChangeCallbackImpl::SpatializationStateChangeCallbackImpl() { AUDIO_INFO_LOG("Instance create"); diff --git a/services/audio_service/client/src/renderer_in_client_public.cpp b/services/audio_service/client/src/renderer_in_client_public.cpp index 73f795f867..82fca27bcc 100644 --- a/services/audio_service/client/src/renderer_in_client_public.cpp +++ b/services/audio_service/client/src/renderer_in_client_public.cpp @@ -615,6 +615,7 @@ void RendererInClientInner::InitCallbackLoop() { cbThreadReleased_ = false; auto weakRef = weak_from_this(); + ResetCallbackLoopTid(); // OS_AudioWriteCB callbackLoop_ = std::thread([weakRef] { bool keepRunning = true; @@ -1815,10 +1816,20 @@ void RendererInClientInner::SetCallbackLoopTid(int32_t tid) { AUDIO_INFO_LOG("Callback loop tid: %{public}d", tid); callbackLoopTid_ = tid; + callbackLoopTidCv_.notify_all(); } int32_t RendererInClientInner::GetCallbackLoopTid() { + std::unique_lock waitLock(callbackLoopTidMutex_); + bool stopWaiting = callbackLoopTidCv_.wait_for(waitLock, std::chrono::seconds(1), [this] { + return callbackLoopTid_ != -1; // callbackLoopTid_ will change when got notified. + }); + + if (!stopWaiting) { + AUDIO_WARNING_LOG("Wait timeout"); + callbackLoopTid_ = 0; // set tid to prevent get operation from getting stuck + } return callbackLoopTid_; } } // namespace AudioStandard -- Gitee From 14295132ab3393f090f9d8b7a63d4dc3882a4f8a Mon Sep 17 00:00:00 2001 From: liyuhang Date: Thu, 8 May 2025 15:22:04 +0000 Subject: [PATCH 3/3] Code check Signed-off-by: liyuhang Change-Id: I7ae218e2670af01048cd476ccac82721372719ae --- .../audio_service/client/include/renderer_in_client_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/audio_service/client/include/renderer_in_client_private.h b/services/audio_service/client/include/renderer_in_client_private.h index 8d39ef56bc..581ca8959e 100644 --- a/services/audio_service/client/include/renderer_in_client_private.h +++ b/services/audio_service/client/include/renderer_in_client_private.h @@ -269,7 +269,7 @@ private: void RegisterThreadPriorityOnStart(StateChangeCmdType cmdType); - void ResetCallbackLoopTid() + void ResetCallbackLoopTid(); private: AudioStreamType eStreamType_ = AudioStreamType::STREAM_DEFAULT; int32_t appUid_ = 0; -- Gitee