AudioFlinger: Update tee patches before locking effect chain
Test: atest CtsMediaAudioTestCases
Bug: 322460604
Change-Id: Id666302f5c23647fc1e44c6754ba8333d6d82f21
diff --git a/services/audioflinger/IAfTrack.h b/services/audioflinger/IAfTrack.h
index 2302e13..ac4ed36 100644
--- a/services/audioflinger/IAfTrack.h
+++ b/services/audioflinger/IAfTrack.h
@@ -18,6 +18,7 @@
#include <android/media/BnAudioRecord.h>
#include <android/media/BnAudioTrack.h>
+#include <audio_utils/mutex.h>
#include <audiomanager/IAudioManager.h>
#include <binder/IMemory.h>
#include <fastpath/FastMixerDumpState.h>
@@ -351,7 +352,8 @@
virtual sp<os::ExternalVibration> getExternalVibration() const = 0;
// This function should be called with holding thread lock.
- virtual void updateTeePatches_l() = 0;
+ virtual void updateTeePatches_l() REQUIRES(audio_utils::ThreadBase_Mutex)
+ EXCLUDES_BELOW_ThreadBase_Mutex = 0;
// Argument teePatchesToUpdate is by value, use std::move to optimize.
virtual void setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) = 0;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index b4cb805..826ba65 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -194,7 +194,8 @@
sp<os::ExternalVibration> getExternalVibration() const final { return mExternalVibration; }
// This function should be called with holding thread lock.
- void updateTeePatches_l() final;
+ void updateTeePatches_l() final REQUIRES(audio_utils::ThreadBase_Mutex)
+ EXCLUDES_BELOW_ThreadBase_Mutex;
void setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) final;
void tallyUnderrunFrames(size_t frames) final {
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 671e27f..4e422ef 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4160,6 +4160,30 @@
metadataUpdate = updateMetadata_l();
+ // Acquire a local copy of active tracks with lock (release w/o lock).
+ //
+ // Control methods on the track acquire the ThreadBase lock (e.g. start()
+ // stop(), pause(), etc.), but the threadLoop is entitled to call audio
+ // data / buffer methods on tracks from activeTracks without the ThreadBase lock.
+ activeTracks.insert(activeTracks.end(), mActiveTracks.begin(), mActiveTracks.end());
+
+ setHalLatencyMode_l();
+
+ // updateTeePatches_l will acquire the ThreadBase_Mutex of other threads,
+ // so this is done before we lock our effect chains.
+ for (const auto& track : mActiveTracks) {
+ track->updateTeePatches_l();
+ }
+
+ // signal actual start of output stream when the render position reported by
+ // the kernel starts moving.
+ if (!mHalStarted && ((isSuspended() && (mBytesWritten != 0)) || (!mStandby
+ && (mKernelPositionOnStandby
+ != mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL])))) {
+ mHalStarted = true;
+ mWaitHalStartCV.notify_all();
+ }
+
// prevent any changes in effect chain list and in each effect chain
// during mixing and effect process as the audio buffers could be deleted
// or modified if an effect is created or deleted
@@ -4187,28 +4211,6 @@
}
}
}
-
- // Acquire a local copy of active tracks with lock (release w/o lock).
- //
- // Control methods on the track acquire the ThreadBase lock (e.g. start()
- // stop(), pause(), etc.), but the threadLoop is entitled to call audio
- // data / buffer methods on tracks from activeTracks without the ThreadBase lock.
- activeTracks.insert(activeTracks.end(), mActiveTracks.begin(), mActiveTracks.end());
-
- setHalLatencyMode_l();
-
- for (const auto &track : mActiveTracks ) {
- track->updateTeePatches_l();
- }
-
- // signal actual start of output stream when the render position reported by the kernel
- // starts moving.
- if (!mHalStarted && ((isSuspended() && (mBytesWritten != 0)) || (!mStandby
- && (mKernelPositionOnStandby
- != mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL])))) {
- mHalStarted = true;
- mWaitHalStartCV.notify_all();
- }
} // mutex() scope ends
if (mBytesRemaining == 0) {