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

Commit 5137adf4 authored by Mikhail Naganov's avatar Mikhail Naganov Committed by Android (Google) Code Review
Browse files

Merge "libaudiohal@aidl: Fix callbacks handling" into 24D1-dev

parents 35707086 8065bfd2
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -478,15 +478,21 @@ status_t DeviceHalAidl::openOutputStream(
                __func__, ret.desc.toString().c_str());
        return NO_INIT;
    }
    *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
    auto stream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
            std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
    void* cbCookie = (*outStream).get();
    *outStream = stream;
    /* StreamOutHalInterface* */ void* cbCookie = (*outStream).get();
    {
        std::lock_guard l(mLock);
        mCallbacks.emplace(cbCookie, Callbacks{});
        mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
    }
    if (streamCb) streamCb->setCookie(cbCookie);
    if (streamCb) {
        streamCb->setCookie(cbCookie);
        // Although StreamOutHalAidl implements StreamOutHalInterfaceCallback,
        // we always go via the CallbackBroker for consistency.
        setStreamOutCallback(cbCookie, stream);
    }
    eventCb->setCookie(cbCookie);
    cleanups.disarmAll();
    return OK;
+77 −23
Original line number Diff line number Diff line
@@ -82,7 +82,12 @@ StreamHalAidl::StreamHalAidl(
          mConfig(configToBase(config)),
          mContext(std::move(context)),
          mStream(stream),
          mVendorExt(vext) {
          mVendorExt(vext),
          mLastReplyLifeTimeNs(
                  std::min(static_cast<size_t>(100),
                          2 * mContext.getBufferDurationMs(mConfig.sample_rate))
                  * NANOS_PER_MILLISECOND)
{
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    {
        std::lock_guard l(mLock);
@@ -285,8 +290,7 @@ status_t StreamHalAidl::getHardwarePosition(int64_t *frames, int64_t *timestamp)
    ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
    if (!mStream) return NO_INIT;
    StreamDescriptor::Reply reply;
    // TODO: switch to updateCountersIfNeeded once we sort out mWorkerTid initialization
    RETURN_STATUS_IF_ERROR(sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), &reply, true));
    RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
    *frames = std::max<int64_t>(0, reply.hardware.frames);
    *timestamp = std::max<int64_t>(0, reply.hardware.timeNs);
    return OK;
@@ -409,6 +413,37 @@ status_t StreamHalAidl::exit() {
    return statusTFromBinderStatus(mStream->prepareToClose());
}

void StreamHalAidl::onAsyncTransferReady() {
    if (auto state = getState(); state == StreamDescriptor::State::TRANSFERRING) {
        // Retrieve the current state together with position counters.
        updateCountersIfNeeded();
    } else {
        ALOGW("%s: unexpected onTransferReady in the state %s", __func__, toString(state).c_str());
    }
}

void StreamHalAidl::onAsyncDrainReady() {
    if (auto state = getState(); state == StreamDescriptor::State::DRAINING) {
        // Retrieve the current state together with position counters.
        updateCountersIfNeeded();
    } else {
        ALOGW("%s: unexpected onDrainReady in the state %s", __func__, toString(state).c_str());
    }
}

void StreamHalAidl::onAsyncError() {
    std::lock_guard l(mLock);
    if (mLastReply.state == StreamDescriptor::State::IDLE ||
        mLastReply.state == StreamDescriptor::State::DRAINING ||
        mLastReply.state == StreamDescriptor::State::TRANSFERRING) {
        mLastReply.state = StreamDescriptor::State::ERROR;
        ALOGW("%s: onError received", __func__);
    } else {
        ALOGW("%s: unexpected onError in the state %s", __func__,
                toString(mLastReply.state).c_str());
    }
}

status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
                                         struct audio_mmap_buffer_info *info) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
@@ -487,6 +522,7 @@ status_t StreamHalAidl::sendCommand(
            reply->latencyMs = mLastReply.latencyMs;
        }
        mLastReply = *reply;
        mLastReplyExpirationNs = uptimeNanos() + mLastReplyLifeTimeNs;
    }
    switch (reply->status) {
        case STATUS_OK: return OK;
@@ -502,14 +538,17 @@ status_t StreamHalAidl::sendCommand(

status_t StreamHalAidl::updateCountersIfNeeded(
        ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply) {
    if (mWorkerTid.load(std::memory_order_acquire) == gettid()) {
        if (const auto state = getState(); state != StreamDescriptor::State::ACTIVE &&
                state != StreamDescriptor::State::DRAINING &&
                state != StreamDescriptor::State::TRANSFERRING) {
            return sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), reply);
        }
    }
    if (reply != nullptr) {
    bool doUpdate = false;
    {
        std::lock_guard l(mLock);
        doUpdate = uptimeNanos() > mLastReplyExpirationNs;
    }
    if (doUpdate) {
        // Since updates are paced, it is OK to perform them from any thread, they should
        // not interfere with I/O operations of the worker.
        return sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(),
                reply, true /*safeFromNonWorkerThread */);
    } else if (reply != nullptr) {  // provide cached reply
        std::lock_guard l(mLock);
        *reply = mLastReply;
    }
@@ -545,7 +584,7 @@ StreamOutHalAidl::StreamOutHalAidl(

StreamOutHalAidl::~StreamOutHalAidl() {
    if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
        broker->clearCallbacks(this);
        broker->clearCallbacks(static_cast<StreamOutHalInterface*>(this));
    }
}

@@ -602,21 +641,14 @@ status_t StreamOutHalAidl::getNextWriteTimestamp(int64_t *timestamp __unused) {
}

status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
    ALOGD("%p %s", this, __func__);
    TIME_CHECK();
    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 cb = callback.promote(); cb != nullptr) {
            broker->setStreamOutCallback(this, cb);
        } else {
            // It is expected that the framework never passes a null pointer.
            // In the AIDL model callbacks can't be "unregistered".
            LOG_ALWAYS_FATAL("%s: received an expired or null callback pointer", __func__);
        }
    }
    mClientCallback = callback;
    return OK;
}

@@ -739,7 +771,7 @@ status_t StreamOutHalAidl::setEventCallback(
    TIME_CHECK();
    if (!mStream) return NO_INIT;
    if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
        broker->setStreamOutEventCallback(this, callback);
        broker->setStreamOutEventCallback(static_cast<StreamOutHalInterface*>(this), callback);
    }
    return OK;
}
@@ -773,7 +805,8 @@ status_t StreamOutHalAidl::setLatencyModeCallback(
    TIME_CHECK();
    if (!mStream) return NO_INIT;
    if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
        broker->setStreamOutLatencyModeCallback(this, callback);
        broker->setStreamOutLatencyModeCallback(
                static_cast<StreamOutHalInterface*>(this), callback);
    }
    return OK;
};
@@ -782,6 +815,27 @@ status_t StreamOutHalAidl::exit() {
    return StreamHalAidl::exit();
}

void StreamOutHalAidl::onWriteReady() {
    onAsyncTransferReady();
    if (auto clientCb = mClientCallback.load().promote(); clientCb != nullptr) {
        clientCb->onWriteReady();
    }
}

void StreamOutHalAidl::onDrainReady() {
    onAsyncDrainReady();
    if (auto clientCb = mClientCallback.load().promote(); clientCb != nullptr) {
        clientCb->onDrainReady();
    }
}

void StreamOutHalAidl::onError() {
    onAsyncError();
    if (auto clientCb = mClientCallback.load().promote(); clientCb != nullptr) {
        clientCb->onError();
    }
}

status_t StreamOutHalAidl::filterAndUpdateOffloadMetadata(AudioParameter &parameters) {
    TIME_CHECK();
    bool updateMetadata = false;
+19 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <media/audiohal/StreamHalInterface.h>
#include <media/AidlConversionUtil.h>
#include <media/AudioParameter.h>
#include <mediautils/Synchronization.h>

#include "ConversionHelperAidl.h"
#include "StreamPowerLog.h"
@@ -93,6 +94,9 @@ class StreamContextAidl {
    }
    size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; }
    size_t getBufferSizeFrames() const { return mBufferSizeFrames; }
    size_t getBufferDurationMs(int32_t sampleRate) const {
        return sampleRate != 0 ? mBufferSizeFrames * MILLIS_PER_SECOND / sampleRate : 0;
    }
    CommandMQ* getCommandMQ() const { return mCommandMQ.get(); }
    DataMQ* getDataMQ() const { return mDataMQ.get(); }
    size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
@@ -232,6 +236,10 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper

    status_t exit();

    void onAsyncTransferReady();
    void onAsyncDrainReady();
    void onAsyncError();

    const bool mIsInput;
    const audio_config_base_t mConfig;
    const StreamContextAidl mContext;
@@ -257,8 +265,10 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper

    const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> mStream;
    const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt;
    const int64_t mLastReplyLifeTimeNs;
    std::mutex mLock;
    ::aidl::android::hardware::audio::core::StreamDescriptor::Reply mLastReply GUARDED_BY(mLock);
    int64_t mLastReplyExpirationNs GUARDED_BY(mLock) = 0;
    // mStreamPowerLog is used for audio signal power logging.
    StreamPowerLog mStreamPowerLog;
    std::atomic<pid_t> mWorkerTid = -1;
@@ -266,7 +276,9 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper

class CallbackBroker;

class StreamOutHalAidl : public StreamOutHalInterface, public StreamHalAidl {
class StreamOutHalAidl : public virtual StreamOutHalInterface,
                         public virtual StreamOutHalInterfaceCallback,
                         public StreamHalAidl {
  public:
    // Extract the output stream parameters and set by AIDL APIs.
    status_t setParameters(const String8& kvPairs) override;
@@ -344,6 +356,11 @@ class StreamOutHalAidl : public StreamOutHalInterface, public StreamHalAidl {

    status_t exit() override;

    // StreamOutHalInterfaceCallback
    void onWriteReady() override;
    void onDrainReady() override;
    void onError() override;

  private:
    friend class sp<StreamOutHalAidl>;

@@ -352,6 +369,7 @@ class StreamOutHalAidl : public StreamOutHalInterface, public StreamHalAidl {

    const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut> mStream;
    const wp<CallbackBroker> mCallbackBroker;
    mediautils::atomic_wp<StreamOutHalInterfaceCallback> mClientCallback;

    AudioOffloadMetadata mOffloadMetadata;