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

Commit 35b81e0b authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "audio: fix mmap output" into main am: f28b8e80

parents 32cde75c f28b8e80
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <aidl/android/media/audio/common/AudioDeviceType.h>
#include <aidl/android/media/audio/common/AudioFormatDescription.h>
#include <aidl/android/media/audio/common/AudioInputFlags.h>
#include <aidl/android/media/audio/common/AudioIoFlags.h>
#include <aidl/android/media/audio/common/AudioMode.h>
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
#include <aidl/android/media/audio/common/PcmType.h>
@@ -191,4 +192,15 @@ constexpr int32_t frameCountFromDurationMs(int32_t durationMs, int32_t sampleRat
    return frameCountFromDurationUs(durationMs * 1000, sampleRateHz);
}

constexpr bool hasMmapFlag(const ::aidl::android::media::audio::common::AudioIoFlags& flags) {
    return (flags.getTag() == ::aidl::android::media::audio::common::AudioIoFlags::Tag::input &&
            isBitPositionFlagSet(
                    flags.get<::aidl::android::media::audio::common::AudioIoFlags::Tag::input>(),
                    ::aidl::android::media::audio::common::AudioInputFlags::MMAP_NOIRQ)) ||
           (flags.getTag() == ::aidl::android::media::audio::common::AudioIoFlags::Tag::output &&
            isBitPositionFlagSet(
                    flags.get<::aidl::android::media::audio::common::AudioIoFlags::Tag::output>(),
                    ::aidl::android::media::audio::common::AudioOutputFlags::MMAP_NOIRQ));
}

}  // namespace aidl::android::hardware::audio::common
+38 −28
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@

using aidl::android::hardware::audio::common::frameCountFromDurationMs;
using aidl::android::hardware::audio::common::getFrameSizeInBytes;
using aidl::android::hardware::audio::common::hasMmapFlag;
using aidl::android::hardware::audio::common::isBitPositionFlagSet;
using aidl::android::hardware::audio::common::isValidAudioMode;
using aidl::android::hardware::audio::common::SinkMetadata;
@@ -205,36 +206,32 @@ ndk::ScopedAStatus Module::createStreamContext(
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
    }
    const auto& flags = portConfigIt->flags.value();
    if ((flags.getTag() == AudioIoFlags::Tag::input &&
         !isBitPositionFlagSet(flags.get<AudioIoFlags::Tag::input>(),
                               AudioInputFlags::MMAP_NOIRQ)) ||
        (flags.getTag() == AudioIoFlags::Tag::output &&
         !isBitPositionFlagSet(flags.get<AudioIoFlags::Tag::output>(),
                               AudioOutputFlags::MMAP_NOIRQ))) {
    StreamContext::DebugParameters params{mDebug.streamTransientStateDelayMs,
                                          mVendorDebug.forceTransientBurst,
                                          mVendorDebug.forceSynchronousDrain};
    std::unique_ptr<StreamContext::DataMQ> dataMQ = nullptr;
    std::shared_ptr<IStreamCallback> streamAsyncCallback = nullptr;
    std::shared_ptr<ISoundDose> soundDose;
    if (!getSoundDose(&soundDose).isOk()) {
        LOG(ERROR) << __func__ << ": could not create sound dose instance";
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
    if (!hasMmapFlag(flags)) {
        dataMQ = std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames);
        streamAsyncCallback = asyncCallback;
    }
    StreamContext temp(
            std::make_unique<StreamContext::CommandMQ>(1, true /*configureEventFlagWord*/),
            std::make_unique<StreamContext::ReplyMQ>(1, true /*configureEventFlagWord*/),
            portConfigIt->format.value(), portConfigIt->channelMask.value(),
            portConfigIt->sampleRate.value().value, flags, nominalLatencyMs,
                portConfigIt->ext.get<AudioPortExt::mix>().handle,
                std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames),
                asyncCallback, outEventCallback, mSoundDose.getInstance(), params);
            portConfigIt->ext.get<AudioPortExt::mix>().handle, std::move(dataMQ),
            streamAsyncCallback, outEventCallback, mSoundDose.getInstance(), params);
    if (temp.isValid()) {
        *out_context = std::move(temp);
    } else {
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
    } else {
        // TODO: Implement simulation of MMAP buffer allocation
    }
    return ndk::ScopedAStatus::ok();
}

@@ -373,6 +370,13 @@ int32_t Module::getNominalLatencyMs(const AudioPortConfig&) {
    return kLatencyMs;
}

ndk::ScopedAStatus Module::createMmapBuffer(
        const ::aidl::android::hardware::audio::core::StreamContext& context __unused,
        ::aidl::android::hardware::audio::core::StreamDescriptor* desc __unused) {
    LOG(ERROR) << __func__ << ": " << mType << ": is not implemented";
    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}

std::vector<AudioRoute*> Module::getAudioRoutesForAudioPortImpl(int32_t portId) {
    std::vector<AudioRoute*> result;
    auto& routes = getConfig().routes;
@@ -866,6 +870,9 @@ ndk::ScopedAStatus Module::openInputStream(const OpenInputStreamArguments& in_ar
    RETURN_STATUS_IF_ERROR(createStreamContext(in_args.portConfigId, in_args.bufferSizeFrames,
                                               nullptr, nullptr, &context));
    context.fillDescriptor(&_aidl_return->desc);
    if (hasMmapFlag(context.getFlags())) {
        RETURN_STATUS_IF_ERROR(createMmapBuffer(context, &_aidl_return->desc));
    }
    std::shared_ptr<StreamIn> stream;
    RETURN_STATUS_IF_ERROR(createInputStream(std::move(context), in_args.sinkMetadata,
                                             getMicrophoneInfos(), &stream));
@@ -913,6 +920,9 @@ ndk::ScopedAStatus Module::openOutputStream(const OpenOutputStreamArguments& in_
                                               isNonBlocking ? in_args.callback : nullptr,
                                               in_args.eventCallback, &context));
    context.fillDescriptor(&_aidl_return->desc);
    if (hasMmapFlag(context.getFlags())) {
        RETURN_STATUS_IF_ERROR(createMmapBuffer(context, &_aidl_return->desc));
    }
    std::shared_ptr<StreamOut> stream;
    RETURN_STATUS_IF_ERROR(createOutputStream(std::move(context), in_args.sourceMetadata,
                                              in_args.offloadInfo, &stream));
+36 −18
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
using aidl::android::hardware::audio::common::AudioOffloadMetadata;
using aidl::android::hardware::audio::common::getChannelCount;
using aidl::android::hardware::audio::common::getFrameSizeInBytes;
using aidl::android::hardware::audio::common::hasMmapFlag;
using aidl::android::hardware::audio::common::isBitPositionFlagSet;
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
@@ -84,7 +85,7 @@ bool StreamContext::isValid() const {
        LOG(ERROR) << "frame size is invalid";
        return false;
    }
    if (mDataMQ && !mDataMQ->isValid()) {
    if (!hasMmapFlag(mFlags) && mDataMQ && !mDataMQ->isValid()) {
        LOG(ERROR) << "data FMQ is invalid";
        return false;
    }
@@ -116,6 +117,7 @@ pid_t StreamWorkerCommonLogic::getTid() const {
std::string StreamWorkerCommonLogic::init() {
    if (mContext->getCommandMQ() == nullptr) return "Command MQ is null";
    if (mContext->getReplyMQ() == nullptr) return "Reply MQ is null";
    if (!hasMmapFlag(mContext->getFlags())) {
        StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
        if (dataMQ == nullptr) return "Data MQ is null";
        if (sizeof(DataBufferElement) != dataMQ->getQuantumSize()) {
@@ -128,6 +130,7 @@ std::string StreamWorkerCommonLogic::init() {
                   std::to_string(dataMQ->getQuantumCount()) +
                   ", size in bytes: " + std::to_string(mDataBufferSize);
        }
    }
    if (::android::status_t status = mDriver->init(); status != STATUS_OK) {
        return "Failed to initialize the driver: " + std::to_string(status);
    }
@@ -136,16 +139,26 @@ std::string StreamWorkerCommonLogic::init() {

void StreamWorkerCommonLogic::populateReply(StreamDescriptor::Reply* reply,
                                            bool isConnected) const {
    static const StreamDescriptor::Position kUnknownPosition = {
            .frames = StreamDescriptor::Position::UNKNOWN,
            .timeNs = StreamDescriptor::Position::UNKNOWN};
    reply->status = STATUS_OK;
    if (isConnected) {
        reply->observable.frames = mContext->getFrameCount();
        reply->observable.timeNs = ::android::uptimeNanos();
        if (auto status = mDriver->refinePosition(&reply->observable); status == ::android::OK) {
            return;
        if (auto status = mDriver->refinePosition(&reply->observable); status != ::android::OK) {
            reply->observable = kUnknownPosition;
        }
    } else {
        reply->observable = reply->hardware = kUnknownPosition;
    }
    if (hasMmapFlag(mContext->getFlags())) {
        if (auto status = mDriver->getMmapPositionAndLatency(&reply->hardware, &reply->latencyMs);
            status != ::android::OK) {
            reply->hardware = kUnknownPosition;
            reply->latencyMs = StreamDescriptor::LATENCY_UNKNOWN;
        }
    }
    reply->observable.frames = StreamDescriptor::Position::UNKNOWN;
    reply->observable.timeNs = StreamDescriptor::Position::UNKNOWN;
}

void StreamWorkerCommonLogic::populateReplyWrongState(
@@ -224,7 +237,9 @@ StreamInWorkerLogic::Status StreamInWorkerLogic::cycle() {
                    mState == StreamDescriptor::State::ACTIVE ||
                    mState == StreamDescriptor::State::PAUSED ||
                    mState == StreamDescriptor::State::DRAINING) {
                    if (!read(fmqByteCount, &reply)) {
                    if (hasMmapFlag(mContext->getFlags())) {
                        populateReply(&reply, mIsConnected);
                    } else if (!read(fmqByteCount, &reply)) {
                        mState = StreamDescriptor::State::ERROR;
                    }
                    if (mState == StreamDescriptor::State::IDLE ||
@@ -470,7 +485,9 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
                if (mState != StreamDescriptor::State::ERROR &&
                    mState != StreamDescriptor::State::TRANSFERRING &&
                    mState != StreamDescriptor::State::TRANSFER_PAUSED) {
                    if (!write(fmqByteCount, &reply)) {
                    if (hasMmapFlag(mContext->getFlags())) {
                        populateReply(&reply, mIsConnected);
                    } else if (!write(fmqByteCount, &reply)) {
                        mState = StreamDescriptor::State::ERROR;
                    }
                    std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
@@ -657,6 +674,7 @@ ndk::ScopedAStatus StreamCommonImpl::initInstance(
        const std::shared_ptr<StreamCommonInterface>& delegate) {
    mCommon = ndk::SharedRefBase::make<StreamCommonDelegator>(delegate);
    if (!mWorker->start()) {
        LOG(ERROR) << __func__ << ": Worker start error: " << mWorker->getError();
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
    if (auto flags = getContext().getFlags();
+3 −0
Original line number Diff line number Diff line
@@ -205,6 +205,9 @@ class Module : public BnModule {
    virtual std::unique_ptr<Configuration> initializeConfig();
    virtual int32_t getNominalLatencyMs(
            const ::aidl::android::media::audio::common::AudioPortConfig& portConfig);
    virtual ndk::ScopedAStatus createMmapBuffer(
            const ::aidl::android::hardware::audio::core::StreamContext& context,
            ::aidl::android::hardware::audio::core::StreamDescriptor* desc);

    // Utility and helper functions accessible to subclasses.
    static int32_t calculateBufferSizeFrames(int32_t latencyMs, int32_t sampleRateHz) {
+7 −0
Original line number Diff line number Diff line
@@ -177,6 +177,11 @@ struct DriverInterface {
    virtual ::android::status_t refinePosition(StreamDescriptor::Position* /*position*/) {
        return ::android::OK;
    }
    // Implement 'getMmapPositionAndLatency' is necessary if driver can support mmap stream.
    virtual ::android::status_t getMmapPositionAndLatency(StreamDescriptor::Position* /*position*/,
                                                          int32_t* /*latency*/) {
        return ::android::OK;
    }
    virtual void shutdown() = 0;  // This function is only called once.
};

@@ -241,6 +246,7 @@ struct StreamWorkerInterface {
    virtual bool start() = 0;
    virtual pid_t getTid() = 0;
    virtual void stop() = 0;
    virtual std::string getError() = 0;
};

template <class WorkerLogic>
@@ -260,6 +266,7 @@ class StreamWorkerImpl : public StreamWorkerInterface,
    }
    pid_t getTid() override { return WorkerImpl::getTid(); }
    void stop() override { return WorkerImpl::stop(); }
    std::string getError() override { return WorkerImpl::getError(); }
};

class StreamInWorkerLogic : public StreamWorkerCommonLogic {
Loading