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

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

audiohal: Pass thread identifiers to the client for priority adjustment

HALs are prohibited from using framework binder, and there is
no equivalent scheduling policy service in hwbinder. Thus, in order
to match priorities of FastCapture / Mixer threads with their
counterparts in the HAL, it is needed to request the priority boost
from audioflinger on behalf of the HAL.

Bug: 34131400
Change-Id: I7c8db9d520b4cf272d2896ad875752b109b57ab7
Test: check priority match between audioflinger's and hal's threads
parent db4d6813
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -91,7 +91,11 @@ interface IStreamIn extends IStream {
     *     to the client;
     *  -- status queue is used for reporting operation status
     *     (e.g. amount of bytes actually read or error code).
     * The driver operates on a dedicated thread.
     *
     * The driver operates on a dedicated thread. The client must ensure that
     * the thread is given an appropriate priority and assigned to correct
     * scheduler and cgroup. For this purpose, the method returns identifiers
     * of the driver thread.
     *
     * @param frameSize the size of a single frame, in bytes.
     * @param framesCount the number of frames in a buffer.
@@ -105,15 +109,15 @@ interface IStreamIn extends IStream {
     *                specified at the stream opening.
     * @return statusMQ a message queue used for passing status from the driver
     *                  using ReadStatus structures.
     * @return threadInfo identifiers of the driver's dedicated thread.
     */
    prepareForReading(
            uint32_t frameSize, uint32_t framesCount,
            ThreadPriority threadPriority)
    prepareForReading(uint32_t frameSize, uint32_t framesCount)
    generates (
            Result retval,
            fmq_sync<ReadParameters> commandMQ,
            fmq_sync<uint8_t> dataMQ,
            fmq_sync<ReadStatus> statusMQ);
            fmq_sync<ReadStatus> statusMQ,
            ThreadInfo threadInfo);

    /*
     * Return the amount of input frames lost in the audio driver since the last
+9 −6
Original line number Diff line number Diff line
@@ -85,11 +85,14 @@ interface IStreamOut extends IStream {
     *     to the driver;
     *  -- status queue is used for reporting operation status
     *     (e.g. amount of bytes actually written or error code).
     * The driver operates on a dedicated thread.
     *
     * The driver operates on a dedicated thread. The client must ensure that
     * the thread is given an appropriate priority and assigned to correct
     * scheduler and cgroup. For this purpose, the method returns identifiers
     * of the driver thread.
     *
     * @param frameSize the size of a single frame, in bytes.
     * @param framesCount the number of frames in a buffer.
     * @param threadPriority priority of the driver thread.
     * @return retval OK if both message queues were created successfully.
     *                INVALID_STATE if the method was already called.
     *                INVALID_ARGUMENTS if there was a problem setting up
@@ -99,15 +102,15 @@ interface IStreamOut extends IStream {
     *                specified at the stream opening.
     * @return statusMQ a message queue used for passing status from the driver
     *                  using WriteStatus structures.
     * @return threadInfo identifiers of the driver's dedicated thread.
     */
    prepareForWriting(
            uint32_t frameSize, uint32_t framesCount,
            ThreadPriority threadPriority)
    prepareForWriting(uint32_t frameSize, uint32_t framesCount)
    generates (
            Result retval,
            fmq_sync<WriteCommand> commandMQ,
            fmq_sync<uint8_t> dataMQ,
            fmq_sync<WriteStatus> statusMQ);
            fmq_sync<WriteStatus> statusMQ,
            ThreadInfo threadInfo);

    /*
     * Return the number of audio frames written by the audio DSP to DAC since
+0 −1
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@ LOCAL_SHARED_LIBRARIES := \
    libhidltransport \
    libhwbinder \
    liblog \
    libmediautils \
    libutils \
    android.hardware.audio@2.0 \
    android.hardware.audio.common@2.0 \
+15 −26
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@

#include <android/log.h>
#include <hardware/audio.h>
#include <mediautils/SchedulingPolicyService.h>
#include <utils/Trace.h>

#include "StreamIn.h"
@@ -33,6 +32,8 @@ namespace audio {
namespace V2_0 {
namespace implementation {

using ::android::hardware::audio::common::V2_0::ThreadInfo;

namespace {

class ReadThread : public Thread {
@@ -43,8 +44,7 @@ class ReadThread : public Thread {
            StreamIn::CommandMQ* commandMQ,
            StreamIn::DataMQ* dataMQ,
            StreamIn::StatusMQ* statusMQ,
            EventFlag* efGroup,
            ThreadPriority threadPriority)
            EventFlag* efGroup)
            : Thread(false /*canCallJava*/),
              mStop(stop),
              mStream(stream),
@@ -52,13 +52,10 @@ class ReadThread : public Thread {
              mDataMQ(dataMQ),
              mStatusMQ(statusMQ),
              mEfGroup(efGroup),
              mThreadPriority(threadPriority),
              mBuffer(new uint8_t[dataMQ->getQuantumCount()]) {
    }
    virtual ~ReadThread() {}

    status_t readyToRun() override;

  private:
    std::atomic<bool>* mStop;
    audio_stream_in_t* mStream;
@@ -66,7 +63,6 @@ class ReadThread : public Thread {
    StreamIn::DataMQ* mDataMQ;
    StreamIn::StatusMQ* mStatusMQ;
    EventFlag* mEfGroup;
    ThreadPriority mThreadPriority;
    std::unique_ptr<uint8_t[]> mBuffer;
    IStreamIn::ReadParameters mParameters;
    IStreamIn::ReadStatus mStatus;
@@ -77,16 +73,6 @@ class ReadThread : public Thread {
    void doRead();
};

status_t ReadThread::readyToRun() {
    if (mThreadPriority != ThreadPriority::NORMAL) {
        int err = requestPriority(
                getpid(), getTid(), static_cast<int>(mThreadPriority), true /*asynchronous*/);
        ALOGW_IF(err, "failed to set priority %d for pid %d tid %d; error %d",
                static_cast<int>(mThreadPriority), getpid(), getTid(), err);
    }
    return OK;
}

void ReadThread::doRead() {
    size_t availableToWrite = mDataMQ->availableToWrite();
    size_t requestedToRead = mParameters.params.read;
@@ -313,14 +299,14 @@ Return<Result> StreamIn::setGain(float gain) {
}

Return<void> StreamIn::prepareForReading(
        uint32_t frameSize, uint32_t framesCount, ThreadPriority threadPriority,
        prepareForReading_cb _hidl_cb)  {
        uint32_t frameSize, uint32_t framesCount, prepareForReading_cb _hidl_cb)  {
    status_t status;
    ThreadInfo threadInfo = { 0, 0 };
    // Create message queues.
    if (mDataMQ) {
        ALOGE("the client attempts to call prepareForReading twice");
        _hidl_cb(Result::INVALID_STATE,
                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor());
                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
        return Void();
    }
    std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1));
@@ -332,7 +318,7 @@ Return<void> StreamIn::prepareForReading(
        ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
        ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
        _hidl_cb(Result::INVALID_ARGUMENTS,
                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor());
                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
        return Void();
    }
    // TODO: Remove event flag management once blocking MQ is implemented. b/33815422
@@ -340,7 +326,7 @@ Return<void> StreamIn::prepareForReading(
    if (status != OK || !mEfGroup) {
        ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
        _hidl_cb(Result::INVALID_ARGUMENTS,
                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor());
                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
        return Void();
    }

@@ -351,20 +337,23 @@ Return<void> StreamIn::prepareForReading(
            tempCommandMQ.get(),
            tempDataMQ.get(),
            tempStatusMQ.get(),
            mEfGroup,
            threadPriority);
            mEfGroup);
    status = mReadThread->run("reader", PRIORITY_URGENT_AUDIO);
    if (status != OK) {
        ALOGW("failed to start reader thread: %s", strerror(-status));
        _hidl_cb(Result::INVALID_ARGUMENTS,
                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor());
                CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
        return Void();
    }

    mCommandMQ = std::move(tempCommandMQ);
    mDataMQ = std::move(tempDataMQ);
    mStatusMQ = std::move(tempStatusMQ);
    _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc());
    threadInfo.pid = getpid();
    threadInfo.tid = mReadThread->getTid();
    _hidl_cb(Result::OK,
            *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(),
            threadInfo);
    return Void();
}

+1 −3
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@ using ::android::hardware::audio::V2_0::IStream;
using ::android::hardware::audio::V2_0::IStreamIn;
using ::android::hardware::audio::V2_0::ParameterValue;
using ::android::hardware::audio::V2_0::Result;
using ::android::hardware::audio::V2_0::ThreadPriority;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
@@ -89,8 +88,7 @@ struct StreamIn : public IStreamIn {
    Return<void> getAudioSource(getAudioSource_cb _hidl_cb)  override;
    Return<Result> setGain(float gain)  override;
    Return<void> prepareForReading(
            uint32_t frameSize, uint32_t framesCount, ThreadPriority threadPriority,
            prepareForReading_cb _hidl_cb)  override;
            uint32_t frameSize, uint32_t framesCount, prepareForReading_cb _hidl_cb)  override;
    Return<uint32_t> getInputFramesLost()  override;
    Return<void> getCapturePosition(getCapturePosition_cb _hidl_cb)  override;
    Return<Result> start() override;
Loading