aaudio: reduce glitching by improving sleep timing
ALways sleep a minimum time to avoid busy wait in real-time thread.
Account for wakeup jitter in threads on the other side of a FIFO.
Avoid race condition that caused a longer sleep than necessary.
Fix calculation of mFreeRunning for capture mode.
Also added systrace logging, which was used to debug this.
Bug: 63814792
Test: Run GStomper on Walleye with MMAP on, see bug
Change-Id: I7b20098580ff454365425bd21e43c17ade532a0a
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
index 22f8bd1..7b1e53e 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
@@ -24,6 +24,9 @@
#include "client/AudioStreamInternalCapture.h"
#include "utility/AudioClock.h"
+#define ATRACE_TAG ATRACE_TAG_AUDIO
+#include <utils/Trace.h>
+
using android::WrappingBuffer;
using namespace aaudio;
@@ -36,7 +39,6 @@
AudioStreamInternalCapture::~AudioStreamInternalCapture() {}
-
// Write the data, block if needed and timeoutMillis > 0
aaudio_result_t AudioStreamInternalCapture::read(void *buffer, int32_t numFrames,
int64_t timeoutNanoseconds)
@@ -52,6 +54,9 @@
return result;
}
+ const char *traceName = "aaRdNow";
+ ATRACE_BEGIN(traceName);
+
if (mAudioEndpoint.isFreeRunning()) {
//ALOGD("AudioStreamInternalCapture::processDataNow() - update remote counter");
// Update data queue based on the timing model.
@@ -63,6 +68,9 @@
// If the write index passed the read index then consider it an overrun.
if (mAudioEndpoint.getEmptyFramesAvailable() < 0) {
mXRunCount++;
+ if (ATRACE_ENABLED()) {
+ ATRACE_INT("aaOverRuns", mXRunCount);
+ }
}
// Read some data from the buffer.
@@ -70,6 +78,9 @@
int32_t framesProcessed = readNowWithConversion(buffer, numFrames);
//ALOGD("AudioStreamInternalCapture::processDataNow() - tried to read %d frames, read %d",
// numFrames, framesProcessed);
+ if (ATRACE_ENABLED()) {
+ ATRACE_INT("aaRead", framesProcessed);
+ }
// Calculate an ideal time to wake up.
if (wakeTimePtr != nullptr && framesProcessed >= 0) {
@@ -82,14 +93,14 @@
case AAUDIO_STREAM_STATE_OPEN:
case AAUDIO_STREAM_STATE_STARTING:
break;
- case AAUDIO_STREAM_STATE_STARTED: // When do we expect the next read burst to occur?
+ case AAUDIO_STREAM_STATE_STARTED:
{
- uint32_t burstSize = mFramesPerBurst;
- if (burstSize < 32) {
- burstSize = 32; // TODO review
- }
+ // When do we expect the next write burst to occur?
- uint64_t nextReadPosition = mAudioEndpoint.getDataWriteCounter() + burstSize;
+ // Calculate frame position based off of the readCounter because
+ // the writeCounter might have just advanced in the background,
+ // causing us to sleep until a later burst.
+ int64_t nextReadPosition = mAudioEndpoint.getDataReadCounter() + mFramesPerBurst;
wakeTime = mClockModel.convertPositionToTime(nextReadPosition);
}
break;
@@ -99,10 +110,8 @@
*wakeTimePtr = wakeTime;
}
-// ALOGD("AudioStreamInternalCapture::readNow finished: now = %llu, read# = %llu, wrote# = %llu",
-// (unsigned long long)currentNanoTime,
-// (unsigned long long)mAudioEndpoint.getDataReadCounter(),
-// (unsigned long long)mAudioEndpoint.getDownDataWriteCounter());
+
+ ATRACE_END();
return framesProcessed;
}