Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec21f2b5 authored by Phil Burk's avatar Phil Burk
Browse files

aaudio: prevent very short sleeps in callback thread

When the buffer size was set to the maximum, the calculation
of the sleep time did not account for the inability to write
ahead of the buffer threshold. So the CPU would wake up,
fail to write, sleep for the minimal time, then repeat.

Now the code checks for the max buffer size.

Bug: b/224871395
Test: see repro steps involving OboeTester in b/224871395#comment19
Test: Use OboeTester, TEST OUTPUT
Test: slide bufferSize fader to far right
Test: look for short sleeps using Perfetto
Change-Id: I2df9e2372c7464ce4f3e8156d7980ec4eadaa2c1
parent be55f493
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -202,10 +202,18 @@ aaudio_result_t AudioStreamInternalPlay::processDataNow(void *buffer, int32_t nu
                break;
            case AAUDIO_STREAM_STATE_STARTED:
            {
                // Sleep until the readCounter catches up and we only have
                // the getBufferSize() frames of data sitting in the buffer.
                int64_t nextReadPosition = mAudioEndpoint->getDataWriteCounter() - getBufferSize();
                wakeTime = mClockModel.convertPositionToTime(nextReadPosition);
                // Calculate when there will be room available to write to the buffer.
                // If the appBufferSize is smaller than the endpointBufferSize then
                // we will have room to write data beyond the appBufferSize.
                // That is a technique used to reduce glitches without adding latency.
                const int32_t appBufferSize = getBufferSize();
                // The endpoint buffer size is set to the maximum that can be written.
                // If we use it then we must carve out some room to write data when we wake up.
                const int32_t endBufferSize = mAudioEndpoint->getBufferSizeInFrames()
                        - getFramesPerBurst();
                const int32_t bestBufferSize = std::min(appBufferSize, endBufferSize);
                int64_t targetReadPosition = mAudioEndpoint->getDataWriteCounter() - bestBufferSize;
                wakeTime = mClockModel.convertPositionToTime(targetReadPosition);
            }
                break;
            default:
+3 −1
Original line number Diff line number Diff line
@@ -562,7 +562,9 @@ int32_t AAudioProperty_getWakeupDelayMicros() {
int32_t AAudioProperty_getMinimumSleepMicros() {
    const int32_t minMicros = 1; // arbitrary
    // Higher values can increase latency for moderate workloads.
    const int32_t defaultMicros = 1; // arbitrary
    // Short values can cause the CPU to short cycle if there is a bug in
    // calculating the wakeup times.
    const int32_t defaultMicros = 100; // arbitrary
    const int32_t maxMicros = 200; // arbitrary
    int32_t prop = property_get_int32(AAUDIO_PROP_MINIMUM_SLEEP_USEC, defaultMicros);
    if (prop < minMicros) {