aaudio: fix race condition in timestamp path
There was a potential race between setting the first timestamp
and reading the first timestamp that could cause the timestamp service
thread to exit. This would cause the client to not get any timestamps.
Then the timing model would not advance and the stream would stall.
This could result in read() or write() returning zero,
or a TIMEOUT error.
This was rare except for some devices that had different
timing in the HAL.
Bug: 68271891
Bug: 117557847
Test: adb shell write_sine_callback -pl -m2 -n2 -s2 -c2 -l100
Test: atest CtsNativeMediaAAudioTestCases
Change-Id: Ib0974a576aaa17ff8de40899e60ed56015027bd7
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index a7cd128..2f1ec7e 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -193,5 +193,13 @@
aaudio_result_t AAudioServiceEndpointShared::getTimestamp(int64_t *positionFrames,
int64_t *timeNanos) {
- return mStreamInternal->getTimestamp(CLOCK_MONOTONIC, positionFrames, timeNanos);
+ aaudio_result_t result = mStreamInternal->getTimestamp(CLOCK_MONOTONIC, positionFrames, timeNanos);
+ if (result == AAUDIO_ERROR_INVALID_STATE) {
+ // getTimestamp() can return AAUDIO_ERROR_INVALID_STATE if the stream has
+ // not completely started. This can cause a race condition that kills the
+ // timestamp service thread. So we reduce the error to a less serious one
+ // that allows the timestamp thread to continue.
+ result = AAUDIO_ERROR_UNAVAILABLE;
+ }
+ return result;
}