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