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

Commit 712d71b2 authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

libaudiohal: Handle pause-flush-resume for offloaded streams

Update StreamHalAidl to support pause-flush-resume sequence.
This is implemented by moving the asynchronous output stream
from IDLE back to ACTIVE state by issuing 'burst' command
(see stream-out-async-sm.gv).

Bug: 270552159
Test: atest CtsMediaAudioTestCases:VolumeShaperTest
Change-Id: I810fe817ef648567c30a161f1762343c9bca990b
parent f5839887
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -460,7 +460,7 @@ status_t DeviceHalAidl::openOutputStream(
    args.eventCallback = eventCb;
    args.eventCallback = eventCb;
    ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
    ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
    StreamContextAidl context(ret.desc);
    StreamContextAidl context(ret.desc, isOffload);
    if (!context.isValid()) {
    if (!context.isValid()) {
        ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
        ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
                __func__, ret.desc.toString().c_str());
                __func__, ret.desc.toString().c_str());
@@ -520,7 +520,7 @@ status_t DeviceHalAidl::openInputStream(
    args.bufferSizeFrames = aidlConfig.frameCount;
    args.bufferSizeFrames = aidlConfig.frameCount;
    ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
    ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
    StreamContextAidl context(ret.desc);
    StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
    if (!context.isValid()) {
    if (!context.isValid()) {
        ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
        ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
                __func__, ret.desc.toString().c_str());
                __func__, ret.desc.toString().c_str());
+24 −0
Original line number Original line Diff line number Diff line
@@ -323,6 +323,26 @@ status_t StreamHalAidl::resume(StreamDescriptor::Reply* reply) {
    if (mIsInput) {
    if (mIsInput) {
        return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), reply);
        return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), reply);
    } else {
    } else {
        if (mContext.isAsynchronous()) {
            // Handle pause-flush-resume sequence. 'flush' from PAUSED goes to
            // IDLE. We move here from IDLE to ACTIVE (same as 'start' from PAUSED).
            const auto state = getState();
            if (state == StreamDescriptor::State::IDLE) {
                StreamDescriptor::Reply localReply{};
                StreamDescriptor::Reply* innerReply = reply ?: &localReply;
                if (status_t status =
                        sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), innerReply);
                        status != OK) {
                    return status;
                }
                if (innerReply->state != StreamDescriptor::State::ACTIVE) {
                    ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
                            __func__, toString(innerReply->state).c_str());
                    return INVALID_OPERATION;
                }
                return OK;
            }
        }
        return sendCommand(makeHalCommand<HalCommand::Tag::start>(), reply);
        return sendCommand(makeHalCommand<HalCommand::Tag::start>(), reply);
    }
    }
}
}
@@ -514,6 +534,10 @@ status_t StreamOutHalAidl::getNextWriteTimestamp(int64_t *timestamp __unused) {
status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
    TIME_CHECK();
    TIME_CHECK();
    if (!mStream) return NO_INIT;
    if (!mStream) return NO_INIT;
    if (!mContext.isAsynchronous()) {
        ALOGE("%s: the callback is intended for asynchronous streams only", __func__);
        return INVALID_OPERATION;
    }
    if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
    if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
        if (auto cb = callback.promote(); cb != nullptr) {
        if (auto cb = callback.promote(); cb != nullptr) {
            broker->setStreamOutCallback(this, cb);
            broker->setStreamOutCallback(this, cb);
+9 −3
Original line number Original line Diff line number Diff line
@@ -43,24 +43,28 @@ class StreamContextAidl {
            ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;
            ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;


    explicit StreamContextAidl(
    explicit StreamContextAidl(
            const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor)
            const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
            bool isAsynchronous)
        : mFrameSizeBytes(descriptor.frameSizeBytes),
        : mFrameSizeBytes(descriptor.frameSizeBytes),
          mCommandMQ(new CommandMQ(descriptor.command)),
          mCommandMQ(new CommandMQ(descriptor.command)),
          mReplyMQ(new ReplyMQ(descriptor.reply)),
          mReplyMQ(new ReplyMQ(descriptor.reply)),
          mBufferSizeFrames(descriptor.bufferSizeFrames),
          mBufferSizeFrames(descriptor.bufferSizeFrames),
          mDataMQ(maybeCreateDataMQ(descriptor)) {}
          mDataMQ(maybeCreateDataMQ(descriptor)),
          mIsAsynchronous(isAsynchronous) {}
    StreamContextAidl(StreamContextAidl&& other) :
    StreamContextAidl(StreamContextAidl&& other) :
            mFrameSizeBytes(other.mFrameSizeBytes),
            mFrameSizeBytes(other.mFrameSizeBytes),
            mCommandMQ(std::move(other.mCommandMQ)),
            mCommandMQ(std::move(other.mCommandMQ)),
            mReplyMQ(std::move(other.mReplyMQ)),
            mReplyMQ(std::move(other.mReplyMQ)),
            mBufferSizeFrames(other.mBufferSizeFrames),
            mBufferSizeFrames(other.mBufferSizeFrames),
            mDataMQ(std::move(other.mDataMQ)) {}
            mDataMQ(std::move(other.mDataMQ)),
            mIsAsynchronous(other.mIsAsynchronous) {}
    StreamContextAidl& operator=(StreamContextAidl&& other) {
    StreamContextAidl& operator=(StreamContextAidl&& other) {
        mFrameSizeBytes = other.mFrameSizeBytes;
        mFrameSizeBytes = other.mFrameSizeBytes;
        mCommandMQ = std::move(other.mCommandMQ);
        mCommandMQ = std::move(other.mCommandMQ);
        mReplyMQ = std::move(other.mReplyMQ);
        mReplyMQ = std::move(other.mReplyMQ);
        mBufferSizeFrames = other.mBufferSizeFrames;
        mBufferSizeFrames = other.mBufferSizeFrames;
        mDataMQ = std::move(other.mDataMQ);
        mDataMQ = std::move(other.mDataMQ);
        mIsAsynchronous = other.mIsAsynchronous;
        return *this;
        return *this;
    }
    }
    bool isValid() const {
    bool isValid() const {
@@ -78,6 +82,7 @@ class StreamContextAidl {
    DataMQ* getDataMQ() const { return mDataMQ.get(); }
    DataMQ* getDataMQ() const { return mDataMQ.get(); }
    size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
    size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
    ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
    ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
    bool isAsynchronous() const { return mIsAsynchronous; }


  private:
  private:
    static std::unique_ptr<DataMQ> maybeCreateDataMQ(
    static std::unique_ptr<DataMQ> maybeCreateDataMQ(
@@ -94,6 +99,7 @@ class StreamContextAidl {
    std::unique_ptr<ReplyMQ> mReplyMQ;
    std::unique_ptr<ReplyMQ> mReplyMQ;
    size_t mBufferSizeFrames;
    size_t mBufferSizeFrames;
    std::unique_ptr<DataMQ> mDataMQ;
    std::unique_ptr<DataMQ> mDataMQ;
    bool mIsAsynchronous;
};
};


class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelperAidl {
class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelperAidl {