AudioTrack and AudioRecord: add stopAndJoinCallbacks()
Explicitly force callbacks to stop running.
This is needed to prevent a race condition with
the callbacks running after a close.
Bug: 164411271
Bug: 143305727
Bug: 182954108
Test: atest CtsNativeMediaAAudioTestCases
Test: libaaudio/tests/test_callback_race.cpp
Change-Id: Ia86c758d7f1c281a5d933bc384283440e1f1a756
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 142a85c..df97658 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -259,12 +259,18 @@
}
void AudioStreamTrack::close_l() {
- // Stop callbacks before deleting mFixedBlockReader memory.
+ // The callbacks are normally joined in the AudioTrack destructor.
+ // But if another object has a reference to the AudioTrack then
+ // it will not get deleted here.
+ // So we should join callbacks explicitly before returning.
+ // Unlock around the join to avoid deadlocks if the callback tries to lock.
+ // This can happen if the callback returns AAUDIO_CALLBACK_RESULT_STOP
+ mStreamLock.unlock();
+ mAudioTrack->stopAndJoinCallbacks();
+ mStreamLock.lock();
mAudioTrack.clear();
- // Do not close mFixedBlockReader because a data callback
- // thread might still be running if someone else has a reference
- // to mAudioRecord.
- // It has a unique_ptr to its buffer so it will clean up by itself.
+ // Do not close mFixedBlockReader. It has a unique_ptr to its buffer
+ // so it will clean up by itself.
AudioStream::close_l();
}