audio: Fix resume in StreamOffloadStub
An override of `DriverInterface::start` was lacking, added
and implemented to support resume after draining.
Added logging of `DriverInterface` calls for the DriverStubImpl.
Bug: 373872271
Bug: 384431822
Test: atest CtsMediaAudioTestCases
Test: atest VtsHalAudioCoreTargetTest
Change-Id: I88b561b7f878c2bb408826ac6f65b577ee700dd1
diff --git a/audio/aidl/default/include/core-impl/DriverStubImpl.h b/audio/aidl/default/include/core-impl/DriverStubImpl.h
index a1a6c82..84f869a 100644
--- a/audio/aidl/default/include/core-impl/DriverStubImpl.h
+++ b/audio/aidl/default/include/core-impl/DriverStubImpl.h
@@ -22,7 +22,9 @@
class DriverStubImpl : virtual public DriverInterface {
public:
- explicit DriverStubImpl(const StreamContext& context);
+ explicit DriverStubImpl(const StreamContext& context)
+ : DriverStubImpl(context, 500 /*asyncSleepTimeUs*/) {}
+ DriverStubImpl(const StreamContext& context, int asyncSleepTimeUs);
::android::status_t init(DriverCallbackInterface* callback) override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
@@ -40,6 +42,8 @@
const int mSampleRate;
const bool mIsAsynchronous;
const bool mIsInput;
+ const int32_t mMixPortHandle;
+ const int mAsyncSleepTimeUs;
bool mIsInitialized = false; // Used for validating the state machine logic.
bool mIsStandby = true; // Used for validating the state machine logic.
int64_t mStartTimeNs = 0;
diff --git a/audio/aidl/default/include/core-impl/StreamOffloadStub.h b/audio/aidl/default/include/core-impl/StreamOffloadStub.h
index 3b452f9..67abe95 100644
--- a/audio/aidl/default/include/core-impl/StreamOffloadStub.h
+++ b/audio/aidl/default/include/core-impl/StreamOffloadStub.h
@@ -60,11 +60,14 @@
::android::status_t drain(StreamDescriptor::DrainMode drainMode) override;
::android::status_t flush() override;
::android::status_t pause() override;
+ ::android::status_t start() override;
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
void shutdown() override;
private:
+ ::android::status_t startWorkerIfNeeded();
+
DspSimulatorState mState;
DspSimulatorWorker mDspWorker;
bool mDspWorkerStarted = false;
diff --git a/audio/aidl/default/stub/DriverStubImpl.cpp b/audio/aidl/default/stub/DriverStubImpl.cpp
index 107affb..0d129e6 100644
--- a/audio/aidl/default/stub/DriverStubImpl.cpp
+++ b/audio/aidl/default/stub/DriverStubImpl.cpp
@@ -24,19 +24,27 @@
namespace aidl::android::hardware::audio::core {
-DriverStubImpl::DriverStubImpl(const StreamContext& context)
+DriverStubImpl::DriverStubImpl(const StreamContext& context, int asyncSleepTimeUs)
: mBufferSizeFrames(context.getBufferSizeInFrames()),
mFrameSizeBytes(context.getFrameSize()),
mSampleRate(context.getSampleRate()),
mIsAsynchronous(!!context.getAsyncCallback()),
- mIsInput(context.isInput()) {}
+ mIsInput(context.isInput()),
+ mMixPortHandle(context.getMixPortHandle()),
+ mAsyncSleepTimeUs(asyncSleepTimeUs) {}
+
+#define LOG_ENTRY() \
+ LOG(DEBUG) << "[" << (mIsInput ? "in" : "out") << "|ioHandle:" << mMixPortHandle << "] " \
+ << __func__;
::android::status_t DriverStubImpl::init(DriverCallbackInterface* /*callback*/) {
+ LOG_ENTRY();
mIsInitialized = true;
return ::android::OK;
}
::android::status_t DriverStubImpl::drain(StreamDescriptor::DrainMode) {
+ LOG_ENTRY();
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
@@ -46,14 +54,15 @@
const size_t delayUs = static_cast<size_t>(
std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate));
usleep(delayUs);
- } else {
- usleep(500);
+ } else if (mAsyncSleepTimeUs) {
+ usleep(mAsyncSleepTimeUs);
}
}
return ::android::OK;
}
::android::status_t DriverStubImpl::flush() {
+ LOG_ENTRY();
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
@@ -61,6 +70,7 @@
}
::android::status_t DriverStubImpl::pause() {
+ LOG_ENTRY();
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
@@ -68,6 +78,7 @@
}
::android::status_t DriverStubImpl::standby() {
+ LOG_ENTRY();
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
@@ -76,6 +87,7 @@
}
::android::status_t DriverStubImpl::start() {
+ LOG_ENTRY();
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
@@ -87,6 +99,7 @@
::android::status_t DriverStubImpl::transfer(void* buffer, size_t frameCount,
size_t* actualFrameCount, int32_t*) {
+ // No LOG_ENTRY as this is called very often.
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
@@ -95,7 +108,7 @@
}
*actualFrameCount = frameCount;
if (mIsAsynchronous) {
- usleep(500);
+ if (mAsyncSleepTimeUs) usleep(mAsyncSleepTimeUs);
} else {
mFramesSinceStart += *actualFrameCount;
const long bufferDurationUs = (*actualFrameCount) * MICROS_PER_SECOND / mSampleRate;
@@ -120,6 +133,7 @@
}
void DriverStubImpl::shutdown() {
+ LOG_ENTRY();
mIsInitialized = false;
}
diff --git a/audio/aidl/default/stub/StreamOffloadStub.cpp b/audio/aidl/default/stub/StreamOffloadStub.cpp
index fb12697..95cef35 100644
--- a/audio/aidl/default/stub/StreamOffloadStub.cpp
+++ b/audio/aidl/default/stub/StreamOffloadStub.cpp
@@ -81,11 +81,13 @@
}
DriverOffloadStubImpl::DriverOffloadStubImpl(const StreamContext& context)
- : DriverStubImpl(context),
+ : DriverStubImpl(context, 0 /*asyncSleepTimeUs*/),
mState{context.getFormat().encoding, context.getSampleRate(),
250 /*earlyNotifyMs*/ * context.getSampleRate() / MILLIS_PER_SECOND,
static_cast<int64_t>(context.getBufferSizeInFrames()) / 2},
- mDspWorker(mState) {}
+ mDspWorker(mState) {
+ LOG_IF(FATAL, !mIsAsynchronous) << "The steam must be used in asynchronous mode";
+}
::android::status_t DriverOffloadStubImpl::init(DriverCallbackInterface* callback) {
RETURN_STATUS_IF_ERROR(DriverStubImpl::init(callback));
@@ -99,10 +101,7 @@
}
::android::status_t DriverOffloadStubImpl::drain(StreamDescriptor::DrainMode drainMode) {
- // Does not call into the DriverStubImpl::drain.
- if (!mIsInitialized) {
- LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
- }
+ RETURN_STATUS_IF_ERROR(DriverStubImpl::drain(drainMode));
std::lock_guard l(mState.lock);
if (!mState.clipFramesLeft.empty()) {
// Cut playback of the current clip.
@@ -132,23 +131,27 @@
return ::android::OK;
}
+::android::status_t DriverOffloadStubImpl::start() {
+ RETURN_STATUS_IF_ERROR(DriverStubImpl::start());
+ RETURN_STATUS_IF_ERROR(startWorkerIfNeeded());
+ bool hasClips; // Can be start after paused draining.
+ {
+ std::lock_guard l(mState.lock);
+ hasClips = !mState.clipFramesLeft.empty();
+ LOG(DEBUG) << __func__
+ << ": clipFramesLeft: " << ::android::internal::ToString(mState.clipFramesLeft);
+ }
+ if (hasClips) {
+ mDspWorker.resume();
+ }
+ return ::android::OK;
+}
+
::android::status_t DriverOffloadStubImpl::transfer(void* buffer, size_t frameCount,
- size_t* actualFrameCount,
- int32_t* /*latencyMs*/) {
- // Does not call into the DriverStubImpl::transfer.
- if (!mIsInitialized) {
- LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
- }
- if (mIsStandby) {
- LOG(FATAL) << __func__ << ": must not happen while in standby";
- }
- if (!mDspWorkerStarted) {
- // This is an "audio service thread," must have elevated priority.
- if (!mDspWorker.start("dsp_sim", ANDROID_PRIORITY_URGENT_AUDIO)) {
- return ::android::NO_INIT;
- }
- mDspWorkerStarted = true;
- }
+ size_t* actualFrameCount, int32_t* latencyMs) {
+ RETURN_STATUS_IF_ERROR(
+ DriverStubImpl::transfer(buffer, frameCount, actualFrameCount, latencyMs));
+ RETURN_STATUS_IF_ERROR(startWorkerIfNeeded());
// Scan the buffer for clip headers.
*actualFrameCount = frameCount;
while (buffer != nullptr && frameCount > 0) {
@@ -189,6 +192,18 @@
void DriverOffloadStubImpl::shutdown() {
LOG(DEBUG) << __func__ << ": stopping the DSP simulator worker";
mDspWorker.stop();
+ DriverStubImpl::shutdown();
+}
+
+::android::status_t DriverOffloadStubImpl::startWorkerIfNeeded() {
+ if (!mDspWorkerStarted) {
+ // This is an "audio service thread," must have elevated priority.
+ if (!mDspWorker.start("dsp_sim", ANDROID_PRIORITY_URGENT_AUDIO)) {
+ return ::android::NO_INIT;
+ }
+ mDspWorkerStarted = true;
+ }
+ return ::android::OK;
}
// static