[audio] threadLoop_write 到 audio-hal 分析

接上文

https://blog.csdn.net/we1less/article/details/156491150?spm=1001.2014.3001.5502
https://blog.csdn.net/we1less/article/details/156506593?spm=1001.2014.3001.5502


audioflinger

av/services/audioflinger/Threads.cpp threadLoop_write

AudioMixerBasemSinkBuffer 填充, mNormalSink 将数据写入到 hal 中

cpp 复制代码
ssize_t PlaybackThread::threadLoop_write()
{
 
    ssize_t bytesWritten;
 
    const size_t offset = mCurrentWriteLength - mBytesRemaining;
 
 
    if (mNormalSink != 0) {
 
        const size_t count = mBytesRemaining / mFrameSize;
 
 
        ssize_t framesWritten = mNormalSink->write((char *)mSinkBuffer + offset, count);
 
 
    }
    return bytesWritten;
}

看下这个 mNormalSink 是从哪来的

av/services/audioflinger/Threads.cpp mNormalSink

可以看出 mNormalSink 是由 构造 AudioStreamOutSink 赋值而来

cpp 复制代码
/* static */
sp<IAfPlaybackThread> IAfPlaybackThread::createMixerThread(
        const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
        audio_io_handle_t id, bool systemReady, type_t type, audio_config_base_t* mixerConfig) {
    return sp<MixerThread>::make(afThreadCallback, output, id, systemReady, type, mixerConfig);
}
 
MixerThread::MixerThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
        audio_io_handle_t id, bool systemReady, type_t type, audio_config_base_t *mixerConfig)
    :   PlaybackThread(afThreadCallback, output, id, type, systemReady, mixerConfig),
        // mOutputSink below
        // mPipeSink below
        // mNormalSink below
{
    mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
 
    mOutputSink = new AudioStreamOutSink(output->stream);
 
    mNormalSink = mOutputSink;
 
}

av/media/libnbaio/AudioStreamOutSink.cpp write

上文已经得知,在 AudioStreamOutSink 的构造器中保存了output->streammStream 后续的 write 数据就是用 mStream

上文可得知,mStream 是由 AudioStreamOut 构造而来

cpp 复制代码
AudioStreamOutSink::AudioStreamOutSink(sp<StreamOutHalInterface> stream) :
        NBAIO_Sink(),
        mStream(stream),
        mStreamBufferSizeBytes(0)
{
    ALOG_ASSERT(stream != 0);
}

ssize_t AudioStreamOutSink::write(const void *buffer, size_t count)
{

    size_t written;

    status_t ret = mStream->write(buffer, count * mFrameSize, &written);

    auto processor = mMelProcessor.load();

    processor->process(buffer, written);

    written /= mFrameSize;

    mFramesWritten += written;

    return written;
}

av/services/audioflinger/datapath/AudioStreamOut.cpp write

上文可得知,这里的 streamStreamOutHalHidl

cpp 复制代码
ssize_t AudioStreamOut::write(const void *buffer, size_t numBytes)
{
    size_t bytesWritten;

    const status_t result = stream->write(buffer, numBytes, &bytesWritten);

    if (result == OK && bytesWritten > 0 && mHalFrameSize > 0) {
        mFramesWritten += bytesWritten / mHalFrameSize;
    }

    return result == OK ? bytesWritten : result;
}

av/media/libaudiohal/impl/StreamHalHidl.cpp StreamOutHalHidl::write

cpp 复制代码
status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
    status_t status;

    if (!mDataMQ) {

        size_t bufferSize;

        if ((status = getCachedBufferSize(&bufferSize)) != OK) {

            return status;
        }

        if (bytes > bufferSize) bufferSize = bytes;

        if ((status = prepareForWriting(bufferSize)) != OK) {

            return status;
        }
    }

    status = callWriterThread(
            WriteCommand::WRITE, "write", static_cast<const uint8_t*>(buffer), bytes,
            [&] (const WriteStatus& writeStatus) {

                *written = writeStatus.reply.written;

            });
    
    return status;
}


status_t StreamOutHalHidl::callWriterThread(
        WriteCommand cmd, const char* cmdName,
        const uint8_t* data, size_t dataSize, StreamOutHalHidl::WriterCallback callback) {

    mCommandMQ->write(&cmd);

    size_t availableToWrite = mDataMQ->availableToWrite();

    mDataMQ->write(data, dataSize);

    mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));

    uint32_t efState = 0;

retry:

    status_t ret = mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);

    if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)) {

        WriteStatus writeStatus;

        writeStatus.retval = Result::NOT_INITIALIZED;

        mStatusMQ->read(&writeStatus);

        if (writeStatus.retval == Result::OK) {

            ret = OK;

            callback(writeStatus);

        } else {

            ret = processReturn(cmdName, writeStatus.retval);
        }

        return ret;
    }

    if (ret == -EAGAIN || ret == -EINTR) {

        goto retry;
    }

    return ret;
}

av/media/libaudiohal/impl/StreamHalHidl.h

cpp 复制代码
typedef MessageQueue<WriteCommand, hardware::kSynchronizedReadWrite> CommandMQ;
typedef MessageQueue<uint8_t, hardware::kSynchronizedReadWrite> DataMQ;
typedef MessageQueue<WriteStatus, hardware::kSynchronizedReadWrite> StatusMQ;

std::unique_ptr<CommandMQ> mCommandMQ;
std::unique_ptr<DataMQ> mDataMQ;
std::unique_ptr<StatusMQ> mStatusMQ;

libfmq/include/fmq/MessageQueue.h fast message queue 快速共享内存消息队列方案

bash 复制代码
NX563J:/ # ps -A | grep audio
root           491     2          0      0 rescuer_thread      0 S [uaudio_svc]
u0_a153       3329  1024   14529584  77320 SyS_epoll_wait      0 S org.lineageos.audiofx
audioserver   3975     1      53432  18240 binder_ioctl_write_read 0 S android.hardware.audio.service
audioserver   3976     1   11615784  22980 binder_ioctl_write_read 0 S audioserver


NX563J:/ # cat proc/3976/maps | grep Ashmem                                                                                                                                                                       
1|NX563J:/ # cat proc/3976/maps | grep ashmem                                                                                                                                                                     
741dcf7000-741dd00000 rw-s 00000000 00:05 48339                          /dev/ashmem/MemoryHeapBase (deleted)
741de1c000-741de1d000 rw-s 00000000 00:05 72121                          /dev/ashmem/MessageQueue (deleted)
741de64000-741de65000 rw-s 00000000 00:05 72121                          /dev/ashmem/MessageQueue (deleted)
741dec7000-741dec8000 rw-s 00000000 00:05 72121                          /dev/ashmem/MessageQueue (deleted)
741df5f000-741df60000 rw-s 00001000 00:05 72120                          /dev/ashmem/MessageQueue (deleted)
741e0a4000-741e0a6000 rw-s 00000000 00:05 72120                          /dev/ashmem/MessageQueue (deleted)
741e122000-741e127000 rw-s 00000000 00:05 88955                          /dev/ashmem/MemoryHeapBase (deleted)
741e34e000-741e34f000 rw-s 00000000 00:05 72120                          /dev/ashmem/MessageQueue (deleted)
741e34f000-741e350000 rw-s 00000000 00:05 72120                          /dev/ashmem/MessageQueue (deleted)
741e350000-741e355000 rw-s 00000000 00:05 47035                          /dev/ashmem/MemoryHeapBase (deleted)
741e53e000-741e53f000 rw-s 00000000 00:05 72119                          /dev/ashmem/MessageQueue (deleted)
741e540000-741e541000 rw-s 00000000 00:05 72119                          /dev/ashmem/MessageQueue (deleted)
741e541000-741e542000 rw-s 00000000 00:05 72119                          /dev/ashmem/MessageQueue (deleted)
741e547000-741e548000 rw-s 00000000 00:05 60603                          /dev/ashmem/MemoryHeapBase (deleted)
741e548000-741e549000 rw-s 00000000 00:05 62515                          /dev/ashmem/MessageQueue (deleted)
741e549000-741e54a000 rw-s 00000000 00:05 62515                          /dev/ashmem/MessageQueue (deleted)
741e54a000-741e54b000 rw-s 00000000 00:05 62515                          /dev/ashmem/MessageQueue (deleted)
741e54c000-741e54d000 rw-s 00000000 00:05 62514                          /dev/ashmem/MessageQueue (deleted)
741e54d000-741e54e000 rw-s 00000000 00:05 62514                          /dev/ashmem/MessageQueue (deleted)
741e54f000-741e550000 rw-s 00000000 00:05 62514                          /dev/ashmem/MessageQueue (deleted)
741e550000-741e551000 rw-s 00000000 00:05 62514                          /dev/ashmem/MessageQueue (deleted)
741e551000-741e552000 rw-s 00000000 00:05 62513                          /dev/ashmem/MessageQueue (deleted)
741e554000-741e555000 rw-s 00000000 00:05 62513                          /dev/ashmem/MessageQueue (deleted)
741f709000-741f70a000 rw-s 00000000 00:05 62513                          /dev/ashmem/MessageQueue (deleted)
741f70a000-741f70b000 rw-s 00000000 00:05 48109                          /dev/ashmem/MemoryHeapBase (deleted)

NX563J:/ # cat proc/3975/maps | grep ashmem                                                                                                                                                                       
e74df000-e74e0000 rw-s 00000000 00:05 72121                              /dev/ashmem/MessageQueue (deleted)
e74e0000-e74e1000 rw-s 00000000 00:05 72121                              /dev/ashmem/MessageQueue (deleted)
e74e1000-e74e2000 rw-s 00000000 00:05 72121                              /dev/ashmem/MessageQueue (deleted)
e74e2000-e74e3000 rw-s 00001000 00:05 72120                              /dev/ashmem/MessageQueue (deleted)
e74e3000-e74e5000 rw-s 00000000 00:05 72120                              /dev/ashmem/MessageQueue (deleted)
e74e5000-e74e6000 rw-s 00000000 00:05 72120                              /dev/ashmem/MessageQueue (deleted)
e74e6000-e74e7000 rw-s 00000000 00:05 72120                              /dev/ashmem/MessageQueue (deleted)
e74e7000-e74e8000 rw-s 00000000 00:05 72119                              /dev/ashmem/MessageQueue (deleted)
e74e8000-e74e9000 rw-s 00000000 00:05 72119                              /dev/ashmem/MessageQueue (deleted)
e74e9000-e74ea000 rw-s 00000000 00:05 72119                              /dev/ashmem/MessageQueue (deleted)
e74fe000-e74ff000 rw-s 00000000 00:05 62515                              /dev/ashmem/MessageQueue (deleted)
e74ff000-e7500000 rw-s 00000000 00:05 62515                              /dev/ashmem/MessageQueue (deleted)
e7500000-e7501000 rw-s 00000000 00:05 62515                              /dev/ashmem/MessageQueue (deleted)
e7501000-e7502000 rw-s 00000000 00:05 62514                              /dev/ashmem/MessageQueue (deleted)
e75bb000-e75bc000 rw-s 00000000 00:05 62514                              /dev/ashmem/MessageQueue (deleted)
e75bc000-e75bd000 rw-s 00000000 00:05 62514                              /dev/ashmem/MessageQueue (deleted)
e75be000-e75bf000 rw-s 00000000 00:05 62514                              /dev/ashmem/MessageQueue (deleted)
e75bf000-e75c0000 rw-s 00000000 00:05 62513                              /dev/ashmem/MessageQueue (deleted)
e75c0000-e75c1000 rw-s 00000000 00:05 62513                              /dev/ashmem/MessageQueue (deleted)
e75c1000-e75c2000 rw-s 00000000 00:05 62513                              /dev/ashmem/MessageQueue (deleted)
e787c000-e787d000 rw-s 00000000 00:05 49782                              /dev/ashmem/MessageQueue (deleted)
e787d000-e787e000 rw-s 00000000 00:05 49782                              /dev/ashmem/MessageQueue (deleted)
e787e000-e787f000 rw-s 00000000 00:05 49782                              /dev/ashmem/MessageQueue (deleted)
e79a6000-e79a7000 rw-s 00000000 00:05 49782                              /dev/ashmem/MessageQueue (deleted)
e7a76000-e7a77000 rw-s 00001000 00:05 40712                              /dev/ashmem/MessageQueue (deleted)
e7a77000-e7a79000 rw-s 00000000 00:05 40712                              /dev/ashmem/MessageQueue (deleted)
e7a79000-e7a7a000 rw-s 00000000 00:05 40712                              /dev/ashmem/MessageQueue (deleted)
e7a7a000-e7a7b000 rw-s 00000000 00:05 40712                              /dev/ashmem/MessageQueue (deleted)

av/media/libaudiohal/impl/StreamHalHidl.cpp prepareForWriting

cpp 复制代码
status_t StreamOutHalHidl::prepareForWriting(size_t bufferSize) {

    std::unique_ptr<CommandMQ> tempCommandMQ;

    std::unique_ptr<DataMQ> tempDataMQ;

    std::unique_ptr<StatusMQ> tempStatusMQ;

    Result retval;

    pid_t halThreadPid, halThreadTid;

    Return<void> ret = mStream->prepareForWriting(
            1, bufferSize,
            [&](Result r,
                    const CommandMQ::Descriptor& commandMQ,
                    const DataMQ::Descriptor& dataMQ,
                    const StatusMQ::Descriptor& statusMQ,
                    const auto& halThreadInfo) {

                retval = r;

                if (retval == Result::OK) {

                    tempCommandMQ.reset(new CommandMQ(commandMQ));

                    tempDataMQ.reset(new DataMQ(dataMQ));

                    tempStatusMQ.reset(new StatusMQ(statusMQ));

                    if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {

                        EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);

                    }


                    halThreadPid = halThreadInfo.pid;
                    halThreadTid = halThreadInfo.tid;

                }
            });
    if (!ret.isOk() || retval != Result::OK) {

        return processReturn("prepareForWriting", ret, retval);

    }

    requestHalThreadPriority(halThreadPid, halThreadTid);

    mCommandMQ = std::move(tempCommandMQ);

    mDataMQ = std::move(tempDataMQ);

    mStatusMQ = std::move(tempStatusMQ);

    mWriterClient = gettid();

    return OK;
}

audio-hal

interfaces/audio/core/all-versions/default/StreamOut.cpp

cpp 复制代码
Return<void> StreamOut::prepareForWriting(uint32_t frameSize, uint32_t framesCount,
                                          prepareForWriting_cb _hidl_cb) {

    status_t status;

    std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1));

    std::unique_ptr<DataMQ> tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */));

    std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));

    auto tempWriteThread =
            sp<WriteThread>::make(&mStopWriteThread, mStream, tempCommandMQ.get(), tempDataMQ.get(),
                                  tempStatusMQ.get(), tempElfGroup.get());

    tempWriteThread->init();

    status = tempWriteThread->run("writer", PRIORITY_URGENT_AUDIO);

    mCommandMQ = std::move(tempCommandMQ);

    mDataMQ = std::move(tempDataMQ);

    mStatusMQ = std::move(tempStatusMQ);

    mWriteThread = tempWriteThread;

    _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(),
             threadInfo);
    return Void();
}

interfaces/audio/core/all-versions/default/StreamOut.cpp

cpp 复制代码
bool WriteThread::threadLoop() {

    while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {

        uint32_t efState = 0;

        mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);

        if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY))) {
            continue;  // Nothing to do.
        }

        if (!mCommandMQ->read(&mStatus.replyTo)) {
            continue;  // Nothing to do.
        }

        switch (mStatus.replyTo) {
            case IStreamOut::WriteCommand::WRITE:

                doWrite();

                break;

            case IStreamOut::WriteCommand::GET_PRESENTATION_POSITION:

                doGetPresentationPosition();

                break;

            case IStreamOut::WriteCommand::GET_LATENCY:

                doGetLatency();

                break;
        }

        if (!mStatusMQ->write(&mStatus)) {
            ALOGE("status message queue write failed");
        }

        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
    }

    return false;
}

void WriteThread::doWrite() {

    const size_t availToRead = mDataMQ->availableToRead();

    mStatus.retval = Result::OK;

    mStatus.reply.written = 0;

    if (mDataMQ->read(&mBuffer[0], availToRead)) {

        ssize_t writeResult = mStream->write(mStream, &mBuffer[0], availToRead);

        if (writeResult >= 0) {

            mStatus.reply.written = writeResult;

        } else {

            mStatus.retval = Stream::analyzeStatus("write", writeResult);

        }
    }
}
相关推荐
冬奇Lab10 小时前
一次必现ANR问题的深度分析与解决之旅:当NestedScrollView遇上VelocityTracker
android·性能优化·debug
三少爷的鞋10 小时前
2025 技术总结:我把技术重新结构化的一年
android
叶羽西10 小时前
查Google Android某个子仓库的修改情况
android
a1760293175710 小时前
3DS模拟器 Azahar模拟器最新版 安卓汉化中文版+PC版附3DS中文游戏资源全集+3DS密匙key和字库
android·游戏
山山而川 潺潺如镜12 小时前
python防止程序多开,但程序运行脚本
android·开发语言·python
花开彼岸天~12 小时前
Flutter跨平台开发:Android View 在鸿蒙系统上的使用指南
android·flutter·harmonyos
子一!!12 小时前
MySQL==表的结构操作1
android·python·adb
你不是我我12 小时前
【Java 开发日记】我们来说一下 MySQL 的慢查询日志
android·java·mysql
梦幻通灵21 小时前
Mysql字段判空实用技巧
android·数据库·mysql