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

Commit f4c93005 authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

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
parent 0f715415
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -22,7 +22,9 @@ namespace aidl::android::hardware::audio::core {

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 @@ class DriverStubImpl : virtual public DriverInterface {
    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;
+3 −0
Original line number Diff line number Diff line
@@ -60,11 +60,14 @@ class DriverOffloadStubImpl : public DriverStubImpl {
    ::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;
+19 −5
Original line number Diff line number Diff line
@@ -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 @@ DriverStubImpl::DriverStubImpl(const StreamContext& context)
            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 @@ DriverStubImpl::DriverStubImpl(const StreamContext& context)
}

::android::status_t DriverStubImpl::pause() {
    LOG_ENTRY();
    if (!mIsInitialized) {
        LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
    }
@@ -68,6 +78,7 @@ DriverStubImpl::DriverStubImpl(const StreamContext& context)
}

::android::status_t DriverStubImpl::standby() {
    LOG_ENTRY();
    if (!mIsInitialized) {
        LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
    }
@@ -76,6 +87,7 @@ DriverStubImpl::DriverStubImpl(const StreamContext& context)
}

::android::status_t DriverStubImpl::start() {
    LOG_ENTRY();
    if (!mIsInitialized) {
        LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
    }
@@ -87,6 +99,7 @@ DriverStubImpl::DriverStubImpl(const StreamContext& context)

::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 @@ DriverStubImpl::DriverStubImpl(const StreamContext& context)
    }
    *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 @@ DriverStubImpl::DriverStubImpl(const StreamContext& context)
}

void DriverStubImpl::shutdown() {
    LOG_ENTRY();
    mIsInitialized = false;
}

+36 −21
Original line number Diff line number Diff line
@@ -81,11 +81,13 @@ DspSimulatorLogic::Status DspSimulatorLogic::cycle() {
}

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 @@ DriverOffloadStubImpl::DriverOffloadStubImpl(const StreamContext& context)
}

::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 @@ DriverOffloadStubImpl::DriverOffloadStubImpl(const StreamContext& context)
    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";
::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 (!mDspWorkerStarted) {
        // This is an "audio service thread," must have elevated priority.
        if (!mDspWorker.start("dsp_sim", ANDROID_PRIORITY_URGENT_AUDIO)) {
            return ::android::NO_INIT;
    if (hasClips) {
        mDspWorker.resume();
    }
        mDspWorkerStarted = true;
    return ::android::OK;
}

::android::status_t DriverOffloadStubImpl::transfer(void* buffer, size_t frameCount,
                                                    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 @@ DriverOffloadStubImpl::DriverOffloadStubImpl(const StreamContext& context)
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