Loading media/libaudiohal/impl/StreamHalAidl.cpp +68 −22 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ using ::aidl::android::hardware::audio::core::IStreamIn; using ::aidl::android::hardware::audio::core::IStreamOut; using ::aidl::android::hardware::audio::core::MmapBufferDescriptor; using ::aidl::android::hardware::audio::core::StreamDescriptor; using ::aidl::android::hardware::audio::core::VendorParameter; using ::aidl::android::media::audio::common::MicrophoneDynamicInfo; using ::aidl::android::media::audio::IHalAdapterVendorExtension; Loading Loading @@ -73,7 +74,15 @@ using ::aidl::android::media::audio::IHalAdapterVendorExtension; namespace android { using HalCommand = StreamDescriptor::Command; namespace { static constexpr int32_t kAidlVersion1 = 1; static constexpr int32_t kAidlVersion2 = 2; static constexpr int32_t kAidlVersion3 = 3; static constexpr const char* kCreateMmapBuffer = "aosp.createMmapBuffer"; template<HalCommand::Tag cmd> HalCommand makeHalCommand() { return HalCommand::make<cmd>(::aidl::android::media::audio::common::Void{}); } Loading Loading @@ -135,7 +144,8 @@ StreamHalAidl::StreamHalAidl(std::string_view className, bool isInput, const aud mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format); } if (mStream != nullptr) { if (mStream == nullptr) return; mContext.getCommandMQ()->setErrorHandler( fmqErrorHandler<StreamContextAidl::CommandMQ::Error>("CommandMQ")); mContext.getReplyMQ()->setErrorHandler( Loading @@ -144,6 +154,17 @@ StreamHalAidl::StreamHalAidl(std::string_view className, bool isInput, const aud mContext.getDataMQ()->setErrorHandler( fmqErrorHandler<StreamContextAidl::DataMQ::Error>("DataMQ")); } if (auto status = mStream->getInterfaceVersion(&mAidlInterfaceVersion); status.isOk()) { if (mAidlInterfaceVersion > kAidlVersion3) { mSupportsCreateMmapBuffer = true; } else { VendorParameter createMmapBuffer{.id = kCreateMmapBuffer}; mSupportsCreateMmapBuffer = mStream->setVendorParameters({createMmapBuffer}, false).isOk(); } } else { AUGMENT_LOG(E, "failed to retrieve stream interface version: %s", status.getMessage()); } } Loading Loading @@ -400,12 +421,17 @@ status_t StreamHalAidl::getHardwarePosition(int64_t *frames, int64_t *timestamp) AUGMENT_LOG(V); if (!mStream) return NO_INIT; StreamDescriptor::Reply reply; RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply)); StatePositions statePositions{}; RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply, &statePositions)); if (reply.hardware.frames == StreamDescriptor::Position::UNKNOWN || reply.hardware.timeNs == StreamDescriptor::Position::UNKNOWN) { AUGMENT_LOG(W, "No position was reported by the HAL"); return INVALID_OPERATION; } *frames = reply.hardware.frames; int64_t mostRecentResetPoint = std::max(statePositions.hardware.framesAtStandby, statePositions.hardware.framesAtFlushOrDrain); int64_t aidlFrames = reply.hardware.frames; *frames = aidlFrames <= mostRecentResetPoint ? 0 : aidlFrames - mostRecentResetPoint; *timestamp = reply.hardware.timeNs; return OK; } Loading Loading @@ -627,7 +653,7 @@ void StreamHalAidl::onAsyncDrainReady() { || mStatePositions.drainState == StatePositions::DrainState::ALL))) { AUGMENT_LOG(D, "setting position %lld as clip end", (long long)mLastReply.observable.frames); mStatePositions.framesAtFlushOrDrain = mLastReply.observable.frames; mStatePositions.observable.framesAtFlushOrDrain = mLastReply.observable.frames; } mStatePositions.drainState = mStatePositions.drainState == StatePositions::DrainState::EN ? StatePositions::DrainState::EN_RECEIVED : StatePositions::DrainState::NONE; Loading @@ -650,12 +676,25 @@ status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused, if (!mContext.isMmapped()) { return BAD_VALUE; } if (mSupportsCreateMmapBuffer && (mAidlInterfaceVersion <= kAidlVersion3)) { std::vector<VendorParameter> parameters; RETURN_STATUS_IF_ERROR(statusTFromBinderStatus( mStream->getVendorParameters({kCreateMmapBuffer}, ¶meters))); if (parameters.size() == 1) { std::optional<MmapBufferDescriptor> result; RETURN_STATUS_IF_ERROR(parameters[0].ext.getParcelable(&result)); mContext.updateMmapBufferDescriptor(std::move(*result)); } else { AUGMENT_LOG(E, "invalid output from 'createMmapBuffer' via 'getVendorParameters': %s", internal::ToString(parameters).c_str()); return INVALID_OPERATION; } } const MmapBufferDescriptor& bufferDescriptor = mContext.getMmapBufferDescriptor(); info->shared_memory_fd = bufferDescriptor.sharedMemory.fd.get(); info->buffer_size_frames = mContext.getBufferSizeFrames(); info->burst_size_frames = bufferDescriptor.burstSizeFrames; info->flags = static_cast<audio_mmap_buffer_flag>(bufferDescriptor.flags); return OK; } Loading Loading @@ -727,15 +766,18 @@ status_t StreamHalAidl::sendCommand( if (reply->observable.frames != StreamDescriptor::Position::UNKNOWN) { if (command.getTag() == StreamDescriptor::Command::standby && reply->state == StreamDescriptor::State::STANDBY) { mStatePositions.framesAtStandby = reply->observable.frames; mStatePositions.observable.framesAtStandby = reply->observable.frames; mStatePositions.hardware.framesAtStandby = reply->hardware.frames; } else if (command.getTag() == StreamDescriptor::Command::flush && reply->state == StreamDescriptor::State::IDLE) { mStatePositions.framesAtFlushOrDrain = reply->observable.frames; mStatePositions.observable.framesAtFlushOrDrain = reply->observable.frames; mStatePositions.hardware.framesAtFlushOrDrain = reply->observable.frames; } else if (!mContext.isAsynchronous() && command.getTag() == StreamDescriptor::Command::drain && (reply->state == StreamDescriptor::State::IDLE || reply->state == StreamDescriptor::State::DRAINING)) { mStatePositions.framesAtFlushOrDrain = reply->observable.frames; mStatePositions.observable.framesAtFlushOrDrain = reply->observable.frames; mStatePositions.hardware.framesAtFlushOrDrain = reply->observable.frames; } // for asynchronous drain, the frame count is saved in 'onAsyncDrainReady' } if (mContext.isAsynchronous() && Loading Loading @@ -767,15 +809,19 @@ status_t StreamHalAidl::updateCountersIfNeeded( ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply, StatePositions* statePositions) { bool doUpdate = false; HalCommand cmd; { std::lock_guard l(mLock); doUpdate = uptimeNanos() > mLastReplyExpirationNs; cmd = mContext.isMmapped() && mSupportsCreateMmapBuffer && mLastReply.state == StreamDescriptor::State::ACTIVE ? makeHalCommand<HalCommand::Tag::burst>(0) : makeHalCommand<HalCommand::Tag::getStatus>(); } 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 */, statePositions); return sendCommand(cmd, reply, true /*safeFromNonWorkerThread */, statePositions); } else if (reply != nullptr) { // provide cached reply std::lock_guard l(mLock); *reply = mLastReply; Loading Loading @@ -882,10 +928,10 @@ status_t StreamOutHalAidl::getRenderPosition(uint64_t *dspFrames) { // See the table at the start of 'StreamHalInterface' on when it needs to reset. int64_t mostRecentResetPoint; if (!mContext.isAsynchronous() && audio_has_proportional_frames(mConfig.format)) { mostRecentResetPoint = statePositions.framesAtStandby; mostRecentResetPoint = statePositions.observable.framesAtStandby; } else { mostRecentResetPoint = std::max(statePositions.framesAtStandby, statePositions.framesAtFlushOrDrain); mostRecentResetPoint = std::max(statePositions.observable.framesAtStandby, statePositions.observable.framesAtFlushOrDrain); } *dspFrames = aidlFrames <= mostRecentResetPoint ? 0 : aidlFrames - mostRecentResetPoint; return OK; Loading Loading @@ -961,8 +1007,8 @@ status_t StreamOutHalAidl::getPresentationPosition(uint64_t *frames, struct time if (!mContext.isAsynchronous() && audio_has_proportional_frames(mConfig.format)) { *frames = aidlFrames; } else { const int64_t mostRecentResetPoint = std::max(statePositions.framesAtStandby, statePositions.framesAtFlushOrDrain); const int64_t mostRecentResetPoint = std::max(statePositions.observable.framesAtStandby, statePositions.observable.framesAtFlushOrDrain); *frames = aidlFrames <= mostRecentResetPoint ? 0 : aidlFrames - mostRecentResetPoint; } timestamp->tv_sec = aidlTimestamp / NANOS_PER_SECOND; Loading media/libaudiohal/impl/StreamHalAidl.h +16 −9 Original line number Diff line number Diff line Loading @@ -37,9 +37,6 @@ #include "ConversionHelperAidl.h" #include "StreamPowerLog.h" using ::aidl::android::hardware::audio::common::AudioOffloadMetadata; using ::aidl::android::hardware::audio::core::MmapBufferDescriptor; namespace android { class StreamContextAidl { Loading Loading @@ -87,10 +84,14 @@ class StreamContextAidl { ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); } bool isAsynchronous() const { return mIsAsynchronous; } bool isMmapped() const { return mIsMmapped; } const MmapBufferDescriptor& getMmapBufferDescriptor() const { return mMmapBufferDescriptor; } const ::aidl::android::hardware::audio::core::MmapBufferDescriptor& getMmapBufferDescriptor() const { return mMmapBufferDescriptor; } size_t getMmapBurstSize() const { return mMmapBufferDescriptor.burstSizeFrames; } int getIoHandle() const { return mIoHandle; } bool hasClipTransitionSupport() const { return mHasClipTransitionSupport; } void updateMmapBufferDescriptor( ::aidl::android::hardware::audio::core::MmapBufferDescriptor&& desc) { mMmapBufferDescriptor = std::move(desc); } private: static std::unique_ptr<DataMQ> maybeCreateDataMQ( Loading @@ -106,7 +107,7 @@ class StreamContextAidl { using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag; return descriptor.audio.getTag() == Tag::mmap; } static MmapBufferDescriptor maybeGetMmapBuffer( static ::aidl::android::hardware::audio::core::MmapBufferDescriptor maybeGetMmapBuffer( ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) { using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag; if (descriptor.audio.getTag() == Tag::mmap) { Loading @@ -122,7 +123,7 @@ class StreamContextAidl { std::unique_ptr<DataMQ> mDataMQ; bool mIsAsynchronous; bool mIsMmapped; MmapBufferDescriptor mMmapBufferDescriptor; ::aidl::android::hardware::audio::core::MmapBufferDescriptor mMmapBufferDescriptor; int mIoHandle; bool mHasClipTransitionSupport; }; Loading Loading @@ -183,9 +184,13 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper // For tests. friend class sp<StreamHalAidl>; struct StatePositions { struct FrameCounters { int64_t framesAtFlushOrDrain; int64_t framesAtStandby; }; struct StatePositions { FrameCounters observable; FrameCounters hardware; enum DrainState : int32_t { NONE, ALL, EN /*early notify*/, EN_RECEIVED }; DrainState drainState; }; Loading Loading @@ -288,7 +293,7 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper const bool mIsInput; const audio_config_base_t mConfig; const StreamContextAidl mContext; StreamContextAidl mContext; // This lock is used to make sending of a command and receiving a reply an atomic // operation. Otherwise, when two threads are trying to send a command, they may both advance to // reading of the reply once the HAL has consumed the command from the MQ, and that creates a Loading Loading @@ -340,6 +345,8 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper // mStreamPowerLog is used for audio signal power logging. StreamPowerLog mStreamPowerLog; std::atomic<pid_t> mWorkerTid = -1; int32_t mAidlInterfaceVersion = -1; bool mSupportsCreateMmapBuffer = false; }; class CallbackBroker; Loading Loading @@ -446,7 +453,7 @@ class StreamOutHalAidl : public virtual StreamOutHalInterface, const wp<CallbackBroker> mCallbackBroker; mediautils::atomic_wp<StreamOutHalInterfaceCallback> mClientCallback; AudioOffloadMetadata mOffloadMetadata; ::aidl::android::hardware::audio::common::AudioOffloadMetadata mOffloadMetadata; // Can not be constructed directly by clients. StreamOutHalAidl( Loading media/libaudiohal/tests/CoreAudioHalAidl_test.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,10 @@ using ::aidl::android::media::audio::common::PcmType; class VendorParameterMock { public: void clearParameters() { mAsyncParameters.clear(); mSyncParameters.clear(); } const std::vector<std::string>& getRetrievedParameterIds() const { return mGetParameterIds; } const std::vector<VendorParameter>& getAsyncParameters() const { return mAsyncParameters; } const std::vector<VendorParameter>& getSyncParameters() const { return mSyncParameters; } Loading Loading @@ -995,6 +999,8 @@ class StreamHalAidlVendorParametersTest : public testing::Test { false /*hasClipTransitionSupport*/); mStream = sp<StreamHalAidl>::make("test", false /*isInput*/, config, 0 /*nominalLatency*/, std::move(context), mStreamCommon, mVendorExt); // The stream may check for some properties after creating. mStreamCommon->clearParameters(); } void TearDown() override { mStream.clear(); Loading media/libmediahelper/AudioParameter.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ const char * const AudioParameter::keyOffloadCodecPaddingSamples = AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES; const char * const AudioParameter::keyClipTransitionSupport = AUDIO_PARAMETER_CLIP_TRANSITION_SUPPORT; const char * const keyCreateMmapBuffer = AUDIO_PARAMETER_CREATE_MMAP_BUFFER; AudioParameter::AudioParameter(const String8& keyValuePairs) { Loading media/libmediahelper/include/media/AudioParameter.h +1 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,7 @@ public: static const char * const keyOffloadCodecPaddingSamples; static const char * const keyClipTransitionSupport; static const char * const keyCreateMmapBuffer; String8 toString() const { return toStringImpl(true); } String8 keysToString() const { return toStringImpl(false); } Loading Loading
media/libaudiohal/impl/StreamHalAidl.cpp +68 −22 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ using ::aidl::android::hardware::audio::core::IStreamIn; using ::aidl::android::hardware::audio::core::IStreamOut; using ::aidl::android::hardware::audio::core::MmapBufferDescriptor; using ::aidl::android::hardware::audio::core::StreamDescriptor; using ::aidl::android::hardware::audio::core::VendorParameter; using ::aidl::android::media::audio::common::MicrophoneDynamicInfo; using ::aidl::android::media::audio::IHalAdapterVendorExtension; Loading Loading @@ -73,7 +74,15 @@ using ::aidl::android::media::audio::IHalAdapterVendorExtension; namespace android { using HalCommand = StreamDescriptor::Command; namespace { static constexpr int32_t kAidlVersion1 = 1; static constexpr int32_t kAidlVersion2 = 2; static constexpr int32_t kAidlVersion3 = 3; static constexpr const char* kCreateMmapBuffer = "aosp.createMmapBuffer"; template<HalCommand::Tag cmd> HalCommand makeHalCommand() { return HalCommand::make<cmd>(::aidl::android::media::audio::common::Void{}); } Loading Loading @@ -135,7 +144,8 @@ StreamHalAidl::StreamHalAidl(std::string_view className, bool isInput, const aud mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format); } if (mStream != nullptr) { if (mStream == nullptr) return; mContext.getCommandMQ()->setErrorHandler( fmqErrorHandler<StreamContextAidl::CommandMQ::Error>("CommandMQ")); mContext.getReplyMQ()->setErrorHandler( Loading @@ -144,6 +154,17 @@ StreamHalAidl::StreamHalAidl(std::string_view className, bool isInput, const aud mContext.getDataMQ()->setErrorHandler( fmqErrorHandler<StreamContextAidl::DataMQ::Error>("DataMQ")); } if (auto status = mStream->getInterfaceVersion(&mAidlInterfaceVersion); status.isOk()) { if (mAidlInterfaceVersion > kAidlVersion3) { mSupportsCreateMmapBuffer = true; } else { VendorParameter createMmapBuffer{.id = kCreateMmapBuffer}; mSupportsCreateMmapBuffer = mStream->setVendorParameters({createMmapBuffer}, false).isOk(); } } else { AUGMENT_LOG(E, "failed to retrieve stream interface version: %s", status.getMessage()); } } Loading Loading @@ -400,12 +421,17 @@ status_t StreamHalAidl::getHardwarePosition(int64_t *frames, int64_t *timestamp) AUGMENT_LOG(V); if (!mStream) return NO_INIT; StreamDescriptor::Reply reply; RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply)); StatePositions statePositions{}; RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply, &statePositions)); if (reply.hardware.frames == StreamDescriptor::Position::UNKNOWN || reply.hardware.timeNs == StreamDescriptor::Position::UNKNOWN) { AUGMENT_LOG(W, "No position was reported by the HAL"); return INVALID_OPERATION; } *frames = reply.hardware.frames; int64_t mostRecentResetPoint = std::max(statePositions.hardware.framesAtStandby, statePositions.hardware.framesAtFlushOrDrain); int64_t aidlFrames = reply.hardware.frames; *frames = aidlFrames <= mostRecentResetPoint ? 0 : aidlFrames - mostRecentResetPoint; *timestamp = reply.hardware.timeNs; return OK; } Loading Loading @@ -627,7 +653,7 @@ void StreamHalAidl::onAsyncDrainReady() { || mStatePositions.drainState == StatePositions::DrainState::ALL))) { AUGMENT_LOG(D, "setting position %lld as clip end", (long long)mLastReply.observable.frames); mStatePositions.framesAtFlushOrDrain = mLastReply.observable.frames; mStatePositions.observable.framesAtFlushOrDrain = mLastReply.observable.frames; } mStatePositions.drainState = mStatePositions.drainState == StatePositions::DrainState::EN ? StatePositions::DrainState::EN_RECEIVED : StatePositions::DrainState::NONE; Loading @@ -650,12 +676,25 @@ status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused, if (!mContext.isMmapped()) { return BAD_VALUE; } if (mSupportsCreateMmapBuffer && (mAidlInterfaceVersion <= kAidlVersion3)) { std::vector<VendorParameter> parameters; RETURN_STATUS_IF_ERROR(statusTFromBinderStatus( mStream->getVendorParameters({kCreateMmapBuffer}, ¶meters))); if (parameters.size() == 1) { std::optional<MmapBufferDescriptor> result; RETURN_STATUS_IF_ERROR(parameters[0].ext.getParcelable(&result)); mContext.updateMmapBufferDescriptor(std::move(*result)); } else { AUGMENT_LOG(E, "invalid output from 'createMmapBuffer' via 'getVendorParameters': %s", internal::ToString(parameters).c_str()); return INVALID_OPERATION; } } const MmapBufferDescriptor& bufferDescriptor = mContext.getMmapBufferDescriptor(); info->shared_memory_fd = bufferDescriptor.sharedMemory.fd.get(); info->buffer_size_frames = mContext.getBufferSizeFrames(); info->burst_size_frames = bufferDescriptor.burstSizeFrames; info->flags = static_cast<audio_mmap_buffer_flag>(bufferDescriptor.flags); return OK; } Loading Loading @@ -727,15 +766,18 @@ status_t StreamHalAidl::sendCommand( if (reply->observable.frames != StreamDescriptor::Position::UNKNOWN) { if (command.getTag() == StreamDescriptor::Command::standby && reply->state == StreamDescriptor::State::STANDBY) { mStatePositions.framesAtStandby = reply->observable.frames; mStatePositions.observable.framesAtStandby = reply->observable.frames; mStatePositions.hardware.framesAtStandby = reply->hardware.frames; } else if (command.getTag() == StreamDescriptor::Command::flush && reply->state == StreamDescriptor::State::IDLE) { mStatePositions.framesAtFlushOrDrain = reply->observable.frames; mStatePositions.observable.framesAtFlushOrDrain = reply->observable.frames; mStatePositions.hardware.framesAtFlushOrDrain = reply->observable.frames; } else if (!mContext.isAsynchronous() && command.getTag() == StreamDescriptor::Command::drain && (reply->state == StreamDescriptor::State::IDLE || reply->state == StreamDescriptor::State::DRAINING)) { mStatePositions.framesAtFlushOrDrain = reply->observable.frames; mStatePositions.observable.framesAtFlushOrDrain = reply->observable.frames; mStatePositions.hardware.framesAtFlushOrDrain = reply->observable.frames; } // for asynchronous drain, the frame count is saved in 'onAsyncDrainReady' } if (mContext.isAsynchronous() && Loading Loading @@ -767,15 +809,19 @@ status_t StreamHalAidl::updateCountersIfNeeded( ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply, StatePositions* statePositions) { bool doUpdate = false; HalCommand cmd; { std::lock_guard l(mLock); doUpdate = uptimeNanos() > mLastReplyExpirationNs; cmd = mContext.isMmapped() && mSupportsCreateMmapBuffer && mLastReply.state == StreamDescriptor::State::ACTIVE ? makeHalCommand<HalCommand::Tag::burst>(0) : makeHalCommand<HalCommand::Tag::getStatus>(); } 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 */, statePositions); return sendCommand(cmd, reply, true /*safeFromNonWorkerThread */, statePositions); } else if (reply != nullptr) { // provide cached reply std::lock_guard l(mLock); *reply = mLastReply; Loading Loading @@ -882,10 +928,10 @@ status_t StreamOutHalAidl::getRenderPosition(uint64_t *dspFrames) { // See the table at the start of 'StreamHalInterface' on when it needs to reset. int64_t mostRecentResetPoint; if (!mContext.isAsynchronous() && audio_has_proportional_frames(mConfig.format)) { mostRecentResetPoint = statePositions.framesAtStandby; mostRecentResetPoint = statePositions.observable.framesAtStandby; } else { mostRecentResetPoint = std::max(statePositions.framesAtStandby, statePositions.framesAtFlushOrDrain); mostRecentResetPoint = std::max(statePositions.observable.framesAtStandby, statePositions.observable.framesAtFlushOrDrain); } *dspFrames = aidlFrames <= mostRecentResetPoint ? 0 : aidlFrames - mostRecentResetPoint; return OK; Loading Loading @@ -961,8 +1007,8 @@ status_t StreamOutHalAidl::getPresentationPosition(uint64_t *frames, struct time if (!mContext.isAsynchronous() && audio_has_proportional_frames(mConfig.format)) { *frames = aidlFrames; } else { const int64_t mostRecentResetPoint = std::max(statePositions.framesAtStandby, statePositions.framesAtFlushOrDrain); const int64_t mostRecentResetPoint = std::max(statePositions.observable.framesAtStandby, statePositions.observable.framesAtFlushOrDrain); *frames = aidlFrames <= mostRecentResetPoint ? 0 : aidlFrames - mostRecentResetPoint; } timestamp->tv_sec = aidlTimestamp / NANOS_PER_SECOND; Loading
media/libaudiohal/impl/StreamHalAidl.h +16 −9 Original line number Diff line number Diff line Loading @@ -37,9 +37,6 @@ #include "ConversionHelperAidl.h" #include "StreamPowerLog.h" using ::aidl::android::hardware::audio::common::AudioOffloadMetadata; using ::aidl::android::hardware::audio::core::MmapBufferDescriptor; namespace android { class StreamContextAidl { Loading Loading @@ -87,10 +84,14 @@ class StreamContextAidl { ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); } bool isAsynchronous() const { return mIsAsynchronous; } bool isMmapped() const { return mIsMmapped; } const MmapBufferDescriptor& getMmapBufferDescriptor() const { return mMmapBufferDescriptor; } const ::aidl::android::hardware::audio::core::MmapBufferDescriptor& getMmapBufferDescriptor() const { return mMmapBufferDescriptor; } size_t getMmapBurstSize() const { return mMmapBufferDescriptor.burstSizeFrames; } int getIoHandle() const { return mIoHandle; } bool hasClipTransitionSupport() const { return mHasClipTransitionSupport; } void updateMmapBufferDescriptor( ::aidl::android::hardware::audio::core::MmapBufferDescriptor&& desc) { mMmapBufferDescriptor = std::move(desc); } private: static std::unique_ptr<DataMQ> maybeCreateDataMQ( Loading @@ -106,7 +107,7 @@ class StreamContextAidl { using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag; return descriptor.audio.getTag() == Tag::mmap; } static MmapBufferDescriptor maybeGetMmapBuffer( static ::aidl::android::hardware::audio::core::MmapBufferDescriptor maybeGetMmapBuffer( ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) { using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag; if (descriptor.audio.getTag() == Tag::mmap) { Loading @@ -122,7 +123,7 @@ class StreamContextAidl { std::unique_ptr<DataMQ> mDataMQ; bool mIsAsynchronous; bool mIsMmapped; MmapBufferDescriptor mMmapBufferDescriptor; ::aidl::android::hardware::audio::core::MmapBufferDescriptor mMmapBufferDescriptor; int mIoHandle; bool mHasClipTransitionSupport; }; Loading Loading @@ -183,9 +184,13 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper // For tests. friend class sp<StreamHalAidl>; struct StatePositions { struct FrameCounters { int64_t framesAtFlushOrDrain; int64_t framesAtStandby; }; struct StatePositions { FrameCounters observable; FrameCounters hardware; enum DrainState : int32_t { NONE, ALL, EN /*early notify*/, EN_RECEIVED }; DrainState drainState; }; Loading Loading @@ -288,7 +293,7 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper const bool mIsInput; const audio_config_base_t mConfig; const StreamContextAidl mContext; StreamContextAidl mContext; // This lock is used to make sending of a command and receiving a reply an atomic // operation. Otherwise, when two threads are trying to send a command, they may both advance to // reading of the reply once the HAL has consumed the command from the MQ, and that creates a Loading Loading @@ -340,6 +345,8 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper // mStreamPowerLog is used for audio signal power logging. StreamPowerLog mStreamPowerLog; std::atomic<pid_t> mWorkerTid = -1; int32_t mAidlInterfaceVersion = -1; bool mSupportsCreateMmapBuffer = false; }; class CallbackBroker; Loading Loading @@ -446,7 +453,7 @@ class StreamOutHalAidl : public virtual StreamOutHalInterface, const wp<CallbackBroker> mCallbackBroker; mediautils::atomic_wp<StreamOutHalInterfaceCallback> mClientCallback; AudioOffloadMetadata mOffloadMetadata; ::aidl::android::hardware::audio::common::AudioOffloadMetadata mOffloadMetadata; // Can not be constructed directly by clients. StreamOutHalAidl( Loading
media/libaudiohal/tests/CoreAudioHalAidl_test.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,10 @@ using ::aidl::android::media::audio::common::PcmType; class VendorParameterMock { public: void clearParameters() { mAsyncParameters.clear(); mSyncParameters.clear(); } const std::vector<std::string>& getRetrievedParameterIds() const { return mGetParameterIds; } const std::vector<VendorParameter>& getAsyncParameters() const { return mAsyncParameters; } const std::vector<VendorParameter>& getSyncParameters() const { return mSyncParameters; } Loading Loading @@ -995,6 +999,8 @@ class StreamHalAidlVendorParametersTest : public testing::Test { false /*hasClipTransitionSupport*/); mStream = sp<StreamHalAidl>::make("test", false /*isInput*/, config, 0 /*nominalLatency*/, std::move(context), mStreamCommon, mVendorExt); // The stream may check for some properties after creating. mStreamCommon->clearParameters(); } void TearDown() override { mStream.clear(); Loading
media/libmediahelper/AudioParameter.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ const char * const AudioParameter::keyOffloadCodecPaddingSamples = AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES; const char * const AudioParameter::keyClipTransitionSupport = AUDIO_PARAMETER_CLIP_TRANSITION_SUPPORT; const char * const keyCreateMmapBuffer = AUDIO_PARAMETER_CREATE_MMAP_BUFFER; AudioParameter::AudioParameter(const String8& keyValuePairs) { Loading
media/libmediahelper/include/media/AudioParameter.h +1 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,7 @@ public: static const char * const keyOffloadCodecPaddingSamples; static const char * const keyClipTransitionSupport; static const char * const keyCreateMmapBuffer; String8 toString() const { return toStringImpl(true); } String8 keysToString() const { return toStringImpl(false); } Loading