diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp index f51f65e60e..d47b0b1bb6 100644 --- a/audio/aidl/default/Android.bp +++ b/audio/aidl/default/Android.bp @@ -77,6 +77,7 @@ cc_library { "r_submix/ModuleRemoteSubmix.cpp", "r_submix/SubmixRoute.cpp", "r_submix/StreamRemoteSubmix.cpp", + "stub/DriverStubImpl.cpp", "stub/ModuleStub.cpp", "stub/StreamStub.cpp", "usb/ModuleUsb.cpp", diff --git a/audio/aidl/default/include/core-impl/DriverStubImpl.h b/audio/aidl/default/include/core-impl/DriverStubImpl.h new file mode 100644 index 0000000000..40a9feab88 --- /dev/null +++ b/audio/aidl/default/include/core-impl/DriverStubImpl.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "core-impl/Stream.h" + +namespace aidl::android::hardware::audio::core { + +class DriverStubImpl : virtual public DriverInterface { + public: + explicit DriverStubImpl(const StreamContext& context); + + ::android::status_t init() override; + ::android::status_t drain(StreamDescriptor::DrainMode) override; + ::android::status_t flush() override; + ::android::status_t pause() override; + ::android::status_t standby() override; + ::android::status_t start() override; + ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount, + int32_t* latencyMs) override; + void shutdown() override; + + private: + const size_t mBufferSizeFrames; + const size_t mFrameSizeBytes; + const int mSampleRate; + const bool mIsAsynchronous; + const bool mIsInput; + bool mIsInitialized = false; // Used for validating the state machine logic. + bool mIsStandby = true; // Used for validating the state machine logic. + int64_t mStartTimeNs = 0; + long mFramesSinceStart = 0; +}; + +} // namespace aidl::android::hardware::audio::core diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h index 5dca739039..f7b926961e 100644 --- a/audio/aidl/default/include/core-impl/Stream.h +++ b/audio/aidl/default/include/core-impl/Stream.h @@ -133,6 +133,9 @@ class StreamContext { ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); } int getTransientStateDelayMs() const { return mDebugParameters.transientStateDelayMs; } int getSampleRate() const { return mSampleRate; } + bool isInput() const { + return mFlags.getTag() == ::aidl::android::media::audio::common::AudioIoFlags::input; + } bool isValid() const; // 'reset' is called on a Binder thread when closing the stream. Does not use // locking because it only cleans MQ pointers which were also set on the Binder thread. diff --git a/audio/aidl/default/include/core-impl/StreamPrimary.h b/audio/aidl/default/include/core-impl/StreamPrimary.h index 600c3779cd..4f19a468a3 100644 --- a/audio/aidl/default/include/core-impl/StreamPrimary.h +++ b/audio/aidl/default/include/core-impl/StreamPrimary.h @@ -16,25 +16,39 @@ #pragma once +#include #include +#include + +#include "DriverStubImpl.h" #include "StreamAlsa.h" -#include "StreamSwitcher.h" +#include "primary/PrimaryMixer.h" namespace aidl::android::hardware::audio::core { class StreamPrimary : public StreamAlsa { public: - StreamPrimary(StreamContext* context, const Metadata& metadata, - const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices); + StreamPrimary(StreamContext* context, const Metadata& metadata); + // Methods of 'DriverInterface'. + ::android::status_t init() override; + ::android::status_t drain(StreamDescriptor::DrainMode mode) override; + ::android::status_t flush() override; + ::android::status_t pause() override; + ::android::status_t standby() override; ::android::status_t start() override; ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount, int32_t* latencyMs) override; ::android::status_t refinePosition(StreamDescriptor::Position* position) override; + void shutdown() override; + + // Overridden methods of 'StreamCommonImpl', called on a Binder thread. + ndk::ScopedAStatus setConnectedDevices(const ConnectedDevices& devices) override; protected: std::vector getDeviceProfiles() override; + bool isStubStream(); const bool mIsAsynchronous; int64_t mStartTimeNs = 0; @@ -42,12 +56,29 @@ class StreamPrimary : public StreamAlsa { bool mSkipNextTransfer = false; private: - static std::pair getCardAndDeviceId( + using AlsaDeviceId = std::pair; + + static constexpr StreamPrimary::AlsaDeviceId kDefaultCardAndDeviceId{ + primary::PrimaryMixer::kAlsaCard, primary::PrimaryMixer::kAlsaDevice}; + static constexpr StreamPrimary::AlsaDeviceId kStubDeviceId{ + primary::PrimaryMixer::kInvalidAlsaCard, primary::PrimaryMixer::kInvalidAlsaDevice}; + + static AlsaDeviceId getCardAndDeviceId( const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices); - const std::pair mCardAndDeviceId; + static bool useStubStream(bool isInput, + const ::aidl::android::media::audio::common::AudioDevice& device); + + bool isStubStreamOnWorker() const { return mCurrAlsaDeviceId == kStubDeviceId; } + + DriverStubImpl mStubDriver; + mutable std::mutex mLock; + AlsaDeviceId mAlsaDeviceId GUARDED_BY(mLock) = kStubDeviceId; + + // Used by the worker thread only. + AlsaDeviceId mCurrAlsaDeviceId = kStubDeviceId; }; -class StreamInPrimary final : public StreamIn, public StreamSwitcher, public StreamInHwGainHelper { +class StreamInPrimary final : public StreamIn, public StreamPrimary, public StreamInHwGainHelper { public: friend class ndk::SharedRefBase; StreamInPrimary( @@ -56,14 +87,6 @@ class StreamInPrimary final : public StreamIn, public StreamSwitcher, public Str const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones); private: - static bool useStubStream(const ::aidl::android::media::audio::common::AudioDevice& device); - - DeviceSwitchBehavior switchCurrentStream( - const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) - override; - std::unique_ptr createNewStream( - const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices, - StreamContext* context, const Metadata& metadata) override; void onClose(StreamDescriptor::State) override { defaultOnClose(); } ndk::ScopedAStatus getHwGain(std::vector* _aidl_return) override; @@ -71,7 +94,7 @@ class StreamInPrimary final : public StreamIn, public StreamSwitcher, public Str }; class StreamOutPrimary final : public StreamOut, - public StreamSwitcher, + public StreamPrimary, public StreamOutHwVolumeHelper { public: friend class ndk::SharedRefBase; @@ -81,22 +104,10 @@ class StreamOutPrimary final : public StreamOut, offloadInfo); private: - static bool useStubStream(const ::aidl::android::media::audio::common::AudioDevice& device); - - DeviceSwitchBehavior switchCurrentStream( - const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) - override; - std::unique_ptr createNewStream( - const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices, - StreamContext* context, const Metadata& metadata) override; void onClose(StreamDescriptor::State) override { defaultOnClose(); } ndk::ScopedAStatus getHwVolume(std::vector* _aidl_return) override; ndk::ScopedAStatus setHwVolume(const std::vector& in_channelVolumes) override; - - ndk::ScopedAStatus setConnectedDevices( - const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) - override; }; } // namespace aidl::android::hardware::audio::core diff --git a/audio/aidl/default/include/core-impl/StreamStub.h b/audio/aidl/default/include/core-impl/StreamStub.h index 22b20202c5..cee44db848 100644 --- a/audio/aidl/default/include/core-impl/StreamStub.h +++ b/audio/aidl/default/include/core-impl/StreamStub.h @@ -16,38 +16,15 @@ #pragma once +#include "core-impl/DriverStubImpl.h" #include "core-impl/Stream.h" namespace aidl::android::hardware::audio::core { -class StreamStub : public StreamCommonImpl { +class StreamStub : public StreamCommonImpl, public DriverStubImpl { public: StreamStub(StreamContext* context, const Metadata& metadata); ~StreamStub(); - - // Methods of 'DriverInterface'. - ::android::status_t init() override; - ::android::status_t drain(StreamDescriptor::DrainMode) override; - ::android::status_t flush() override; - ::android::status_t pause() override; - ::android::status_t standby() override; - ::android::status_t start() override; - ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount, - int32_t* latencyMs) override; - void shutdown() override; - - private: - const size_t mBufferSizeFrames; - const size_t mFrameSizeBytes; - const int mSampleRate; - const bool mIsAsynchronous; - const bool mIsInput; - bool mIsInitialized = false; // Used for validating the state machine logic. - bool mIsStandby = true; // Used for validating the state machine logic. - - // Used by the worker thread. - int64_t mStartTimeNs = 0; - long mFramesSinceStart = 0; }; class StreamInStub final : public StreamIn, public StreamStub { diff --git a/audio/aidl/default/primary/PrimaryMixer.h b/audio/aidl/default/primary/PrimaryMixer.h index 3806428cfd..760d42f362 100644 --- a/audio/aidl/default/primary/PrimaryMixer.h +++ b/audio/aidl/default/primary/PrimaryMixer.h @@ -16,20 +16,14 @@ #pragma once -#include -#include -#include -#include - -#include -#include - #include "alsa/Mixer.h" namespace aidl::android::hardware::audio::core::primary { class PrimaryMixer : public alsa::Mixer { public: + static constexpr int kInvalidAlsaCard = -1; + static constexpr int kInvalidAlsaDevice = -1; static constexpr int kAlsaCard = 0; static constexpr int kAlsaDevice = 0; diff --git a/audio/aidl/default/primary/StreamPrimary.cpp b/audio/aidl/default/primary/StreamPrimary.cpp index 801bbb8e59..1176d05316 100644 --- a/audio/aidl/default/primary/StreamPrimary.cpp +++ b/audio/aidl/default/primary/StreamPrimary.cpp @@ -25,9 +25,7 @@ #include #include -#include "PrimaryMixer.h" #include "core-impl/StreamPrimary.h" -#include "core-impl/StreamStub.h" using aidl::android::hardware::audio::common::SinkMetadata; using aidl::android::hardware::audio::common::SourceMetadata; @@ -41,19 +39,49 @@ using android::base::GetBoolProperty; namespace aidl::android::hardware::audio::core { -const static constexpr std::pair kDefaultCardAndDeviceId = { - primary::PrimaryMixer::kAlsaCard, primary::PrimaryMixer::kAlsaDevice}; - -StreamPrimary::StreamPrimary( - StreamContext* context, const Metadata& metadata, - const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) +StreamPrimary::StreamPrimary(StreamContext* context, const Metadata& metadata) : StreamAlsa(context, metadata, 3 /*readWriteRetries*/), mIsAsynchronous(!!getContext().getAsyncCallback()), - mCardAndDeviceId(getCardAndDeviceId(devices)) { + mStubDriver(getContext()) { context->startStreamDataProcessor(); } +::android::status_t StreamPrimary::init() { + RETURN_STATUS_IF_ERROR(mStubDriver.init()); + return StreamAlsa::init(); +} + +::android::status_t StreamPrimary::drain(StreamDescriptor::DrainMode mode) { + return isStubStreamOnWorker() ? mStubDriver.drain(mode) : StreamAlsa::drain(mode); +} + +::android::status_t StreamPrimary::flush() { + return isStubStreamOnWorker() ? mStubDriver.flush() : StreamAlsa::flush(); +} + +::android::status_t StreamPrimary::pause() { + return isStubStreamOnWorker() ? mStubDriver.pause() : StreamAlsa::pause(); +} + +::android::status_t StreamPrimary::standby() { + return isStubStreamOnWorker() ? mStubDriver.standby() : StreamAlsa::standby(); +} + ::android::status_t StreamPrimary::start() { + bool isStub = true, shutdownAlsaStream = false; + { + std::lock_guard l(mLock); + isStub = mAlsaDeviceId == kStubDeviceId; + shutdownAlsaStream = + mCurrAlsaDeviceId != mAlsaDeviceId && mCurrAlsaDeviceId != kStubDeviceId; + mCurrAlsaDeviceId = mAlsaDeviceId; + } + if (shutdownAlsaStream) { + StreamAlsa::shutdown(); // Close currently opened ALSA devices. + } + if (isStub) { + return mStubDriver.start(); + } RETURN_STATUS_IF_ERROR(StreamAlsa::start()); mStartTimeNs = ::android::uptimeNanos(); mFramesSinceStart = 0; @@ -63,6 +91,9 @@ StreamPrimary::StreamPrimary( ::android::status_t StreamPrimary::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount, int32_t* latencyMs) { + if (isStubStreamOnWorker()) { + return mStubDriver.transfer(buffer, frameCount, actualFrameCount, latencyMs); + } // This is a workaround for the emulator implementation which has a host-side buffer // and is not being able to achieve real-time behavior similar to ADSPs (b/302587331). if (!mSkipNextTransfer) { @@ -102,19 +133,52 @@ StreamPrimary::StreamPrimary( return ::android::OK; } +void StreamPrimary::shutdown() { + StreamAlsa::shutdown(); + mStubDriver.shutdown(); +} + +ndk::ScopedAStatus StreamPrimary::setConnectedDevices(const ConnectedDevices& devices) { + LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(devices); + if (devices.size() > 1) { + LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: " + << devices.size(); + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + } + { + const bool useStubDriver = devices.empty() || useStubStream(mIsInput, devices[0]); + std::lock_guard l(mLock); + mAlsaDeviceId = useStubDriver ? kStubDeviceId : getCardAndDeviceId(devices); + } + if (!devices.empty()) { + auto streamDataProcessor = getContext().getStreamDataProcessor().lock(); + if (streamDataProcessor != nullptr) { + streamDataProcessor->setAudioDevice(devices[0]); + } + } + return StreamAlsa::setConnectedDevices(devices); +} + std::vector StreamPrimary::getDeviceProfiles() { - return {alsa::DeviceProfile{.card = mCardAndDeviceId.first, - .device = mCardAndDeviceId.second, + return {alsa::DeviceProfile{.card = mCurrAlsaDeviceId.first, + .device = mCurrAlsaDeviceId.second, .direction = mIsInput ? PCM_IN : PCM_OUT, .isExternal = false}}; } -std::pair StreamPrimary::getCardAndDeviceId(const std::vector& devices) { +bool StreamPrimary::isStubStream() { + std::lock_guard l(mLock); + return mAlsaDeviceId == kStubDeviceId; +} + +// static +StreamPrimary::AlsaDeviceId StreamPrimary::getCardAndDeviceId( + const std::vector& devices) { if (devices.empty() || devices[0].address.getTag() != AudioDeviceAddress::id) { return kDefaultCardAndDeviceId; } std::string deviceAddress = devices[0].address.get(); - std::pair cardAndDeviceId; + AlsaDeviceId cardAndDeviceId; if (const size_t suffixPos = deviceAddress.rfind("CARD_"); suffixPos == std::string::npos || sscanf(deviceAddress.c_str() + suffixPos, "CARD_%d_DEV_%d", &cardAndDeviceId.first, @@ -126,48 +190,28 @@ std::pair StreamPrimary::getCardAndDeviceId(const std::vector& microphones) : StreamIn(std::move(context), microphones), - StreamSwitcher(&mContextInstance, sinkMetadata), + StreamPrimary(&mContextInstance, sinkMetadata), StreamInHwGainHelper(&mContextInstance) {} -bool StreamInPrimary::useStubStream(const AudioDevice& device) { - static const bool kSimulateInput = - GetBoolProperty("ro.boot.audio.tinyalsa.simulate_input", false); - return kSimulateInput || device.type.type == AudioDeviceType::IN_TELEPHONY_RX || - device.type.type == AudioDeviceType::IN_FM_TUNER || - device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated */; -} - -StreamSwitcher::DeviceSwitchBehavior StreamInPrimary::switchCurrentStream( - const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) { - LOG(DEBUG) << __func__; - if (devices.size() > 1) { - LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: " - << devices.size(); - return DeviceSwitchBehavior::UNSUPPORTED_DEVICES; - } - if (devices.empty() || useStubStream(devices[0]) == isStubStream()) { - return DeviceSwitchBehavior::USE_CURRENT_STREAM; - } - return DeviceSwitchBehavior::CREATE_NEW_STREAM; -} - -std::unique_ptr StreamInPrimary::createNewStream( - const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices, - StreamContext* context, const Metadata& metadata) { - if (devices.empty()) { - LOG(FATAL) << __func__ << ": called with empty devices"; // see 'switchCurrentStream' - } - if (useStubStream(devices[0])) { - return std::unique_ptr( - new InnerStreamWrapper(context, metadata)); - } - return std::unique_ptr( - new InnerStreamWrapper(context, metadata, devices)); -} - ndk::ScopedAStatus StreamInPrimary::getHwGain(std::vector* _aidl_return) { if (isStubStream()) { return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); @@ -201,44 +245,9 @@ ndk::ScopedAStatus StreamInPrimary::setHwGain(const std::vector& in_chann StreamOutPrimary::StreamOutPrimary(StreamContext&& context, const SourceMetadata& sourceMetadata, const std::optional& offloadInfo) : StreamOut(std::move(context), offloadInfo), - StreamSwitcher(&mContextInstance, sourceMetadata), + StreamPrimary(&mContextInstance, sourceMetadata), StreamOutHwVolumeHelper(&mContextInstance) {} -bool StreamOutPrimary::useStubStream(const AudioDevice& device) { - static const bool kSimulateOutput = - GetBoolProperty("ro.boot.audio.tinyalsa.ignore_output", false); - return kSimulateOutput || device.type.type == AudioDeviceType::OUT_TELEPHONY_TX || - device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated*/; -} - -StreamSwitcher::DeviceSwitchBehavior StreamOutPrimary::switchCurrentStream( - const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) { - LOG(DEBUG) << __func__; - if (devices.size() > 1) { - LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: " - << devices.size(); - return DeviceSwitchBehavior::UNSUPPORTED_DEVICES; - } - if (devices.empty() || useStubStream(devices[0]) == isStubStream()) { - return DeviceSwitchBehavior::USE_CURRENT_STREAM; - } - return DeviceSwitchBehavior::CREATE_NEW_STREAM; -} - -std::unique_ptr StreamOutPrimary::createNewStream( - const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices, - StreamContext* context, const Metadata& metadata) { - if (devices.empty()) { - LOG(FATAL) << __func__ << ": called with empty devices"; // see 'switchCurrentStream' - } - if (useStubStream(devices[0])) { - return std::unique_ptr( - new InnerStreamWrapper(context, metadata)); - } - return std::unique_ptr( - new InnerStreamWrapper(context, metadata, devices)); -} - ndk::ScopedAStatus StreamOutPrimary::getHwVolume(std::vector* _aidl_return) { if (isStubStream()) { return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); @@ -264,15 +273,4 @@ ndk::ScopedAStatus StreamOutPrimary::setHwVolume(const std::vector& in_ch return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus StreamOutPrimary::setConnectedDevices( - const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) { - if (!devices.empty()) { - auto streamDataProcessor = mContextInstance.getStreamDataProcessor().lock(); - if (streamDataProcessor != nullptr) { - streamDataProcessor->setAudioDevice(devices[0]); - } - } - return StreamSwitcher::setConnectedDevices(devices); -} - } // namespace aidl::android::hardware::audio::core diff --git a/audio/aidl/default/stub/DriverStubImpl.cpp b/audio/aidl/default/stub/DriverStubImpl.cpp new file mode 100644 index 0000000000..beb0114bda --- /dev/null +++ b/audio/aidl/default/stub/DriverStubImpl.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define LOG_TAG "AHAL_Stream" +#include +#include + +#include "core-impl/DriverStubImpl.h" + +namespace aidl::android::hardware::audio::core { + +DriverStubImpl::DriverStubImpl(const StreamContext& context) + : mBufferSizeFrames(context.getBufferSizeInFrames()), + mFrameSizeBytes(context.getFrameSize()), + mSampleRate(context.getSampleRate()), + mIsAsynchronous(!!context.getAsyncCallback()), + mIsInput(context.isInput()) {} + +::android::status_t DriverStubImpl::init() { + mIsInitialized = true; + return ::android::OK; +} + +::android::status_t DriverStubImpl::drain(StreamDescriptor::DrainMode) { + if (!mIsInitialized) { + LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; + } + if (!mIsInput) { + if (!mIsAsynchronous) { + static constexpr float kMicrosPerSecond = MICROS_PER_SECOND; + const size_t delayUs = static_cast( + std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate)); + usleep(delayUs); + } else { + usleep(500); + } + } + return ::android::OK; +} + +::android::status_t DriverStubImpl::flush() { + if (!mIsInitialized) { + LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; + } + return ::android::OK; +} + +::android::status_t DriverStubImpl::pause() { + if (!mIsInitialized) { + LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; + } + return ::android::OK; +} + +::android::status_t DriverStubImpl::standby() { + if (!mIsInitialized) { + LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; + } + mIsStandby = true; + return ::android::OK; +} + +::android::status_t DriverStubImpl::start() { + if (!mIsInitialized) { + LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; + } + mIsStandby = false; + mStartTimeNs = ::android::uptimeNanos(); + mFramesSinceStart = 0; + return ::android::OK; +} + +::android::status_t DriverStubImpl::transfer(void* buffer, size_t frameCount, + size_t* actualFrameCount, int32_t*) { + if (!mIsInitialized) { + LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; + } + if (mIsStandby) { + LOG(FATAL) << __func__ << ": must not happen while in standby"; + } + *actualFrameCount = frameCount; + if (mIsAsynchronous) { + usleep(500); + } else { + mFramesSinceStart += *actualFrameCount; + const long bufferDurationUs = (*actualFrameCount) * MICROS_PER_SECOND / mSampleRate; + const auto totalDurationUs = + (::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND; + const long totalOffsetUs = + mFramesSinceStart * MICROS_PER_SECOND / mSampleRate - totalDurationUs; + LOG(VERBOSE) << __func__ << ": totalOffsetUs " << totalOffsetUs; + if (totalOffsetUs > 0) { + const long sleepTimeUs = std::min(totalOffsetUs, bufferDurationUs); + LOG(VERBOSE) << __func__ << ": sleeping for " << sleepTimeUs << " us"; + usleep(sleepTimeUs); + } + } + if (mIsInput) { + uint8_t* byteBuffer = static_cast(buffer); + for (size_t i = 0; i < frameCount * mFrameSizeBytes; ++i) { + byteBuffer[i] = std::rand() % 255; + } + } + return ::android::OK; +} + +void DriverStubImpl::shutdown() { + mIsInitialized = false; +} + +} // namespace aidl::android::hardware::audio::core diff --git a/audio/aidl/default/stub/StreamStub.cpp b/audio/aidl/default/stub/StreamStub.cpp index a3d99a8873..f6c87e1911 100644 --- a/audio/aidl/default/stub/StreamStub.cpp +++ b/audio/aidl/default/stub/StreamStub.cpp @@ -32,110 +32,12 @@ using aidl::android::media::audio::common::MicrophoneInfo; namespace aidl::android::hardware::audio::core { StreamStub::StreamStub(StreamContext* context, const Metadata& metadata) - : StreamCommonImpl(context, metadata), - mBufferSizeFrames(getContext().getBufferSizeInFrames()), - mFrameSizeBytes(getContext().getFrameSize()), - mSampleRate(getContext().getSampleRate()), - mIsAsynchronous(!!getContext().getAsyncCallback()), - mIsInput(isInput(metadata)) {} + : StreamCommonImpl(context, metadata), DriverStubImpl(getContext()) {} StreamStub::~StreamStub() { cleanupWorker(); } -::android::status_t StreamStub::init() { - mIsInitialized = true; - return ::android::OK; -} - -::android::status_t StreamStub::drain(StreamDescriptor::DrainMode) { - if (!mIsInitialized) { - LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; - } - if (!mIsInput) { - if (!mIsAsynchronous) { - static constexpr float kMicrosPerSecond = MICROS_PER_SECOND; - const size_t delayUs = static_cast( - std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate)); - usleep(delayUs); - } else { - usleep(500); - } - } - return ::android::OK; -} - -::android::status_t StreamStub::flush() { - if (!mIsInitialized) { - LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; - } - return ::android::OK; -} - -::android::status_t StreamStub::pause() { - if (!mIsInitialized) { - LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; - } - return ::android::OK; -} - -::android::status_t StreamStub::standby() { - if (!mIsInitialized) { - LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; - } - mIsStandby = true; - return ::android::OK; -} - -::android::status_t StreamStub::start() { - if (!mIsInitialized) { - LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; - } - mIsStandby = false; - mStartTimeNs = ::android::uptimeNanos(); - mFramesSinceStart = 0; - return ::android::OK; -} - -::android::status_t StreamStub::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount, - int32_t*) { - if (!mIsInitialized) { - LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; - } - if (mIsStandby) { - LOG(FATAL) << __func__ << ": must not happen while in standby"; - } - *actualFrameCount = frameCount; - if (mIsAsynchronous) { - usleep(500); - } else { - mFramesSinceStart += *actualFrameCount; - const long bufferDurationUs = - (*actualFrameCount) * MICROS_PER_SECOND / mContext.getSampleRate(); - const auto totalDurationUs = - (::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND; - const long totalOffsetUs = - mFramesSinceStart * MICROS_PER_SECOND / mContext.getSampleRate() - totalDurationUs; - LOG(VERBOSE) << __func__ << ": totalOffsetUs " << totalOffsetUs; - if (totalOffsetUs > 0) { - const long sleepTimeUs = std::min(totalOffsetUs, bufferDurationUs); - LOG(VERBOSE) << __func__ << ": sleeping for " << sleepTimeUs << " us"; - usleep(sleepTimeUs); - } - } - if (mIsInput) { - uint8_t* byteBuffer = static_cast(buffer); - for (size_t i = 0; i < frameCount * mFrameSizeBytes; ++i) { - byteBuffer[i] = std::rand() % 255; - } - } - return ::android::OK; -} - -void StreamStub::shutdown() { - mIsInitialized = false; -} - StreamInStub::StreamInStub(StreamContext&& context, const SinkMetadata& sinkMetadata, const std::vector& microphones) : StreamIn(std::move(context), microphones), StreamStub(&mContextInstance, sinkMetadata) {}