Loading audio/aidl/common/include/Utils.h +6 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,12 @@ constexpr U makeBitPositionFlagMask(std::initializer_list<E> flags) { return result; } template <typename E, typename U = std::underlying_type_t<E>, typename = std::enable_if_t<is_bit_position_enum<E>::value>> constexpr bool areAllBitPositionFlagsSet(U mask, std::initializer_list<E> flags) { return (mask & makeBitPositionFlagMask<E>(flags)) == makeBitPositionFlagMask<E>(flags); } template <typename E, typename U = std::underlying_type_t<E>, typename = std::enable_if_t<is_bit_position_enum<E>::value>> constexpr bool isAnyBitPositionFlagSet(U mask, std::initializer_list<E> flags) { Loading audio/aidl/default/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -77,8 +77,10 @@ cc_library { "r_submix/ModuleRemoteSubmix.cpp", "r_submix/SubmixRoute.cpp", "r_submix/StreamRemoteSubmix.cpp", "stub/ApeHeader.cpp", "stub/DriverStubImpl.cpp", "stub/ModuleStub.cpp", "stub/StreamOffloadStub.cpp", "stub/StreamStub.cpp", "usb/ModuleUsb.cpp", "usb/StreamUsb.cpp", Loading audio/aidl/default/Module.cpp +3 −12 Original line number Diff line number Diff line Loading @@ -211,9 +211,9 @@ ndk::ScopedAStatus Module::createStreamContext( return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } const auto& flags = portConfigIt->flags.value(); StreamContext::DebugParameters params{ mDebug.streamTransientStateDelayMs, mVendorDebug.forceTransientBurst, mVendorDebug.forceSynchronousDrain, mVendorDebug.forceDrainToDraining}; 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; Loading Loading @@ -1546,7 +1546,6 @@ ndk::ScopedAStatus Module::generateHwAvSyncId(int32_t* _aidl_return) { const std::string Module::VendorDebug::kForceTransientBurstName = "aosp.forceTransientBurst"; const std::string Module::VendorDebug::kForceSynchronousDrainName = "aosp.forceSynchronousDrain"; const std::string Module::VendorDebug::kForceDrainToDrainingName = "aosp.forceDrainToDraining"; ndk::ScopedAStatus Module::getVendorParameters(const std::vector<std::string>& in_ids, std::vector<VendorParameter>* _aidl_return) { Loading @@ -1561,10 +1560,6 @@ ndk::ScopedAStatus Module::getVendorParameters(const std::vector<std::string>& i VendorParameter forceSynchronousDrain{.id = id}; forceSynchronousDrain.ext.setParcelable(Boolean{mVendorDebug.forceSynchronousDrain}); _aidl_return->push_back(std::move(forceSynchronousDrain)); } else if (id == VendorDebug::kForceDrainToDrainingName) { VendorParameter forceDrainToDraining{.id = id}; forceDrainToDraining.ext.setParcelable(Boolean{mVendorDebug.forceDrainToDraining}); _aidl_return->push_back(std::move(forceDrainToDraining)); } else { allParametersKnown = false; LOG(VERBOSE) << __func__ << ": " << mType << ": unrecognized parameter \"" << id << "\""; Loading Loading @@ -1605,10 +1600,6 @@ ndk::ScopedAStatus Module::setVendorParameters(const std::vector<VendorParameter if (!extractParameter<Boolean>(p, &mVendorDebug.forceSynchronousDrain)) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } } else if (p.id == VendorDebug::kForceDrainToDrainingName) { if (!extractParameter<Boolean>(p, &mVendorDebug.forceDrainToDraining)) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } } else { allParametersKnown = false; LOG(VERBOSE) << __func__ << ": " << mType << ": unrecognized parameter \"" << p.id Loading audio/aidl/default/ModulePrimary.cpp +27 −2 Original line number Diff line number Diff line Loading @@ -21,12 +21,16 @@ #include <android-base/logging.h> #include "core-impl/ModulePrimary.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::SinkMetadata; using aidl::android::hardware::audio::common::SourceMetadata; 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::MicrophoneInfo; Loading @@ -43,6 +47,17 @@ ndk::ScopedAStatus ModulePrimary::getTelephony(std::shared_ptr<ITelephony>* _aid return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus ModulePrimary::calculateBufferSizeFrames( const ::aidl::android::media::audio::common::AudioFormatDescription& format, int32_t latencyMs, int32_t sampleRateHz, int32_t* bufferSizeFrames) { if (format.type != ::aidl::android::media::audio::common::AudioFormatType::PCM && StreamOffloadStub::getSupportedEncodings().count(format.encoding)) { *bufferSizeFrames = sampleRateHz / 2; // 1/2 of a second. return ndk::ScopedAStatus::ok(); } return Module::calculateBufferSizeFrames(format, latencyMs, sampleRateHz, bufferSizeFrames); } ndk::ScopedAStatus ModulePrimary::createInputStream(StreamContext&& context, const SinkMetadata& sinkMetadata, const std::vector<MicrophoneInfo>& microphones, Loading @@ -54,8 +69,18 @@ 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( 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); } } int32_t ModulePrimary::getNominalLatencyMs(const AudioPortConfig&) { Loading audio/aidl/default/Stream.cpp +52 −37 Original line number Diff line number Diff line Loading @@ -142,12 +142,16 @@ std::string StreamWorkerCommonLogic::init() { ", size in bytes: " + std::to_string(mDataBufferSize); } } if (::android::status_t status = mDriver->init(); status != STATUS_OK) { if (::android::status_t status = mDriver->init(this /*DriverCallbackInterface*/); status != STATUS_OK) { return "Failed to initialize the driver: " + std::to_string(status); } return ""; } void StreamWorkerCommonLogic::onBufferStateChange(size_t /*bufferFramesLeft*/) {} void StreamWorkerCommonLogic::onClipStateChange(size_t /*clipFramesLeft*/, bool /*hasNextClip*/) {} void StreamWorkerCommonLogic::populateReply(StreamDescriptor::Reply* reply, bool isConnected) const { static const StreamDescriptor::Position kUnknownPosition = { Loading Loading @@ -381,48 +385,60 @@ bool StreamInWorkerLogic::read(size_t clientSize, StreamDescriptor::Reply* reply const std::string StreamOutWorkerLogic::kThreadName = "writer"; StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() { if (mState == StreamDescriptor::State::DRAINING && mContext->getForceDrainToDraining() && mOnDrainReadyStatus == OnDrainReadyStatus::UNSENT) { void StreamOutWorkerLogic::onBufferStateChange(size_t bufferFramesLeft) { const StreamDescriptor::State state = mState; LOG(DEBUG) << __func__ << ": state: " << toString(state) << ", bufferFramesLeft: " << bufferFramesLeft; if (state == StreamDescriptor::State::TRANSFERRING) { mState = StreamDescriptor::State::ACTIVE; std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback(); if (asyncCallback != nullptr) { ndk::ScopedAStatus status = asyncCallback->onDrainReady(); ndk::ScopedAStatus status = asyncCallback->onTransferReady(); if (!status.isOk()) { LOG(ERROR) << __func__ << ": error from onDrainReady: " << status; LOG(ERROR) << __func__ << ": error from onTransferReady: " << status; } // This sets the timeout for moving into IDLE on next iterations. switchToTransientState(StreamDescriptor::State::DRAINING); mOnDrainReadyStatus = OnDrainReadyStatus::SENT; } } else if (mState == StreamDescriptor::State::DRAINING || mState == StreamDescriptor::State::TRANSFERRING) { if (auto stateDurationMs = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::steady_clock::now() - mTransientStateStart); stateDurationMs >= mTransientStateDelayMs) { } } void StreamOutWorkerLogic::onClipStateChange(size_t clipFramesLeft, bool hasNextClip) { const DrainState drainState = mDrainState; std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback(); if (asyncCallback == nullptr) { // In blocking mode, mState can only be DRAINING. mState = StreamDescriptor::State::IDLE; } else { // In a real implementation, the driver should notify the HAL about // drain or transfer completion. In the stub, we switch unconditionally. if (mState == StreamDescriptor::State::DRAINING) { mState = StreamDescriptor::State::IDLE; if (mOnDrainReadyStatus != OnDrainReadyStatus::SENT) { LOG(DEBUG) << __func__ << ": drainState: " << drainState << "; clipFramesLeft " << clipFramesLeft << "; hasNextClip? " << hasNextClip << "; asyncCallback? " << (asyncCallback != nullptr); if (drainState != DrainState::NONE && clipFramesLeft == 0) { mState = hasNextClip ? StreamDescriptor::State::TRANSFERRING : StreamDescriptor::State::IDLE; mDrainState = DrainState::NONE; if (drainState == DrainState::ALL && asyncCallback != nullptr) { LOG(DEBUG) << __func__ << ": sending onDrainReady"; ndk::ScopedAStatus status = asyncCallback->onDrainReady(); if (!status.isOk()) { LOG(ERROR) << __func__ << ": error from onDrainReady: " << status; } mOnDrainReadyStatus = OnDrainReadyStatus::SENT; } } else { mState = StreamDescriptor::State::ACTIVE; ndk::ScopedAStatus status = asyncCallback->onTransferReady(); } else if (drainState == DrainState::EN && clipFramesLeft > 0) { // The stream state does not change, it is still draining. mDrainState = DrainState::EN_SENT; if (asyncCallback != nullptr) { LOG(DEBUG) << __func__ << ": sending onDrainReady"; ndk::ScopedAStatus status = asyncCallback->onDrainReady(); if (!status.isOk()) { LOG(ERROR) << __func__ << ": error from onTransferReady: " << status; LOG(ERROR) << __func__ << ": error from onDrainReady: " << status; } } } } StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() { // Non-blocking mode is handled within 'onClipStateChange' if (std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback(); mState == StreamDescriptor::State::DRAINING && asyncCallback == nullptr) { if (auto stateDurationMs = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::steady_clock::now() - mTransientStateStart); stateDurationMs >= mTransientStateDelayMs) { mState = StreamDescriptor::State::IDLE; if (mTransientStateDelayMs.count() != 0) { LOG(DEBUG) << __func__ << ": switched to state " << toString(mState) << " after a timeout"; Loading Loading @@ -552,10 +568,9 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() { mState = StreamDescriptor::State::IDLE; } else { switchToTransientState(StreamDescriptor::State::DRAINING); mOnDrainReadyStatus = mode == StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY ? OnDrainReadyStatus::UNSENT : OnDrainReadyStatus::IGNORE; mDrainState = mode == StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY ? DrainState::EN : DrainState::ALL; } } else { LOG(ERROR) << __func__ << ": drain failed: " << status; Loading Loading
audio/aidl/common/include/Utils.h +6 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,12 @@ constexpr U makeBitPositionFlagMask(std::initializer_list<E> flags) { return result; } template <typename E, typename U = std::underlying_type_t<E>, typename = std::enable_if_t<is_bit_position_enum<E>::value>> constexpr bool areAllBitPositionFlagsSet(U mask, std::initializer_list<E> flags) { return (mask & makeBitPositionFlagMask<E>(flags)) == makeBitPositionFlagMask<E>(flags); } template <typename E, typename U = std::underlying_type_t<E>, typename = std::enable_if_t<is_bit_position_enum<E>::value>> constexpr bool isAnyBitPositionFlagSet(U mask, std::initializer_list<E> flags) { Loading
audio/aidl/default/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -77,8 +77,10 @@ cc_library { "r_submix/ModuleRemoteSubmix.cpp", "r_submix/SubmixRoute.cpp", "r_submix/StreamRemoteSubmix.cpp", "stub/ApeHeader.cpp", "stub/DriverStubImpl.cpp", "stub/ModuleStub.cpp", "stub/StreamOffloadStub.cpp", "stub/StreamStub.cpp", "usb/ModuleUsb.cpp", "usb/StreamUsb.cpp", Loading
audio/aidl/default/Module.cpp +3 −12 Original line number Diff line number Diff line Loading @@ -211,9 +211,9 @@ ndk::ScopedAStatus Module::createStreamContext( return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } const auto& flags = portConfigIt->flags.value(); StreamContext::DebugParameters params{ mDebug.streamTransientStateDelayMs, mVendorDebug.forceTransientBurst, mVendorDebug.forceSynchronousDrain, mVendorDebug.forceDrainToDraining}; 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; Loading Loading @@ -1546,7 +1546,6 @@ ndk::ScopedAStatus Module::generateHwAvSyncId(int32_t* _aidl_return) { const std::string Module::VendorDebug::kForceTransientBurstName = "aosp.forceTransientBurst"; const std::string Module::VendorDebug::kForceSynchronousDrainName = "aosp.forceSynchronousDrain"; const std::string Module::VendorDebug::kForceDrainToDrainingName = "aosp.forceDrainToDraining"; ndk::ScopedAStatus Module::getVendorParameters(const std::vector<std::string>& in_ids, std::vector<VendorParameter>* _aidl_return) { Loading @@ -1561,10 +1560,6 @@ ndk::ScopedAStatus Module::getVendorParameters(const std::vector<std::string>& i VendorParameter forceSynchronousDrain{.id = id}; forceSynchronousDrain.ext.setParcelable(Boolean{mVendorDebug.forceSynchronousDrain}); _aidl_return->push_back(std::move(forceSynchronousDrain)); } else if (id == VendorDebug::kForceDrainToDrainingName) { VendorParameter forceDrainToDraining{.id = id}; forceDrainToDraining.ext.setParcelable(Boolean{mVendorDebug.forceDrainToDraining}); _aidl_return->push_back(std::move(forceDrainToDraining)); } else { allParametersKnown = false; LOG(VERBOSE) << __func__ << ": " << mType << ": unrecognized parameter \"" << id << "\""; Loading Loading @@ -1605,10 +1600,6 @@ ndk::ScopedAStatus Module::setVendorParameters(const std::vector<VendorParameter if (!extractParameter<Boolean>(p, &mVendorDebug.forceSynchronousDrain)) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } } else if (p.id == VendorDebug::kForceDrainToDrainingName) { if (!extractParameter<Boolean>(p, &mVendorDebug.forceDrainToDraining)) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } } else { allParametersKnown = false; LOG(VERBOSE) << __func__ << ": " << mType << ": unrecognized parameter \"" << p.id Loading
audio/aidl/default/ModulePrimary.cpp +27 −2 Original line number Diff line number Diff line Loading @@ -21,12 +21,16 @@ #include <android-base/logging.h> #include "core-impl/ModulePrimary.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::SinkMetadata; using aidl::android::hardware::audio::common::SourceMetadata; 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::MicrophoneInfo; Loading @@ -43,6 +47,17 @@ ndk::ScopedAStatus ModulePrimary::getTelephony(std::shared_ptr<ITelephony>* _aid return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus ModulePrimary::calculateBufferSizeFrames( const ::aidl::android::media::audio::common::AudioFormatDescription& format, int32_t latencyMs, int32_t sampleRateHz, int32_t* bufferSizeFrames) { if (format.type != ::aidl::android::media::audio::common::AudioFormatType::PCM && StreamOffloadStub::getSupportedEncodings().count(format.encoding)) { *bufferSizeFrames = sampleRateHz / 2; // 1/2 of a second. return ndk::ScopedAStatus::ok(); } return Module::calculateBufferSizeFrames(format, latencyMs, sampleRateHz, bufferSizeFrames); } ndk::ScopedAStatus ModulePrimary::createInputStream(StreamContext&& context, const SinkMetadata& sinkMetadata, const std::vector<MicrophoneInfo>& microphones, Loading @@ -54,8 +69,18 @@ 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( 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); } } int32_t ModulePrimary::getNominalLatencyMs(const AudioPortConfig&) { Loading
audio/aidl/default/Stream.cpp +52 −37 Original line number Diff line number Diff line Loading @@ -142,12 +142,16 @@ std::string StreamWorkerCommonLogic::init() { ", size in bytes: " + std::to_string(mDataBufferSize); } } if (::android::status_t status = mDriver->init(); status != STATUS_OK) { if (::android::status_t status = mDriver->init(this /*DriverCallbackInterface*/); status != STATUS_OK) { return "Failed to initialize the driver: " + std::to_string(status); } return ""; } void StreamWorkerCommonLogic::onBufferStateChange(size_t /*bufferFramesLeft*/) {} void StreamWorkerCommonLogic::onClipStateChange(size_t /*clipFramesLeft*/, bool /*hasNextClip*/) {} void StreamWorkerCommonLogic::populateReply(StreamDescriptor::Reply* reply, bool isConnected) const { static const StreamDescriptor::Position kUnknownPosition = { Loading Loading @@ -381,48 +385,60 @@ bool StreamInWorkerLogic::read(size_t clientSize, StreamDescriptor::Reply* reply const std::string StreamOutWorkerLogic::kThreadName = "writer"; StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() { if (mState == StreamDescriptor::State::DRAINING && mContext->getForceDrainToDraining() && mOnDrainReadyStatus == OnDrainReadyStatus::UNSENT) { void StreamOutWorkerLogic::onBufferStateChange(size_t bufferFramesLeft) { const StreamDescriptor::State state = mState; LOG(DEBUG) << __func__ << ": state: " << toString(state) << ", bufferFramesLeft: " << bufferFramesLeft; if (state == StreamDescriptor::State::TRANSFERRING) { mState = StreamDescriptor::State::ACTIVE; std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback(); if (asyncCallback != nullptr) { ndk::ScopedAStatus status = asyncCallback->onDrainReady(); ndk::ScopedAStatus status = asyncCallback->onTransferReady(); if (!status.isOk()) { LOG(ERROR) << __func__ << ": error from onDrainReady: " << status; LOG(ERROR) << __func__ << ": error from onTransferReady: " << status; } // This sets the timeout for moving into IDLE on next iterations. switchToTransientState(StreamDescriptor::State::DRAINING); mOnDrainReadyStatus = OnDrainReadyStatus::SENT; } } else if (mState == StreamDescriptor::State::DRAINING || mState == StreamDescriptor::State::TRANSFERRING) { if (auto stateDurationMs = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::steady_clock::now() - mTransientStateStart); stateDurationMs >= mTransientStateDelayMs) { } } void StreamOutWorkerLogic::onClipStateChange(size_t clipFramesLeft, bool hasNextClip) { const DrainState drainState = mDrainState; std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback(); if (asyncCallback == nullptr) { // In blocking mode, mState can only be DRAINING. mState = StreamDescriptor::State::IDLE; } else { // In a real implementation, the driver should notify the HAL about // drain or transfer completion. In the stub, we switch unconditionally. if (mState == StreamDescriptor::State::DRAINING) { mState = StreamDescriptor::State::IDLE; if (mOnDrainReadyStatus != OnDrainReadyStatus::SENT) { LOG(DEBUG) << __func__ << ": drainState: " << drainState << "; clipFramesLeft " << clipFramesLeft << "; hasNextClip? " << hasNextClip << "; asyncCallback? " << (asyncCallback != nullptr); if (drainState != DrainState::NONE && clipFramesLeft == 0) { mState = hasNextClip ? StreamDescriptor::State::TRANSFERRING : StreamDescriptor::State::IDLE; mDrainState = DrainState::NONE; if (drainState == DrainState::ALL && asyncCallback != nullptr) { LOG(DEBUG) << __func__ << ": sending onDrainReady"; ndk::ScopedAStatus status = asyncCallback->onDrainReady(); if (!status.isOk()) { LOG(ERROR) << __func__ << ": error from onDrainReady: " << status; } mOnDrainReadyStatus = OnDrainReadyStatus::SENT; } } else { mState = StreamDescriptor::State::ACTIVE; ndk::ScopedAStatus status = asyncCallback->onTransferReady(); } else if (drainState == DrainState::EN && clipFramesLeft > 0) { // The stream state does not change, it is still draining. mDrainState = DrainState::EN_SENT; if (asyncCallback != nullptr) { LOG(DEBUG) << __func__ << ": sending onDrainReady"; ndk::ScopedAStatus status = asyncCallback->onDrainReady(); if (!status.isOk()) { LOG(ERROR) << __func__ << ": error from onTransferReady: " << status; LOG(ERROR) << __func__ << ": error from onDrainReady: " << status; } } } } StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() { // Non-blocking mode is handled within 'onClipStateChange' if (std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback(); mState == StreamDescriptor::State::DRAINING && asyncCallback == nullptr) { if (auto stateDurationMs = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::steady_clock::now() - mTransientStateStart); stateDurationMs >= mTransientStateDelayMs) { mState = StreamDescriptor::State::IDLE; if (mTransientStateDelayMs.count() != 0) { LOG(DEBUG) << __func__ << ": switched to state " << toString(mState) << " after a timeout"; Loading Loading @@ -552,10 +568,9 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() { mState = StreamDescriptor::State::IDLE; } else { switchToTransientState(StreamDescriptor::State::DRAINING); mOnDrainReadyStatus = mode == StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY ? OnDrainReadyStatus::UNSENT : OnDrainReadyStatus::IGNORE; mDrainState = mode == StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY ? DrainState::EN : DrainState::ALL; } } else { LOG(ERROR) << __func__ << ": drain failed: " << status; Loading