audio flinger: handle race condition in AudioRecord creation
A rare race condition can cause a failure to create an AudioRecord if
two creation requests are processed concurrently and thread preemption happens
at a specific time within the sequence between audioflinger and
audio policy manager.
This CL implements a retry mechanism on client side when this particular failure
is detected.
Bug: 161656190
Test: Regression tests for audio capture use cases.
Test: CTS tests for AudiRecord
Change-Id: I155ee4899baeec21e10a1141cb9e323cbc8aa23b
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 34bdac5..36dc1db 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2071,8 +2071,8 @@
Mutex::Autolock _l(mLock);
RecordThread *thread = checkRecordThread_l(output.inputId);
if (thread == NULL) {
- ALOGE("createRecord() checkRecordThread_l failed, input handle %d", output.inputId);
- lStatus = BAD_VALUE;
+ ALOGW("createRecord() checkRecordThread_l failed, input handle %d", output.inputId);
+ lStatus = FAILED_TRANSACTION;
goto Exit;
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index affc09e..75f0743 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7911,7 +7911,8 @@
AutoMutex lock(mLock);
if (recordTrack->isInvalid()) {
recordTrack->clearSyncStartEvent();
- return INVALID_OPERATION;
+ ALOGW("%s track %d: invalidated before startInput", __func__, recordTrack->portId());
+ return DEAD_OBJECT;
}
if (mActiveTracks.indexOf(recordTrack) >= 0) {
if (recordTrack->mState == TrackBase::PAUSING) {
@@ -7941,7 +7942,8 @@
recordTrack->mState = TrackBase::STARTING_2;
// STARTING_2 forces destroy to call stopInput.
}
- return INVALID_OPERATION;
+ ALOGW("%s track %d: invalidated after startInput", __func__, recordTrack->portId());
+ return DEAD_OBJECT;
}
if (recordTrack->mState != TrackBase::STARTING_1) {
ALOGW("%s(%d): unsynchronized mState:%d change",
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index c92bce5..ed285da 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -2229,7 +2229,8 @@
RecordThread *recordThread = (RecordThread *)thread.get();
return recordThread->start(this, event, triggerSession);
} else {
- return BAD_VALUE;
+ ALOGW("%s track %d: thread was destroyed", __func__, portId());
+ return DEAD_OBJECT;
}
}