From 55e0afa49a600731c3c0f85f65080cac8f5a3b29 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Tue, 5 Mar 2024 17:42:20 -0800 Subject: [PATCH] audio: Fix glitching of remote submix Align behavior with the HIDL implementation. This helps to prevent glitches in the scenarios that use remote submix for sending audio externally: Auto and Cast. Bug: 322247032 Bug: 327220024 Test: Repro steps in b/327220024#comment14 Change-Id: If2e4ebd7145375a268ee5f0e4ab656bb3748b2fe Merged-In: If2e4ebd7145375a268ee5f0e4ab656bb3748b2fe --- audio/aidl/default/include/core-impl/Module.h | 7 ++++++- audio/aidl/default/r_submix/StreamRemoteSubmix.cpp | 9 ++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h index 8abf9ef1fe..d6e89053d9 100644 --- a/audio/aidl/default/include/core-impl/Module.h +++ b/audio/aidl/default/include/core-impl/Module.h @@ -212,7 +212,12 @@ class Module : public BnModule { aidl::android::hardware::audio::common::frameCountFromDurationMs(latencyMs, sampleRateHz); // Round up to nearest 16 frames since in the framework this is the size of a mixer burst. - return (rawSizeFrames + 15) & ~15; + const int32_t multipleOf16 = (rawSizeFrames + 15) & ~15; + if (multipleOf16 <= 512) return multipleOf16; + // Larger buffers should use powers of 2. + int32_t powerOf2 = 1; + while (powerOf2 < multipleOf16) powerOf2 <<= 1; + return powerOf2; } ndk::ScopedAStatus bluetoothParametersUpdated(); diff --git a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp index fa4135d3e5..2376ed9371 100644 --- a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp +++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp @@ -136,10 +136,12 @@ void StreamRemoteSubmix::shutdown() { mCurrentRoute->exitStandby(mIsInput); RETURN_STATUS_IF_ERROR(mIsInput ? inRead(buffer, frameCount, actualFrameCount) : outWrite(buffer, frameCount, actualFrameCount)); + mFramesSinceStart += *actualFrameCount; + if (!mIsInput) return ::android::OK; + // Only input streams need to block, for output this is implemented by MonoPipe. const long bufferDurationUs = (*actualFrameCount) * MICROS_PER_SECOND / mContext.getSampleRate(); const auto totalDurationUs = (::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND; - mFramesSinceStart += *actualFrameCount; const long totalOffsetUs = mFramesSinceStart * MICROS_PER_SECOND / mContext.getSampleRate() - totalDurationUs; LOG(VERBOSE) << __func__ << ": totalOffsetUs " << totalOffsetUs; @@ -275,8 +277,9 @@ size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() { char* buff = (char*)buffer; size_t actuallyRead = 0; long remainingFrames = frameCount; - const int64_t deadlineTimeNs = ::android::uptimeNanos() + - getDelayInUsForFrameCount(frameCount) * NANOS_PER_MICROSECOND; + const int64_t deadlineTimeNs = + ::android::uptimeNanos() + + getDelayInUsForFrameCount(frameCount) * NANOS_PER_MICROSECOND / 2; while (remainingFrames > 0) { ssize_t framesRead = source->read(buff, remainingFrames); LOG(VERBOSE) << __func__ << ": frames read " << framesRead;