Loading audio/aidl/default/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ cc_library { "stub/ApeHeader.cpp", "stub/DriverStubImpl.cpp", "stub/ModuleStub.cpp", "stub/StreamMmapStub.cpp", "stub/StreamOffloadStub.cpp", "stub/StreamStub.cpp", "usb/ModuleUsb.cpp", Loading audio/aidl/default/Module.cpp +26 −22 Original line number Diff line number Diff line Loading @@ -214,24 +214,33 @@ ndk::ScopedAStatus Module::createStreamContext( 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( StreamContext temp; if (hasMmapFlag(flags)) { MmapBufferDescriptor mmapDesc; RETURN_STATUS_IF_ERROR( createMmapBuffer(*portConfigIt, in_bufferSizeFrames, frameSize, &mmapDesc)); temp = StreamContext( 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::move(mmapDesc), outEventCallback, mSoundDose.getInstance(), params); } else { temp = StreamContext( 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::move(dataMQ), streamAsyncCallback, outEventCallback, mSoundDose.getInstance(), params); portConfigIt->ext.get<AudioPortExt::mix>().handle, std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames), asyncCallback, outEventCallback, mSoundDose.getInstance(), params); } if (temp.isValid()) { *out_context = std::move(temp); } else { Loading Loading @@ -394,9 +403,10 @@ ndk::ScopedAStatus Module::calculateBufferSizeFrames( return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } ndk::ScopedAStatus Module::createMmapBuffer( const ::aidl::android::hardware::audio::core::StreamContext& context __unused, ::aidl::android::hardware::audio::core::StreamDescriptor* desc __unused) { ndk::ScopedAStatus Module::createMmapBuffer(const AudioPortConfig& portConfig __unused, int32_t bufferSizeFrames __unused, int32_t frameSizeBytes __unused, MmapBufferDescriptor* desc __unused) { LOG(ERROR) << __func__ << ": " << mType << ": is not implemented"; return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } Loading Loading @@ -977,9 +987,6 @@ 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)); Loading Loading @@ -1027,9 +1034,6 @@ 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)); Loading audio/aidl/default/ModulePrimary.cpp +47 −9 Original line number Diff line number Diff line Loading @@ -21,18 +21,23 @@ #include <android-base/logging.h> #include "core-impl/ModulePrimary.h" #include "core-impl/StreamMmapStub.h" #include "core-impl/StreamOffloadStub.h" #include "core-impl/StreamPrimary.h" #include "core-impl/Telephony.h" using aidl::android::hardware::audio::common::areAllBitPositionFlagsSet; using aidl::android::hardware::audio::common::hasMmapFlag; using aidl::android::hardware::audio::common::SinkMetadata; using aidl::android::hardware::audio::common::SourceMetadata; using aidl::android::hardware::audio::core::StreamDescriptor; using aidl::android::media::audio::common::AudioInputFlags; using aidl::android::media::audio::common::AudioIoFlags; using aidl::android::media::audio::common::AudioOffloadInfo; using aidl::android::media::audio::common::AudioOutputFlags; using aidl::android::media::audio::common::AudioPort; using aidl::android::media::audio::common::AudioPortConfig; using aidl::android::media::audio::common::AudioPortExt; using aidl::android::media::audio::common::MicrophoneInfo; namespace aidl::android::hardware::audio::core { Loading Loading @@ -62,6 +67,11 @@ ndk::ScopedAStatus ModulePrimary::createInputStream(StreamContext&& context, const SinkMetadata& sinkMetadata, const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) { if (context.isMmap()) { // "Stub" is used because there is no support for MMAP audio I/O on CVD. return createStreamInstance<StreamInMmapStub>(result, std::move(context), sinkMetadata, microphones); } return createStreamInstance<StreamInPrimary>(result, std::move(context), sinkMetadata, microphones); } Loading @@ -69,26 +79,54 @@ ndk::ScopedAStatus ModulePrimary::createInputStream(StreamContext&& context, ndk::ScopedAStatus ModulePrimary::createOutputStream( StreamContext&& context, const SourceMetadata& sourceMetadata, const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) { if (!areAllBitPositionFlagsSet( if (context.isMmap()) { // "Stub" is used because there is no support for MMAP audio I/O on CVD. return createStreamInstance<StreamOutMmapStub>(result, std::move(context), sourceMetadata, offloadInfo); } else if (areAllBitPositionFlagsSet( context.getFlags().get<AudioIoFlags::output>(), {AudioOutputFlags::COMPRESS_OFFLOAD, AudioOutputFlags::NON_BLOCKING})) { return createStreamInstance<StreamOutPrimary>(result, std::move(context), sourceMetadata, offloadInfo); } else { // "Stub" is used because there is no actual decoder. The stream just // extracts the clip duration from the media file header and simulates // playback over time. return createStreamInstance<StreamOutOffloadStub>(result, std::move(context), sourceMetadata, offloadInfo); } return createStreamInstance<StreamOutPrimary>(result, std::move(context), sourceMetadata, offloadInfo); } ndk::ScopedAStatus ModulePrimary::createMmapBuffer(const AudioPortConfig& portConfig, int32_t bufferSizeFrames, int32_t frameSizeBytes, MmapBufferDescriptor* desc) { const size_t bufferSizeBytes = static_cast<size_t>(bufferSizeFrames) * frameSizeBytes; // The actual mmap buffer for I/O is created after the stream exits standby, via // 'IStreamCommon.createMmapBuffer'. But we must return a valid file descriptor here because // 'MmapBufferDescriptor' can not contain a "null" fd. const std::string regionName = std::string("mmap-sim-o-") + std::to_string(portConfig.ext.get<AudioPortExt::Tag::mix>().handle); int fd = ashmem_create_region(regionName.c_str(), bufferSizeBytes); if (fd < 0) { PLOG(ERROR) << __func__ << ": failed to create shared memory region of " << bufferSizeBytes << " bytes"; return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } desc->sharedMemory.fd = ndk::ScopedFileDescriptor(fd); desc->sharedMemory.size = bufferSizeBytes; desc->burstSizeFrames = bufferSizeFrames / 2; desc->flags = 0; LOG(DEBUG) << __func__ << ": " << desc->toString(); return ndk::ScopedAStatus::ok(); } int32_t ModulePrimary::getNominalLatencyMs(const AudioPortConfig&) { int32_t ModulePrimary::getNominalLatencyMs(const AudioPortConfig& portConfig) { static constexpr int32_t kLowLatencyMs = 5; // 85 ms is chosen considering 4096 frames @ 48 kHz. This is the value which allows // the virtual Android device implementation to pass CTS. Hardware implementations // should have significantly lower latency. static constexpr int32_t kLatencyMs = 85; return kLatencyMs; static constexpr int32_t kStandardLatencyMs = 85; return hasMmapFlag(portConfig.flags.value()) ? kLowLatencyMs : kStandardLatencyMs; } } // namespace aidl::android::hardware::audio::core audio/aidl/default/Stream.cpp +23 −12 Original line number Diff line number Diff line Loading @@ -65,18 +65,26 @@ void StreamContext::fillDescriptor(StreamDescriptor* desc) { if (mReplyMQ) { desc->reply = mReplyMQ->dupeDesc(); } if (mDataMQ) { desc->frameSizeBytes = getFrameSize(); desc->bufferSizeFrames = getBufferSizeInFrames(); if (mDataMQ) { desc->audio.set<StreamDescriptor::AudioBuffer::Tag::fmq>(mDataMQ->dupeDesc()); } else { MmapBufferDescriptor mmapDesc; // Move-only due to `fd`. mmapDesc.sharedMemory.fd = mMmapBufferDesc.sharedMemory.fd.dup(); mmapDesc.sharedMemory.size = mMmapBufferDesc.sharedMemory.size; mmapDesc.burstSizeFrames = mMmapBufferDesc.burstSizeFrames; mmapDesc.flags = mMmapBufferDesc.flags; desc->audio.set<StreamDescriptor::AudioBuffer::Tag::mmap>(std::move(mmapDesc)); } } size_t StreamContext::getBufferSizeInFrames() const { if (mDataMQ) { return mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() / getFrameSize(); } else { return mMmapBufferDesc.sharedMemory.size / getFrameSize(); } return 0; } size_t StreamContext::getFrameSize() const { Loading @@ -96,9 +104,13 @@ bool StreamContext::isValid() const { LOG(ERROR) << "frame size is invalid"; return false; } if (!hasMmapFlag(mFlags) && mDataMQ && !mDataMQ->isValid()) { if (!isMmap() && mDataMQ && !mDataMQ->isValid()) { LOG(ERROR) << "data FMQ is invalid"; return false; } else if (isMmap() && (mMmapBufferDesc.sharedMemory.fd.get() == -1 || mMmapBufferDesc.sharedMemory.size == 0 || mMmapBufferDesc.burstSizeFrames == 0)) { LOG(ERROR) << "mmap info is invalid" << mMmapBufferDesc.toString(); } return true; } Loading @@ -115,6 +127,7 @@ void StreamContext::reset() { mCommandMQ.reset(); mReplyMQ.reset(); mDataMQ.reset(); mMmapBufferDesc.sharedMemory.fd.set(-1); } pid_t StreamWorkerCommonLogic::getTid() const { Loading @@ -128,7 +141,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())) { if (!mContext->isMmap()) { StreamContext::DataMQ* const dataMQ = mContext->getDataMQ(); if (dataMQ == nullptr) return "Data MQ is null"; if (sizeof(DataBufferElement) != dataMQ->getQuantumSize()) { Loading Loading @@ -167,7 +180,7 @@ void StreamWorkerCommonLogic::populateReply(StreamDescriptor::Reply* reply, } else { reply->observable = reply->hardware = kUnknownPosition; } if (hasMmapFlag(mContext->getFlags())) { if (mContext->isMmap()) { if (auto status = mDriver->getMmapPositionAndLatency(&reply->hardware, &reply->latencyMs); status != ::android::OK) { reply->hardware = kUnknownPosition; Loading Loading @@ -252,9 +265,8 @@ StreamInWorkerLogic::Status StreamInWorkerLogic::cycle() { mState == StreamDescriptor::State::ACTIVE || mState == StreamDescriptor::State::PAUSED || mState == StreamDescriptor::State::DRAINING) { if (bool success = hasMmapFlag(mContext->getFlags()) ? readMmap(&reply) : read(fmqByteCount, &reply); if (bool success = mContext->isMmap() ? readMmap(&reply) : read(fmqByteCount, &reply); !success) { mState = StreamDescriptor::State::ERROR; } Loading Loading @@ -548,8 +560,7 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() { if (mState != StreamDescriptor::State::ERROR && mState != StreamDescriptor::State::TRANSFERRING && mState != StreamDescriptor::State::TRANSFER_PAUSED) { if (bool success = hasMmapFlag(mContext->getFlags()) ? writeMmap(&reply) if (bool success = mContext->isMmap() ? writeMmap(&reply) : write(fmqByteCount, &reply); !success) { mState = StreamDescriptor::State::ERROR; Loading audio/aidl/default/include/core-impl/Module.h +2 −2 Original line number Diff line number Diff line Loading @@ -212,8 +212,8 @@ class Module : public BnModule { const ::aidl::android::media::audio::common::AudioFormatDescription &format, int32_t latencyMs, int32_t sampleRateHz, int32_t *bufferSizeFrames); virtual ndk::ScopedAStatus createMmapBuffer( const ::aidl::android::hardware::audio::core::StreamContext& context, ::aidl::android::hardware::audio::core::StreamDescriptor* desc); const ::aidl::android::media::audio::common::AudioPortConfig& portConfig, int32_t bufferSizeFrames, int32_t frameSizeBytes, MmapBufferDescriptor* desc); // Utility and helper functions accessible to subclasses. static int32_t calculateBufferSizeFramesForPcm(int32_t latencyMs, int32_t sampleRateHz) { Loading Loading
audio/aidl/default/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ cc_library { "stub/ApeHeader.cpp", "stub/DriverStubImpl.cpp", "stub/ModuleStub.cpp", "stub/StreamMmapStub.cpp", "stub/StreamOffloadStub.cpp", "stub/StreamStub.cpp", "usb/ModuleUsb.cpp", Loading
audio/aidl/default/Module.cpp +26 −22 Original line number Diff line number Diff line Loading @@ -214,24 +214,33 @@ ndk::ScopedAStatus Module::createStreamContext( 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( StreamContext temp; if (hasMmapFlag(flags)) { MmapBufferDescriptor mmapDesc; RETURN_STATUS_IF_ERROR( createMmapBuffer(*portConfigIt, in_bufferSizeFrames, frameSize, &mmapDesc)); temp = StreamContext( 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::move(mmapDesc), outEventCallback, mSoundDose.getInstance(), params); } else { temp = StreamContext( 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::move(dataMQ), streamAsyncCallback, outEventCallback, mSoundDose.getInstance(), params); portConfigIt->ext.get<AudioPortExt::mix>().handle, std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames), asyncCallback, outEventCallback, mSoundDose.getInstance(), params); } if (temp.isValid()) { *out_context = std::move(temp); } else { Loading Loading @@ -394,9 +403,10 @@ ndk::ScopedAStatus Module::calculateBufferSizeFrames( return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } ndk::ScopedAStatus Module::createMmapBuffer( const ::aidl::android::hardware::audio::core::StreamContext& context __unused, ::aidl::android::hardware::audio::core::StreamDescriptor* desc __unused) { ndk::ScopedAStatus Module::createMmapBuffer(const AudioPortConfig& portConfig __unused, int32_t bufferSizeFrames __unused, int32_t frameSizeBytes __unused, MmapBufferDescriptor* desc __unused) { LOG(ERROR) << __func__ << ": " << mType << ": is not implemented"; return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } Loading Loading @@ -977,9 +987,6 @@ 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)); Loading Loading @@ -1027,9 +1034,6 @@ 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)); Loading
audio/aidl/default/ModulePrimary.cpp +47 −9 Original line number Diff line number Diff line Loading @@ -21,18 +21,23 @@ #include <android-base/logging.h> #include "core-impl/ModulePrimary.h" #include "core-impl/StreamMmapStub.h" #include "core-impl/StreamOffloadStub.h" #include "core-impl/StreamPrimary.h" #include "core-impl/Telephony.h" using aidl::android::hardware::audio::common::areAllBitPositionFlagsSet; using aidl::android::hardware::audio::common::hasMmapFlag; using aidl::android::hardware::audio::common::SinkMetadata; using aidl::android::hardware::audio::common::SourceMetadata; using aidl::android::hardware::audio::core::StreamDescriptor; using aidl::android::media::audio::common::AudioInputFlags; using aidl::android::media::audio::common::AudioIoFlags; using aidl::android::media::audio::common::AudioOffloadInfo; using aidl::android::media::audio::common::AudioOutputFlags; using aidl::android::media::audio::common::AudioPort; using aidl::android::media::audio::common::AudioPortConfig; using aidl::android::media::audio::common::AudioPortExt; using aidl::android::media::audio::common::MicrophoneInfo; namespace aidl::android::hardware::audio::core { Loading Loading @@ -62,6 +67,11 @@ ndk::ScopedAStatus ModulePrimary::createInputStream(StreamContext&& context, const SinkMetadata& sinkMetadata, const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) { if (context.isMmap()) { // "Stub" is used because there is no support for MMAP audio I/O on CVD. return createStreamInstance<StreamInMmapStub>(result, std::move(context), sinkMetadata, microphones); } return createStreamInstance<StreamInPrimary>(result, std::move(context), sinkMetadata, microphones); } Loading @@ -69,26 +79,54 @@ ndk::ScopedAStatus ModulePrimary::createInputStream(StreamContext&& context, ndk::ScopedAStatus ModulePrimary::createOutputStream( StreamContext&& context, const SourceMetadata& sourceMetadata, const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) { if (!areAllBitPositionFlagsSet( if (context.isMmap()) { // "Stub" is used because there is no support for MMAP audio I/O on CVD. return createStreamInstance<StreamOutMmapStub>(result, std::move(context), sourceMetadata, offloadInfo); } else if (areAllBitPositionFlagsSet( context.getFlags().get<AudioIoFlags::output>(), {AudioOutputFlags::COMPRESS_OFFLOAD, AudioOutputFlags::NON_BLOCKING})) { return createStreamInstance<StreamOutPrimary>(result, std::move(context), sourceMetadata, offloadInfo); } else { // "Stub" is used because there is no actual decoder. The stream just // extracts the clip duration from the media file header and simulates // playback over time. return createStreamInstance<StreamOutOffloadStub>(result, std::move(context), sourceMetadata, offloadInfo); } return createStreamInstance<StreamOutPrimary>(result, std::move(context), sourceMetadata, offloadInfo); } ndk::ScopedAStatus ModulePrimary::createMmapBuffer(const AudioPortConfig& portConfig, int32_t bufferSizeFrames, int32_t frameSizeBytes, MmapBufferDescriptor* desc) { const size_t bufferSizeBytes = static_cast<size_t>(bufferSizeFrames) * frameSizeBytes; // The actual mmap buffer for I/O is created after the stream exits standby, via // 'IStreamCommon.createMmapBuffer'. But we must return a valid file descriptor here because // 'MmapBufferDescriptor' can not contain a "null" fd. const std::string regionName = std::string("mmap-sim-o-") + std::to_string(portConfig.ext.get<AudioPortExt::Tag::mix>().handle); int fd = ashmem_create_region(regionName.c_str(), bufferSizeBytes); if (fd < 0) { PLOG(ERROR) << __func__ << ": failed to create shared memory region of " << bufferSizeBytes << " bytes"; return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } desc->sharedMemory.fd = ndk::ScopedFileDescriptor(fd); desc->sharedMemory.size = bufferSizeBytes; desc->burstSizeFrames = bufferSizeFrames / 2; desc->flags = 0; LOG(DEBUG) << __func__ << ": " << desc->toString(); return ndk::ScopedAStatus::ok(); } int32_t ModulePrimary::getNominalLatencyMs(const AudioPortConfig&) { int32_t ModulePrimary::getNominalLatencyMs(const AudioPortConfig& portConfig) { static constexpr int32_t kLowLatencyMs = 5; // 85 ms is chosen considering 4096 frames @ 48 kHz. This is the value which allows // the virtual Android device implementation to pass CTS. Hardware implementations // should have significantly lower latency. static constexpr int32_t kLatencyMs = 85; return kLatencyMs; static constexpr int32_t kStandardLatencyMs = 85; return hasMmapFlag(portConfig.flags.value()) ? kLowLatencyMs : kStandardLatencyMs; } } // namespace aidl::android::hardware::audio::core
audio/aidl/default/Stream.cpp +23 −12 Original line number Diff line number Diff line Loading @@ -65,18 +65,26 @@ void StreamContext::fillDescriptor(StreamDescriptor* desc) { if (mReplyMQ) { desc->reply = mReplyMQ->dupeDesc(); } if (mDataMQ) { desc->frameSizeBytes = getFrameSize(); desc->bufferSizeFrames = getBufferSizeInFrames(); if (mDataMQ) { desc->audio.set<StreamDescriptor::AudioBuffer::Tag::fmq>(mDataMQ->dupeDesc()); } else { MmapBufferDescriptor mmapDesc; // Move-only due to `fd`. mmapDesc.sharedMemory.fd = mMmapBufferDesc.sharedMemory.fd.dup(); mmapDesc.sharedMemory.size = mMmapBufferDesc.sharedMemory.size; mmapDesc.burstSizeFrames = mMmapBufferDesc.burstSizeFrames; mmapDesc.flags = mMmapBufferDesc.flags; desc->audio.set<StreamDescriptor::AudioBuffer::Tag::mmap>(std::move(mmapDesc)); } } size_t StreamContext::getBufferSizeInFrames() const { if (mDataMQ) { return mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() / getFrameSize(); } else { return mMmapBufferDesc.sharedMemory.size / getFrameSize(); } return 0; } size_t StreamContext::getFrameSize() const { Loading @@ -96,9 +104,13 @@ bool StreamContext::isValid() const { LOG(ERROR) << "frame size is invalid"; return false; } if (!hasMmapFlag(mFlags) && mDataMQ && !mDataMQ->isValid()) { if (!isMmap() && mDataMQ && !mDataMQ->isValid()) { LOG(ERROR) << "data FMQ is invalid"; return false; } else if (isMmap() && (mMmapBufferDesc.sharedMemory.fd.get() == -1 || mMmapBufferDesc.sharedMemory.size == 0 || mMmapBufferDesc.burstSizeFrames == 0)) { LOG(ERROR) << "mmap info is invalid" << mMmapBufferDesc.toString(); } return true; } Loading @@ -115,6 +127,7 @@ void StreamContext::reset() { mCommandMQ.reset(); mReplyMQ.reset(); mDataMQ.reset(); mMmapBufferDesc.sharedMemory.fd.set(-1); } pid_t StreamWorkerCommonLogic::getTid() const { Loading @@ -128,7 +141,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())) { if (!mContext->isMmap()) { StreamContext::DataMQ* const dataMQ = mContext->getDataMQ(); if (dataMQ == nullptr) return "Data MQ is null"; if (sizeof(DataBufferElement) != dataMQ->getQuantumSize()) { Loading Loading @@ -167,7 +180,7 @@ void StreamWorkerCommonLogic::populateReply(StreamDescriptor::Reply* reply, } else { reply->observable = reply->hardware = kUnknownPosition; } if (hasMmapFlag(mContext->getFlags())) { if (mContext->isMmap()) { if (auto status = mDriver->getMmapPositionAndLatency(&reply->hardware, &reply->latencyMs); status != ::android::OK) { reply->hardware = kUnknownPosition; Loading Loading @@ -252,9 +265,8 @@ StreamInWorkerLogic::Status StreamInWorkerLogic::cycle() { mState == StreamDescriptor::State::ACTIVE || mState == StreamDescriptor::State::PAUSED || mState == StreamDescriptor::State::DRAINING) { if (bool success = hasMmapFlag(mContext->getFlags()) ? readMmap(&reply) : read(fmqByteCount, &reply); if (bool success = mContext->isMmap() ? readMmap(&reply) : read(fmqByteCount, &reply); !success) { mState = StreamDescriptor::State::ERROR; } Loading Loading @@ -548,8 +560,7 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() { if (mState != StreamDescriptor::State::ERROR && mState != StreamDescriptor::State::TRANSFERRING && mState != StreamDescriptor::State::TRANSFER_PAUSED) { if (bool success = hasMmapFlag(mContext->getFlags()) ? writeMmap(&reply) if (bool success = mContext->isMmap() ? writeMmap(&reply) : write(fmqByteCount, &reply); !success) { mState = StreamDescriptor::State::ERROR; Loading
audio/aidl/default/include/core-impl/Module.h +2 −2 Original line number Diff line number Diff line Loading @@ -212,8 +212,8 @@ class Module : public BnModule { const ::aidl::android::media::audio::common::AudioFormatDescription &format, int32_t latencyMs, int32_t sampleRateHz, int32_t *bufferSizeFrames); virtual ndk::ScopedAStatus createMmapBuffer( const ::aidl::android::hardware::audio::core::StreamContext& context, ::aidl::android::hardware::audio::core::StreamDescriptor* desc); const ::aidl::android::media::audio::common::AudioPortConfig& portConfig, int32_t bufferSizeFrames, int32_t frameSizeBytes, MmapBufferDescriptor* desc); // Utility and helper functions accessible to subclasses. static int32_t calculateBufferSizeFramesForPcm(int32_t latencyMs, int32_t sampleRateHz) { Loading