From f12d4a1ef804f4c382e6bfcef545f37ebbff6a2e Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Thu, 13 Jul 2023 15:25:36 -0700 Subject: [PATCH 1/4] audio: Simplify and extend alsa::Mixer Remove alsa::MixerControl. tinyALSA contains utility functions for setting values in percents, they use the same logic as used to be there for handling the "volume" control. Use access serialization at the mixer level, rather than for each control. Move the call to 'mixer_open' to alsa::Mixer. Add controls for capture (mic) mute and gain. They will be used by the primary HAL. Bug: 264712385 Test: atest VtsHalAudioCoreTargetTest Change-Id: I0fad994153de96aceec3eb8f2fec19805ec912f8 --- audio/aidl/default/alsa/Mixer.cpp | 207 +++++++++++------- audio/aidl/default/alsa/Mixer.h | 51 +++-- .../aidl/default/usb/UsbAlsaMixerControl.cpp | 6 +- 3 files changed, 153 insertions(+), 111 deletions(-) diff --git a/audio/aidl/default/alsa/Mixer.cpp b/audio/aidl/default/alsa/Mixer.cpp index f0393e3a7e..126c033f66 100644 --- a/audio/aidl/default/alsa/Mixer.cpp +++ b/audio/aidl/default/alsa/Mixer.cpp @@ -14,44 +14,17 @@ * limitations under the License. */ -#define LOG_TAG "AHAL_AlsaMixer" -#include - +#include #include +#define LOG_TAG "AHAL_AlsaMixer" +#include #include #include "Mixer.h" namespace aidl::android::hardware::audio::core::alsa { -//----------------------------------------------------------------------------- - -MixerControl::MixerControl(struct mixer_ctl* ctl) - : mCtl(ctl), - mNumValues(mixer_ctl_get_num_values(ctl)), - mMinValue(mixer_ctl_get_range_min(ctl)), - mMaxValue(mixer_ctl_get_range_max(ctl)) {} - -unsigned int MixerControl::getNumValues() const { - return mNumValues; -} - -int MixerControl::getMaxValue() const { - return mMaxValue; -} - -int MixerControl::getMinValue() const { - return mMinValue; -} - -int MixerControl::setArray(const void* array, size_t count) { - const std::lock_guard guard(mLock); - return mixer_ctl_set_array(mCtl, array, count); -} - -//----------------------------------------------------------------------------- - // static const std::map> Mixer::kPossibleControls = { @@ -60,18 +33,20 @@ const std::map> Mixer::initializeMixerControls( - struct mixer* mixer) { - std::map> mixerControls; +Mixer::Controls Mixer::initializeMixerControls(struct mixer* mixer) { + if (mixer == nullptr) return {}; + Controls mixerControls; std::string mixerCtlNames; for (const auto& [control, possibleCtls] : kPossibleControls) { for (const auto& [ctlName, expectedCtlType] : possibleCtls) { struct mixer_ctl* ctl = mixer_get_ctl_by_name(mixer, ctlName.c_str()); if (ctl != nullptr && mixer_ctl_get_type(ctl) == expectedCtlType) { - mixerControls.emplace(control, std::make_unique(ctl)); + mixerControls.emplace(control, ctl); if (!mixerCtlNames.empty()) { mixerCtlNames += ","; } @@ -84,71 +59,141 @@ std::map> Mixer::initializeMixerCo return mixerControls; } -Mixer::Mixer(struct mixer* mixer) - : mMixer(mixer), mMixerControls(initializeMixerControls(mMixer)) {} +std::ostream& operator<<(std::ostream& s, Mixer::Control c) { + switch (c) { + case Mixer::Control::MASTER_SWITCH: + s << "master mute"; + break; + case Mixer::Control::MASTER_VOLUME: + s << "master volume"; + break; + case Mixer::Control::HW_VOLUME: + s << "volume"; + break; + case Mixer::Control::MIC_SWITCH: + s << "mic mute"; + break; + case Mixer::Control::MIC_GAIN: + s << "mic gain"; + break; + } + return s; +} + +Mixer::Mixer(int card) : mMixer(mixer_open(card)), mMixerControls(initializeMixerControls(mMixer)) { + if (!isValid()) { + PLOG(ERROR) << __func__ << ": failed to open mixer for card=" << card; + } +} Mixer::~Mixer() { - mixer_close(mMixer); + if (isValid()) { + std::lock_guard l(mMixerAccess); + mixer_close(mMixer); + } } -namespace { - -int volumeFloatToInteger(float fValue, int maxValue, int minValue) { - return minValue + std::ceil((maxValue - minValue) * fValue); -} - -} // namespace - ndk::ScopedAStatus Mixer::setMasterMute(bool muted) { - auto it = mMixerControls.find(Mixer::MASTER_SWITCH); - if (it == mMixerControls.end()) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); - } - const int numValues = it->second->getNumValues(); - std::vector values(numValues, muted ? 0 : 1); - if (int err = it->second->setArray(values.data(), numValues); err != 0) { - LOG(ERROR) << __func__ << ": failed to set master mute, err=" << err; - return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); - } - return ndk::ScopedAStatus::ok(); + return setMixerControlMute(MASTER_SWITCH, muted); } ndk::ScopedAStatus Mixer::setMasterVolume(float volume) { - auto it = mMixerControls.find(Mixer::MASTER_VOLUME); - if (it == mMixerControls.end()) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); - } - const int numValues = it->second->getNumValues(); - std::vector values(numValues, volumeFloatToInteger(volume, it->second->getMaxValue(), - it->second->getMinValue())); - if (int err = it->second->setArray(values.data(), numValues); err != 0) { - LOG(ERROR) << __func__ << ": failed to set master volume, err=" << err; - return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); - } - return ndk::ScopedAStatus::ok(); + return setMixerControlVolume(MASTER_VOLUME, volume); +} + +ndk::ScopedAStatus Mixer::setMicGain(float gain) { + return setMixerControlVolume(MIC_GAIN, gain); +} + +ndk::ScopedAStatus Mixer::setMicMute(bool muted) { + return setMixerControlMute(MIC_SWITCH, muted); } ndk::ScopedAStatus Mixer::setVolumes(const std::vector& volumes) { + if (!isValid()) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } auto it = mMixerControls.find(Mixer::HW_VOLUME); if (it == mMixerControls.end()) { return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } - const int numValues = it->second->getNumValues(); - if (numValues < 0) { - LOG(FATAL) << __func__ << ": negative number of values: " << numValues; - } - const int maxValue = it->second->getMaxValue(); - const int minValue = it->second->getMinValue(); - std::vector values; - size_t i = 0; - for (; i < static_cast(numValues) && i < values.size(); ++i) { - values.emplace_back(volumeFloatToInteger(volumes[i], maxValue, minValue)); - } - if (int err = it->second->setArray(values.data(), values.size()); err != 0) { + std::vector percents; + std::transform( + volumes.begin(), volumes.end(), std::back_inserter(percents), + [](float volume) -> int { return std::floor(std::clamp(volume, 0.0f, 1.0f) * 100); }); + std::lock_guard l(mMixerAccess); + if (int err = setMixerControlPercent(it->second, percents); err != 0) { LOG(ERROR) << __func__ << ": failed to set volume, err=" << err; return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } return ndk::ScopedAStatus::ok(); } +ndk::ScopedAStatus Mixer::setMixerControlMute(Mixer::Control ctl, bool muted) { + if (!isValid()) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } + auto it = mMixerControls.find(ctl); + if (it == mMixerControls.end()) { + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + } + std::lock_guard l(mMixerAccess); + if (int err = setMixerControlValue(it->second, muted ? 0 : 1); err != 0) { + LOG(ERROR) << __func__ << ": failed to set " << ctl << " to " << muted << ", err=" << err; + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Mixer::setMixerControlVolume(Control ctl, float volume) { + if (!isValid()) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } + auto it = mMixerControls.find(ctl); + if (it == mMixerControls.end()) { + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + } + volume = std::clamp(volume, 0.0f, 1.0f); + std::lock_guard l(mMixerAccess); + if (int err = setMixerControlPercent(it->second, std::floor(volume * 100)); err != 0) { + LOG(ERROR) << __func__ << ": failed to set " << ctl << " to " << volume << ", err=" << err; + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } + return ndk::ScopedAStatus::ok(); +} + +int Mixer::setMixerControlPercent(struct mixer_ctl* ctl, int percent) { + int ret = 0; + const unsigned int n = mixer_ctl_get_num_values(ctl); + for (unsigned int id = 0; id < n; id++) { + if (int error = mixer_ctl_set_percent(ctl, id, percent); error != 0) { + ret = error; + } + } + return ret; +} + +int Mixer::setMixerControlPercent(struct mixer_ctl* ctl, const std::vector& percents) { + int ret = 0; + const unsigned int n = mixer_ctl_get_num_values(ctl); + for (unsigned int id = 0; id < n; id++) { + if (int error = mixer_ctl_set_percent(ctl, id, id < percents.size() ? percents[id] : 0); + error != 0) { + ret = error; + } + } + return ret; +} + +int Mixer::setMixerControlValue(struct mixer_ctl* ctl, int value) { + int ret = 0; + const unsigned int n = mixer_ctl_get_num_values(ctl); + for (unsigned int id = 0; id < n; id++) { + if (int error = mixer_ctl_set_value(ctl, id, value); error != 0) { + ret = error; + } + } + return ret; +} + } // namespace aidl::android::hardware::audio::core::alsa diff --git a/audio/aidl/default/alsa/Mixer.h b/audio/aidl/default/alsa/Mixer.h index de9e6f42cd..78728c296e 100644 --- a/audio/aidl/default/alsa/Mixer.h +++ b/audio/aidl/default/alsa/Mixer.h @@ -16,6 +16,7 @@ #pragma once +#include #include #include #include @@ -31,34 +32,17 @@ extern "C" { namespace aidl::android::hardware::audio::core::alsa { -class MixerControl { - public: - explicit MixerControl(struct mixer_ctl* ctl); - - unsigned int getNumValues() const; - int getMaxValue() const; - int getMinValue() const; - int setArray(const void* array, size_t count); - - private: - std::mutex mLock; - // The mixer_ctl object is owned by ALSA and will be released when the mixer is closed. - struct mixer_ctl* mCtl GUARDED_BY(mLock); - const unsigned int mNumValues; - const int mMinValue; - const int mMaxValue; -}; - class Mixer { public: - explicit Mixer(struct mixer* mixer); - + explicit Mixer(int card); ~Mixer(); bool isValid() const { return mMixer != nullptr; } ndk::ScopedAStatus setMasterMute(bool muted); ndk::ScopedAStatus setMasterVolume(float volume); + ndk::ScopedAStatus setMicGain(float gain); + ndk::ScopedAStatus setMicMute(bool muted); ndk::ScopedAStatus setVolumes(const std::vector& volumes); private: @@ -66,17 +50,32 @@ class Mixer { MASTER_SWITCH, MASTER_VOLUME, HW_VOLUME, + MIC_SWITCH, + MIC_GAIN, }; using ControlNamesAndExpectedCtlType = std::pair; - static const std::map> kPossibleControls; - static std::map> initializeMixerControls( - struct mixer* mixer); + using Controls = std::map; + friend std::ostream& operator<<(std::ostream&, Control); + static const std::map> kPossibleControls; + static Controls initializeMixerControls(struct mixer* mixer); + + ndk::ScopedAStatus setMixerControlMute(Control ctl, bool muted); + ndk::ScopedAStatus setMixerControlVolume(Control ctl, float volume); + + int setMixerControlPercent(struct mixer_ctl* ctl, int percent) REQUIRES(mMixerAccess); + int setMixerControlPercent(struct mixer_ctl* ctl, const std::vector& percents) + REQUIRES(mMixerAccess); + int setMixerControlValue(struct mixer_ctl* ctl, int value) REQUIRES(mMixerAccess); + + // Since ALSA functions do not use internal locking, enforce thread safety at our level. + std::mutex mMixerAccess; // The mixer object is owned by ALSA and will be released when the mixer is closed. - struct mixer* mMixer; + struct mixer* const mMixer; // `mMixerControls` will only be initialized in constructor. After that, it wil only be - // read but not be modified. - const std::map> mMixerControls; + // read but not be modified. Each mixer_ctl object is owned by ALSA, it's life span is + // the same as of the mixer itself. + const Controls mMixerControls; }; } // namespace aidl::android::hardware::audio::core::alsa diff --git a/audio/aidl/default/usb/UsbAlsaMixerControl.cpp b/audio/aidl/default/usb/UsbAlsaMixerControl.cpp index 769d739969..0a49446e5a 100644 --- a/audio/aidl/default/usb/UsbAlsaMixerControl.cpp +++ b/audio/aidl/default/usb/UsbAlsaMixerControl.cpp @@ -33,12 +33,10 @@ void UsbAlsaMixerControl::setDeviceConnectionState(int card, bool masterMuted, f bool connected) { LOG(DEBUG) << __func__ << ": card=" << card << ", connected=" << connected; if (connected) { - struct mixer* mixer = mixer_open(card); - if (mixer == nullptr) { - PLOG(ERROR) << __func__ << ": failed to open mixer for card=" << card; + auto alsaMixer = std::make_shared(card); + if (!alsaMixer->isValid()) { return; } - auto alsaMixer = std::make_shared(mixer); alsaMixer->setMasterMute(masterMuted); alsaMixer->setMasterVolume(masterVolume); const std::lock_guard guard(mLock); From 422f7e6b1b36359e5dd1492b17d29afbbe546c87 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Thu, 13 Jul 2023 16:32:08 -0700 Subject: [PATCH 2/4] audio: Update StreamAlsa and alsa utils for built-in devices Use new functions added to alsa proxy layer for opening attached (built-in) devices. Bug: 264712385 Test: atest VtsHalAudioCoreTargetTest Change-Id: Ia2a47ff96fa62f99ce4ec4a0993ca3fd86f82c9d --- audio/aidl/default/Stream.cpp | 12 +++- audio/aidl/default/alsa/StreamAlsa.cpp | 59 +++++++++++-------- audio/aidl/default/alsa/Utils.cpp | 54 ++++++++++++++++- audio/aidl/default/alsa/Utils.h | 5 ++ audio/aidl/default/include/core-impl/Stream.h | 1 + .../default/include/core-impl/StreamAlsa.h | 6 +- .../default/include/core-impl/StreamUsb.h | 3 - audio/aidl/default/usb/StreamUsb.cpp | 17 +----- 8 files changed, 109 insertions(+), 48 deletions(-) diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp index 215de94a31..470b65b749 100644 --- a/audio/aidl/default/Stream.cpp +++ b/audio/aidl/default/Stream.cpp @@ -47,13 +47,19 @@ void StreamContext::fillDescriptor(StreamDescriptor* desc) { desc->reply = mReplyMQ->dupeDesc(); } if (mDataMQ) { - const size_t frameSize = getFrameSize(); - desc->frameSizeBytes = frameSize; - desc->bufferSizeFrames = mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() / frameSize; + desc->frameSizeBytes = getFrameSize(); + desc->bufferSizeFrames = getBufferSizeInFrames(); desc->audio.set(mDataMQ->dupeDesc()); } } +size_t StreamContext::getBufferSizeInFrames() const { + if (mDataMQ) { + return mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() / getFrameSize(); + } + return 0; +} + size_t StreamContext::getFrameSize() const { return getFrameSizeInBytes(mFormat, mChannelLayout); } diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp index 17c7febdd1..bdbe5733b9 100644 --- a/audio/aidl/default/alsa/StreamAlsa.cpp +++ b/audio/aidl/default/alsa/StreamAlsa.cpp @@ -27,16 +27,32 @@ namespace aidl::android::hardware::audio::core { -StreamAlsa::StreamAlsa(const Metadata& metadata, StreamContext&& context) +StreamAlsa::StreamAlsa(const Metadata& metadata, StreamContext&& context, int readWriteRetries) : StreamCommonImpl(metadata, std::move(context)), mFrameSizeBytes(getContext().getFrameSize()), mIsInput(isInput(metadata)), - mConfig(alsa::getPcmConfig(getContext(), mIsInput)) {} + mConfig(alsa::getPcmConfig(getContext(), mIsInput)), + mReadWriteRetries(readWriteRetries) {} ::android::status_t StreamAlsa::init() { return mConfig.has_value() ? ::android::OK : ::android::NO_INIT; } +::android::status_t StreamAlsa::drain(StreamDescriptor::DrainMode) { + usleep(1000); + return ::android::OK; +} + +::android::status_t StreamAlsa::flush() { + usleep(1000); + return ::android::OK; +} + +::android::status_t StreamAlsa::pause() { + usleep(1000); + return ::android::OK; +} + ::android::status_t StreamAlsa::standby() { mAlsaDeviceProxies.clear(); return ::android::OK; @@ -45,27 +61,21 @@ StreamAlsa::StreamAlsa(const Metadata& metadata, StreamContext&& context) ::android::status_t StreamAlsa::start() { decltype(mAlsaDeviceProxies) alsaDeviceProxies; for (const auto& device : getDeviceProfiles()) { - auto profile = alsa::readAlsaDeviceInfo(device); - if (!profile.has_value()) { - LOG(ERROR) << __func__ << ": unable to read device info, device address=" << device; - return ::android::UNKNOWN_ERROR; + alsa::DeviceProxy proxy; + if (device.isExternal) { + // Always ask alsa configure as required since the configuration should be supported + // by the connected device. That is guaranteed by `setAudioPortConfig` and + // `setAudioPatch`. + proxy = alsa::openProxyForExternalDevice( + device, const_cast(&mConfig.value()), + true /*require_exact_match*/); + } else { + proxy = alsa::openProxyForAttachedDevice( + device, const_cast(&mConfig.value()), + getContext().getBufferSizeInFrames()); } - - auto proxy = alsa::makeDeviceProxy(); - // Always ask for alsa configure as required since the configuration should be supported - // by the connected device. That is guaranteed by `setAudioPortConfig` and `setAudioPatch`. - if (int err = proxy_prepare(proxy.get(), &profile.value(), - const_cast(&mConfig.value()), - true /*require_exact_match*/); - err != 0) { - LOG(ERROR) << __func__ << ": fail to prepare for device address=" << device - << " error=" << err; - return ::android::UNKNOWN_ERROR; - } - if (int err = proxy_open(proxy.get()); err != 0) { - LOG(ERROR) << __func__ << ": failed to open device, address=" << device - << " error=" << err; - return ::android::UNKNOWN_ERROR; + if (!proxy) { + return ::android::NO_INIT; } alsaDeviceProxies.push_back(std::move(proxy)); } @@ -83,11 +93,12 @@ StreamAlsa::StreamAlsa(const Metadata& metadata, StreamContext&& context) return ::android::NO_INIT; } // For input case, only support single device. - proxy_read(mAlsaDeviceProxies[0].get(), buffer, bytesToTransfer); + proxy_read_with_retries(mAlsaDeviceProxies[0].get(), buffer, bytesToTransfer, + mReadWriteRetries); maxLatency = proxy_get_latency(mAlsaDeviceProxies[0].get()); } else { for (auto& proxy : mAlsaDeviceProxies) { - proxy_write(proxy.get(), buffer, bytesToTransfer); + proxy_write_with_retries(proxy.get(), buffer, bytesToTransfer, mReadWriteRetries); maxLatency = std::max(maxLatency, proxy_get_latency(proxy.get())); } } diff --git a/audio/aidl/default/alsa/Utils.cpp b/audio/aidl/default/alsa/Utils.cpp index 162f8529cf..20f77978fd 100644 --- a/audio/aidl/default/alsa/Utils.cpp +++ b/audio/aidl/default/alsa/Utils.cpp @@ -217,7 +217,8 @@ std::optional getDeviceProfile( } return DeviceProfile{.card = alsaAddress[0], .device = alsaAddress[1], - .direction = isInput ? PCM_IN : PCM_OUT}; + .direction = isInput ? PCM_IN : PCM_OUT, + .isExternal = !audioDevice.type.connection.empty()}; } std::optional getDeviceProfile( @@ -269,6 +270,57 @@ DeviceProxy makeDeviceProxy() { }); } +DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile, + struct pcm_config* pcmConfig, size_t bufferFrameCount) { + if (deviceProfile.isExternal) { + LOG(FATAL) << __func__ << ": called for an external device, address=" << deviceProfile; + } + alsa_device_profile profile; + profile_init(&profile, deviceProfile.direction); + profile.card = deviceProfile.card; + profile.device = deviceProfile.device; + if (!profile_fill_builtin_device_info(&profile, pcmConfig, bufferFrameCount)) { + LOG(FATAL) << __func__ << ": failed to init for built-in device, address=" << deviceProfile; + } + auto proxy = makeDeviceProxy(); + if (int err = proxy_prepare_from_default_config(proxy.get(), &profile); err != 0) { + LOG(FATAL) << __func__ << ": fail to prepare for device address=" << deviceProfile + << " error=" << err; + return nullptr; + } + if (int err = proxy_open(proxy.get()); err != 0) { + LOG(ERROR) << __func__ << ": failed to open device, address=" << deviceProfile + << " error=" << err; + return nullptr; + } + return proxy; +} + +DeviceProxy openProxyForExternalDevice(const DeviceProfile& deviceProfile, + struct pcm_config* pcmConfig, bool requireExactMatch) { + if (!deviceProfile.isExternal) { + LOG(FATAL) << __func__ << ": called for an attached device, address=" << deviceProfile; + } + auto profile = readAlsaDeviceInfo(deviceProfile); + if (!profile.has_value()) { + LOG(ERROR) << __func__ << ": unable to read device info, device address=" << deviceProfile; + return nullptr; + } + auto proxy = makeDeviceProxy(); + if (int err = proxy_prepare(proxy.get(), &profile.value(), pcmConfig, requireExactMatch); + err != 0) { + LOG(ERROR) << __func__ << ": fail to prepare for device address=" << deviceProfile + << " error=" << err; + return nullptr; + } + if (int err = proxy_open(proxy.get()); err != 0) { + LOG(ERROR) << __func__ << ": failed to open device, address=" << deviceProfile + << " error=" << err; + return nullptr; + } + return proxy; +} + std::optional readAlsaDeviceInfo(const DeviceProfile& deviceProfile) { alsa_device_profile profile; profile_init(&profile, deviceProfile.direction); diff --git a/audio/aidl/default/alsa/Utils.h b/audio/aidl/default/alsa/Utils.h index c1b9b380c0..615e657064 100644 --- a/audio/aidl/default/alsa/Utils.h +++ b/audio/aidl/default/alsa/Utils.h @@ -40,6 +40,7 @@ struct DeviceProfile { int card; int device; int direction; /* PCM_OUT or PCM_IN */ + bool isExternal; }; std::ostream& operator<<(std::ostream& os, const DeviceProfile& device); using DeviceProxyDeleter = std::function; @@ -60,6 +61,10 @@ std::optional getDeviceProfile( std::optional getPcmConfig(const StreamContext& context, bool isInput); std::vector getSampleRatesFromProfile(const alsa_device_profile* profile); DeviceProxy makeDeviceProxy(); +DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile, + struct pcm_config* pcmConfig, size_t bufferFrameCount); +DeviceProxy openProxyForExternalDevice(const DeviceProfile& deviceProfile, + struct pcm_config* pcmConfig, bool requireExactMatch); std::optional readAlsaDeviceInfo(const DeviceProfile& deviceProfile); ::aidl::android::media::audio::common::AudioFormatDescription diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h index e64c578b68..a1bc9b4b85 100644 --- a/audio/aidl/default/include/core-impl/Stream.h +++ b/audio/aidl/default/include/core-impl/Stream.h @@ -132,6 +132,7 @@ class StreamContext { void fillDescriptor(StreamDescriptor* desc); std::shared_ptr getAsyncCallback() const { return mAsyncCallback; } + size_t getBufferSizeInFrames() const; ::aidl::android::media::audio::common::AudioChannelLayout getChannelLayout() const { return mChannelLayout; } diff --git a/audio/aidl/default/include/core-impl/StreamAlsa.h b/audio/aidl/default/include/core-impl/StreamAlsa.h index 5744d665f3..700573f1da 100644 --- a/audio/aidl/default/include/core-impl/StreamAlsa.h +++ b/audio/aidl/default/include/core-impl/StreamAlsa.h @@ -31,9 +31,12 @@ namespace aidl::android::hardware::audio::core { // provide necessary overrides for all interface methods omitted here. class StreamAlsa : public StreamCommonImpl { public: - StreamAlsa(const Metadata& metadata, StreamContext&& context); + StreamAlsa(const Metadata& metadata, StreamContext&& context, int readWriteRetries); // 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, @@ -48,6 +51,7 @@ class StreamAlsa : public StreamCommonImpl { const size_t mFrameSizeBytes; const bool mIsInput; const std::optional mConfig; + const int mReadWriteRetries; // All fields below are only used on the worker thread. std::vector mAlsaDeviceProxies; }; diff --git a/audio/aidl/default/include/core-impl/StreamUsb.h b/audio/aidl/default/include/core-impl/StreamUsb.h index 44f742a4dd..0189b6b7ed 100644 --- a/audio/aidl/default/include/core-impl/StreamUsb.h +++ b/audio/aidl/default/include/core-impl/StreamUsb.h @@ -30,9 +30,6 @@ class StreamUsb : public StreamAlsa { public: StreamUsb(const Metadata& metadata, StreamContext&& context); // Methods of 'DriverInterface'. - ::android::status_t drain(StreamDescriptor::DrainMode) override; - ::android::status_t flush() override; - ::android::status_t pause() override; ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount, int32_t* latencyMs) override; diff --git a/audio/aidl/default/usb/StreamUsb.cpp b/audio/aidl/default/usb/StreamUsb.cpp index da0ad11be2..f6642450c8 100644 --- a/audio/aidl/default/usb/StreamUsb.cpp +++ b/audio/aidl/default/usb/StreamUsb.cpp @@ -36,7 +36,7 @@ using aidl::android::media::audio::common::MicrophoneInfo; namespace aidl::android::hardware::audio::core { StreamUsb::StreamUsb(const Metadata& metadata, StreamContext&& context) - : StreamAlsa(metadata, std::move(context)) {} + : StreamAlsa(metadata, std::move(context), 1 /*readWriteRetries*/) {} ndk::ScopedAStatus StreamUsb::setConnectedDevices( const std::vector& connectedDevices) { @@ -62,21 +62,6 @@ ndk::ScopedAStatus StreamUsb::setConnectedDevices( return ndk::ScopedAStatus::ok(); } -::android::status_t StreamUsb::drain(StreamDescriptor::DrainMode) { - usleep(1000); - return ::android::OK; -} - -::android::status_t StreamUsb::flush() { - usleep(1000); - return ::android::OK; -} - -::android::status_t StreamUsb::pause() { - usleep(1000); - return ::android::OK; -} - ::android::status_t StreamUsb::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount, int32_t* latencyMs) { if (mConnectedDevicesUpdated.load(std::memory_order_acquire)) { From 2eabaf995ba70c296ea30df9f30f9a03bf2b3910 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Wed, 19 Jul 2023 14:28:47 -0700 Subject: [PATCH 3/4] audio: Use ChildInterface in StreamCommonImpl Replace the pair of 'shared_ptr<>, Binder' with the equivalent ChildInterface. Fix logging of returned sub-objects to print their Binder value instead of the local pointer. Bug: 264712385 Test: m Change-Id: I1350e7b3720c6244cd8527e1d021ee9577399291 --- audio/aidl/default/ModulePrimary.cpp | 3 ++- audio/aidl/default/Stream.cpp | 6 ++---- audio/aidl/default/include/core-impl/Stream.h | 4 ++-- audio/aidl/default/stub/ModuleStub.cpp | 9 ++++++--- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/audio/aidl/default/ModulePrimary.cpp b/audio/aidl/default/ModulePrimary.cpp index cbb6730372..f66da373f9 100644 --- a/audio/aidl/default/ModulePrimary.cpp +++ b/audio/aidl/default/ModulePrimary.cpp @@ -38,7 +38,8 @@ ndk::ScopedAStatus ModulePrimary::getTelephony(std::shared_ptr* _aid mTelephony = ndk::SharedRefBase::make(); } *_aidl_return = mTelephony.getPtr(); - LOG(DEBUG) << __func__ << ": returning instance of ITelephony: " << _aidl_return->get(); + LOG(DEBUG) << __func__ + << ": returning instance of ITelephony: " << _aidl_return->get()->asBinder().get(); return ndk::ScopedAStatus::ok(); } diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp index 470b65b749..b11edff8e4 100644 --- a/audio/aidl/default/Stream.cpp +++ b/audio/aidl/default/Stream.cpp @@ -603,18 +603,16 @@ StreamCommonImpl::~StreamCommonImpl() { ndk::ScopedAStatus StreamCommonImpl::initInstance( const std::shared_ptr& delegate) { mCommon = ndk::SharedRefBase::make(delegate); - mCommonBinder = mCommon->asBinder(); - AIBinder_setMinSchedulerPolicy(mCommonBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO); return mWorker->start() ? ndk::ScopedAStatus::ok() : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } ndk::ScopedAStatus StreamCommonImpl::getStreamCommonCommon( std::shared_ptr* _aidl_return) { - if (mCommon == nullptr) { + if (!mCommon) { LOG(FATAL) << __func__ << ": the common interface was not created"; } - *_aidl_return = mCommon; + *_aidl_return = mCommon.getPtr(); LOG(DEBUG) << __func__ << ": returning " << _aidl_return->get()->asBinder().get(); return ndk::ScopedAStatus::ok(); } diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h index a1bc9b4b85..b65efb26f2 100644 --- a/audio/aidl/default/include/core-impl/Stream.h +++ b/audio/aidl/default/include/core-impl/Stream.h @@ -43,6 +43,7 @@ #include #include +#include "core-impl/ChildInterface.h" #include "core-impl/utils.h" namespace aidl::android::hardware::audio::core { @@ -466,8 +467,7 @@ class StreamCommonImpl : virtual public StreamCommonInterface, virtual public Dr Metadata mMetadata; StreamContext mContext; std::unique_ptr mWorker; - std::shared_ptr mCommon; - ndk::SpAIBinder mCommonBinder; + ChildInterface mCommon; ConnectedDevices mConnectedDevices; }; diff --git a/audio/aidl/default/stub/ModuleStub.cpp b/audio/aidl/default/stub/ModuleStub.cpp index a60075221d..72f2241c03 100644 --- a/audio/aidl/default/stub/ModuleStub.cpp +++ b/audio/aidl/default/stub/ModuleStub.cpp @@ -38,7 +38,8 @@ ndk::ScopedAStatus ModuleStub::getBluetooth(std::shared_ptr* _aidl_r mBluetooth = ndk::SharedRefBase::make(); } *_aidl_return = mBluetooth.getPtr(); - LOG(DEBUG) << __func__ << ": returning instance of IBluetooth: " << _aidl_return->get(); + LOG(DEBUG) << __func__ + << ": returning instance of IBluetooth: " << _aidl_return->get()->asBinder().get(); return ndk::ScopedAStatus::ok(); } @@ -47,7 +48,8 @@ ndk::ScopedAStatus ModuleStub::getBluetoothA2dp(std::shared_ptr* mBluetoothA2dp = ndk::SharedRefBase::make(); } *_aidl_return = mBluetoothA2dp.getPtr(); - LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: " << _aidl_return->get(); + LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: " + << _aidl_return->get()->asBinder().get(); return ndk::ScopedAStatus::ok(); } @@ -56,7 +58,8 @@ ndk::ScopedAStatus ModuleStub::getBluetoothLe(std::shared_ptr* _ai mBluetoothLe = ndk::SharedRefBase::make(); } *_aidl_return = mBluetoothLe.getPtr(); - LOG(DEBUG) << __func__ << ": returning instance of IBluetoothLe: " << _aidl_return->get(); + LOG(DEBUG) << __func__ + << ": returning instance of IBluetoothLe: " << _aidl_return->get()->asBinder().get(); return ndk::ScopedAStatus::ok(); } From 6ddefdbcdf24f28d3477f29adf0bd57d1be04195 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Wed, 19 Jul 2023 17:30:06 -0700 Subject: [PATCH 4/4] audio: Move StreamContext ownership out from StreamCommonImpl Upcoming implementations of the streams of the primary module will need to change the underlying stream type depending on the current connected device. The stream context must persist, thus its life time must be bound to the IStreamIn/Out implementation. Move the StreamContext instance under ownership of StreamIn/Out. Add StreamCommonImpl::onClose so that the owner of the context may know when it is safe to reset it. Re-arrange the order of the arguments when creating a stream so that the context always comes first. Bug: 264712385 Test: atest VtsHalAudioCoreTargetTest Change-Id: Iaf13d4bc3a53cbfc27264d3abd1f6c417ece3941 --- audio/aidl/default/Module.cpp | 4 +-- audio/aidl/default/ModulePrimary.cpp | 10 +++--- audio/aidl/default/Stream.cpp | 18 +++++++--- audio/aidl/default/alsa/StreamAlsa.cpp | 4 +-- audio/aidl/default/include/core-impl/Module.h | 4 +-- .../default/include/core-impl/ModulePrimary.h | 4 +-- .../include/core-impl/ModuleRemoteSubmix.h | 4 +-- .../default/include/core-impl/ModuleStub.h | 4 +-- .../default/include/core-impl/ModuleUsb.h | 4 +-- audio/aidl/default/include/core-impl/Stream.h | 33 ++++++++++++------- .../default/include/core-impl/StreamAlsa.h | 2 +- .../include/core-impl/StreamRemoteSubmix.h | 14 +++++--- .../default/include/core-impl/StreamStub.h | 18 ++++++---- .../default/include/core-impl/StreamUsb.h | 14 ++++---- .../default/r_submix/ModuleRemoteSubmix.cpp | 8 ++--- .../default/r_submix/StreamRemoteSubmix.cpp | 18 +++++----- audio/aidl/default/stub/ModuleStub.cpp | 10 +++--- audio/aidl/default/stub/StreamStub.cpp | 12 +++---- audio/aidl/default/usb/ModuleUsb.cpp | 12 +++---- audio/aidl/default/usb/StreamUsb.cpp | 16 ++++----- 20 files changed, 122 insertions(+), 91 deletions(-) diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp index 12bbbb0cba..bf8b01aaaa 100644 --- a/audio/aidl/default/Module.cpp +++ b/audio/aidl/default/Module.cpp @@ -669,7 +669,7 @@ ndk::ScopedAStatus Module::openInputStream(const OpenInputStreamArguments& in_ar nullptr, nullptr, &context)); context.fillDescriptor(&_aidl_return->desc); std::shared_ptr stream; - RETURN_STATUS_IF_ERROR(createInputStream(in_args.sinkMetadata, std::move(context), + RETURN_STATUS_IF_ERROR(createInputStream(std::move(context), in_args.sinkMetadata, mConfig->microphones, &stream)); StreamWrapper streamWrapper(stream); if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) { @@ -715,7 +715,7 @@ ndk::ScopedAStatus Module::openOutputStream(const OpenOutputStreamArguments& in_ in_args.eventCallback, &context)); context.fillDescriptor(&_aidl_return->desc); std::shared_ptr stream; - RETURN_STATUS_IF_ERROR(createOutputStream(in_args.sourceMetadata, std::move(context), + RETURN_STATUS_IF_ERROR(createOutputStream(std::move(context), in_args.sourceMetadata, in_args.offloadInfo, &stream)); StreamWrapper streamWrapper(stream); if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) { diff --git a/audio/aidl/default/ModulePrimary.cpp b/audio/aidl/default/ModulePrimary.cpp index f66da373f9..d8ea9e7731 100644 --- a/audio/aidl/default/ModulePrimary.cpp +++ b/audio/aidl/default/ModulePrimary.cpp @@ -43,18 +43,18 @@ ndk::ScopedAStatus ModulePrimary::getTelephony(std::shared_ptr* _aid return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus ModulePrimary::createInputStream(const SinkMetadata& sinkMetadata, - StreamContext&& context, +ndk::ScopedAStatus ModulePrimary::createInputStream(StreamContext&& context, + const SinkMetadata& sinkMetadata, const std::vector& microphones, std::shared_ptr* result) { - return createStreamInstance(result, sinkMetadata, std::move(context), + return createStreamInstance(result, std::move(context), sinkMetadata, microphones); } ndk::ScopedAStatus ModulePrimary::createOutputStream( - const SourceMetadata& sourceMetadata, StreamContext&& context, + StreamContext&& context, const SourceMetadata& sourceMetadata, const std::optional& offloadInfo, std::shared_ptr* result) { - return createStreamInstance(result, sourceMetadata, std::move(context), + return createStreamInstance(result, std::move(context), sourceMetadata, offloadInfo); } diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp index b11edff8e4..f4194d23c1 100644 --- a/audio/aidl/default/Stream.cpp +++ b/audio/aidl/default/Stream.cpp @@ -663,7 +663,7 @@ ndk::ScopedAStatus StreamCommonImpl::close() { LOG(DEBUG) << __func__ << ": joining the worker thread..."; mWorker->stop(); LOG(DEBUG) << __func__ << ": worker thread joined"; - mContext.reset(); + onClose(); mWorker->setClosed(); return ndk::ScopedAStatus::ok(); } else { @@ -727,11 +727,15 @@ static std::map transformMicrophones( } } // namespace -StreamIn::StreamIn(const std::vector& microphones) - : mMicrophones(transformMicrophones(microphones)) { +StreamIn::StreamIn(StreamContext&& context, const std::vector& microphones) + : mContext(std::move(context)), mMicrophones(transformMicrophones(microphones)) { LOG(DEBUG) << __func__; } +void StreamIn::defaultOnClose() { + mContext.reset(); +} + ndk::ScopedAStatus StreamIn::getActiveMicrophones( std::vector* _aidl_return) { std::vector result; @@ -784,11 +788,15 @@ ndk::ScopedAStatus StreamIn::setHwGain(const std::vector& in_channelGains return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } -StreamOut::StreamOut(const std::optional& offloadInfo) - : mOffloadInfo(offloadInfo) { +StreamOut::StreamOut(StreamContext&& context, const std::optional& offloadInfo) + : mContext(std::move(context)), mOffloadInfo(offloadInfo) { LOG(DEBUG) << __func__; } +void StreamOut::defaultOnClose() { + mContext.reset(); +} + ndk::ScopedAStatus StreamOut::updateOffloadMetadata( const AudioOffloadMetadata& in_offloadMetadata) { LOG(DEBUG) << __func__; diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp index bdbe5733b9..c7fb02248a 100644 --- a/audio/aidl/default/alsa/StreamAlsa.cpp +++ b/audio/aidl/default/alsa/StreamAlsa.cpp @@ -27,8 +27,8 @@ namespace aidl::android::hardware::audio::core { -StreamAlsa::StreamAlsa(const Metadata& metadata, StreamContext&& context, int readWriteRetries) - : StreamCommonImpl(metadata, std::move(context)), +StreamAlsa::StreamAlsa(const StreamContext& context, const Metadata& metadata, int readWriteRetries) + : StreamCommonImpl(context, metadata), mFrameSizeBytes(getContext().getFrameSize()), mIsInput(isInput(metadata)), mConfig(alsa::getPcmConfig(getContext(), mIsInput)), diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h index ee0458be49..2de7d0f393 100644 --- a/audio/aidl/default/include/core-impl/Module.h +++ b/audio/aidl/default/include/core-impl/Module.h @@ -159,13 +159,13 @@ class Module : public BnModule { // The following virtual functions are intended for vendor extension via inheritance. virtual ndk::ScopedAStatus createInputStream( - const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones, std::shared_ptr* result) = 0; virtual ndk::ScopedAStatus createOutputStream( - const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>& offloadInfo, std::shared_ptr* result) = 0; diff --git a/audio/aidl/default/include/core-impl/ModulePrimary.h b/audio/aidl/default/include/core-impl/ModulePrimary.h index bc808ab03d..6264237fe3 100644 --- a/audio/aidl/default/include/core-impl/ModulePrimary.h +++ b/audio/aidl/default/include/core-impl/ModulePrimary.h @@ -28,13 +28,13 @@ class ModulePrimary final : public Module { ndk::ScopedAStatus getTelephony(std::shared_ptr* _aidl_return) override; ndk::ScopedAStatus createInputStream( - const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones, std::shared_ptr* result) override; ndk::ScopedAStatus createOutputStream( - const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>& offloadInfo, std::shared_ptr* result) override; diff --git a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h index ccfcdd9462..e87be3d9d2 100644 --- a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h +++ b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h @@ -33,13 +33,13 @@ class ModuleRemoteSubmix : public Module { // Module interfaces ndk::ScopedAStatus createInputStream( - const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones, std::shared_ptr* result) override; ndk::ScopedAStatus createOutputStream( - const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>& offloadInfo, std::shared_ptr* result) override; diff --git a/audio/aidl/default/include/core-impl/ModuleStub.h b/audio/aidl/default/include/core-impl/ModuleStub.h index 59c343f4b7..4f771611ab 100644 --- a/audio/aidl/default/include/core-impl/ModuleStub.h +++ b/audio/aidl/default/include/core-impl/ModuleStub.h @@ -30,13 +30,13 @@ class ModuleStub final : public Module { ndk::ScopedAStatus getBluetoothLe(std::shared_ptr* _aidl_return) override; ndk::ScopedAStatus createInputStream( - const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones, std::shared_ptr* result) override; ndk::ScopedAStatus createOutputStream( - const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>& offloadInfo, std::shared_ptr* result) override; diff --git a/audio/aidl/default/include/core-impl/ModuleUsb.h b/audio/aidl/default/include/core-impl/ModuleUsb.h index e6b3e66e41..a296b8c042 100644 --- a/audio/aidl/default/include/core-impl/ModuleUsb.h +++ b/audio/aidl/default/include/core-impl/ModuleUsb.h @@ -33,13 +33,13 @@ class ModuleUsb final : public ModuleAlsa { // Module interfaces ndk::ScopedAStatus createInputStream( - const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones, std::shared_ptr* result) override; ndk::ScopedAStatus createOutputStream( - const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>& offloadInfo, std::shared_ptr* result) override; diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h index b65efb26f2..355d3b4cb8 100644 --- a/audio/aidl/default/include/core-impl/Stream.h +++ b/audio/aidl/default/include/core-impl/Stream.h @@ -411,16 +411,17 @@ class StreamCommonDelegator : public BnStreamCommon { }; // The implementation of DriverInterface must be provided by each concrete stream implementation. +// Note that StreamCommonImpl does not own the context. This is to support swapping on the fly +// implementations of the stream while keeping the same IStreamIn/Out instance. It's that instance +// who must be owner of the context. class StreamCommonImpl : virtual public StreamCommonInterface, virtual public DriverInterface { public: - StreamCommonImpl(const Metadata& metadata, StreamContext&& context, + StreamCommonImpl(const StreamContext& context, const Metadata& metadata, const StreamWorkerInterface::CreateInstance& createWorker) - : mMetadata(metadata), - mContext(std::move(context)), - mWorker(createWorker(mContext, this)) {} - StreamCommonImpl(const Metadata& metadata, StreamContext&& context) + : mContext(context), mMetadata(metadata), mWorker(createWorker(mContext, this)) {} + StreamCommonImpl(const StreamContext& context, const Metadata& metadata) : StreamCommonImpl( - metadata, std::move(context), + context, metadata, isInput(metadata) ? getDefaultInWorkerCreator() : getDefaultOutWorkerCreator()) {} ~StreamCommonImpl(); @@ -462,10 +463,11 @@ class StreamCommonImpl : virtual public StreamCommonInterface, virtual public Dr }; } + virtual void onClose() = 0; void stopWorker(); + const StreamContext& mContext; Metadata mMetadata; - StreamContext mContext; std::unique_ptr mWorker; ChildInterface mCommon; ConnectedDevices mConnectedDevices; @@ -475,6 +477,8 @@ class StreamCommonImpl : virtual public StreamCommonInterface, virtual public Dr // concrete input/output stream implementations. class StreamIn : virtual public StreamCommonInterface, public BnStreamIn { protected: + void defaultOnClose(); + ndk::ScopedAStatus getStreamCommon(std::shared_ptr* _aidl_return) override { return getStreamCommonCommon(_aidl_return); } @@ -494,14 +498,17 @@ class StreamIn : virtual public StreamCommonInterface, public BnStreamIn { friend class ndk::SharedRefBase; - explicit StreamIn( - const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones); + StreamIn(StreamContext&& context, + const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones); + StreamContext mContext; const std::map<::aidl::android::media::audio::common::AudioDevice, std::string> mMicrophones; }; class StreamOut : virtual public StreamCommonInterface, public BnStreamOut { protected: + void defaultOnClose(); + ndk::ScopedAStatus getStreamCommon(std::shared_ptr* _aidl_return) override { return getStreamCommonCommon(_aidl_return); } @@ -535,10 +542,12 @@ class StreamOut : virtual public StreamCommonInterface, public BnStreamOut { friend class ndk::SharedRefBase; - explicit StreamOut(const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>& - offloadInfo); + StreamOut(StreamContext&& context, + const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>& + offloadInfo); - std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo; + StreamContext mContext; + const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo; std::optional<::aidl::android::hardware::audio::common::AudioOffloadMetadata> mOffloadMetadata; }; diff --git a/audio/aidl/default/include/core-impl/StreamAlsa.h b/audio/aidl/default/include/core-impl/StreamAlsa.h index 700573f1da..90d2e36df7 100644 --- a/audio/aidl/default/include/core-impl/StreamAlsa.h +++ b/audio/aidl/default/include/core-impl/StreamAlsa.h @@ -31,7 +31,7 @@ namespace aidl::android::hardware::audio::core { // provide necessary overrides for all interface methods omitted here. class StreamAlsa : public StreamCommonImpl { public: - StreamAlsa(const Metadata& metadata, StreamContext&& context, int readWriteRetries); + StreamAlsa(const StreamContext& context, const Metadata& metadata, int readWriteRetries); // Methods of 'DriverInterface'. ::android::status_t init() override; ::android::status_t drain(StreamDescriptor::DrainMode) override; diff --git a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h index 1bca910995..4c984afff9 100644 --- a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h +++ b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h @@ -29,7 +29,7 @@ using aidl::android::hardware::audio::core::r_submix::SubmixRoute; class StreamRemoteSubmix : public StreamCommonImpl { public: - StreamRemoteSubmix(const Metadata& metadata, StreamContext&& context); + StreamRemoteSubmix(const StreamContext& context, const Metadata& metadata); ::android::status_t init() override; ::android::status_t drain(StreamDescriptor::DrainMode) override; @@ -72,28 +72,32 @@ class StreamRemoteSubmix : public StreamCommonImpl { static constexpr int kReadAttemptSleepUs = 5000; }; -class StreamInRemoteSubmix final : public StreamRemoteSubmix, public StreamIn { +class StreamInRemoteSubmix final : public StreamIn, public StreamRemoteSubmix { public: friend class ndk::SharedRefBase; StreamInRemoteSubmix( - const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones); private: + void onClose() override { defaultOnClose(); } ndk::ScopedAStatus getActiveMicrophones( std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return) override; }; -class StreamOutRemoteSubmix final : public StreamRemoteSubmix, public StreamOut { +class StreamOutRemoteSubmix final : public StreamOut, public StreamRemoteSubmix { public: friend class ndk::SharedRefBase; StreamOutRemoteSubmix( - const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>& offloadInfo); + + private: + void onClose() override { defaultOnClose(); } }; } // 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 6b1b2ddc89..2a92deb07c 100644 --- a/audio/aidl/default/include/core-impl/StreamStub.h +++ b/audio/aidl/default/include/core-impl/StreamStub.h @@ -22,7 +22,7 @@ namespace aidl::android::hardware::audio::core { class StreamStub : public StreamCommonImpl { public: - StreamStub(const Metadata& metadata, StreamContext&& context); + StreamStub(const StreamContext& context, const Metadata& metadata); // Methods of 'DriverInterface'. ::android::status_t init() override; ::android::status_t drain(StreamDescriptor::DrainMode) override; @@ -43,22 +43,28 @@ class StreamStub : public StreamCommonImpl { bool mIsStandby = true; // Used for validating the state machine logic. }; -class StreamInStub final : public StreamStub, public StreamIn { +class StreamInStub final : public StreamIn, public StreamStub { public: friend class ndk::SharedRefBase; StreamInStub( - const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones); + + private: + void onClose() override { defaultOnClose(); } }; -class StreamOutStub final : public StreamStub, public StreamOut { +class StreamOutStub final : public StreamOut, public StreamStub { public: friend class ndk::SharedRefBase; - StreamOutStub(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, - StreamContext&& context, + StreamOutStub(StreamContext&& context, + const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>& offloadInfo); + + private: + void onClose() override { defaultOnClose(); } }; } // namespace aidl::android::hardware::audio::core diff --git a/audio/aidl/default/include/core-impl/StreamUsb.h b/audio/aidl/default/include/core-impl/StreamUsb.h index 0189b6b7ed..7dc7296399 100644 --- a/audio/aidl/default/include/core-impl/StreamUsb.h +++ b/audio/aidl/default/include/core-impl/StreamUsb.h @@ -28,7 +28,7 @@ namespace aidl::android::hardware::audio::core { class StreamUsb : public StreamAlsa { public: - StreamUsb(const Metadata& metadata, StreamContext&& context); + StreamUsb(const StreamContext& context, const Metadata& metadata); // Methods of 'DriverInterface'. ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount, int32_t* latencyMs) override; @@ -44,29 +44,31 @@ class StreamUsb : public StreamAlsa { std::atomic mConnectedDevicesUpdated = false; }; -class StreamInUsb final : public StreamUsb, public StreamIn { +class StreamInUsb final : public StreamIn, public StreamUsb { public: friend class ndk::SharedRefBase; StreamInUsb( - const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, StreamContext&& context, + const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata, const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones); private: + void onClose() override { defaultOnClose(); } ndk::ScopedAStatus getActiveMicrophones( std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return) override; }; -class StreamOutUsb final : public StreamUsb, public StreamOut { +class StreamOutUsb final : public StreamOut, public StreamUsb { public: friend class ndk::SharedRefBase; - StreamOutUsb(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, - StreamContext&& context, + StreamOutUsb(StreamContext&& context, + const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata, const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>& offloadInfo); private: + void onClose() override { defaultOnClose(); } ndk::ScopedAStatus getHwVolume(std::vector* _aidl_return) override; ndk::ScopedAStatus setHwVolume(const std::vector& in_channelVolumes) override; diff --git a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp index 2b79f51117..9be783758d 100644 --- a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp +++ b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp @@ -56,16 +56,16 @@ ndk::ScopedAStatus ModuleRemoteSubmix::setMicMute(bool in_mute __unused) { } ndk::ScopedAStatus ModuleRemoteSubmix::createInputStream( - const SinkMetadata& sinkMetadata, StreamContext&& context, + StreamContext&& context, const SinkMetadata& sinkMetadata, const std::vector& microphones, std::shared_ptr* result) { - return createStreamInstance(result, sinkMetadata, std::move(context), + return createStreamInstance(result, std::move(context), sinkMetadata, microphones); } ndk::ScopedAStatus ModuleRemoteSubmix::createOutputStream( - const SourceMetadata& sourceMetadata, StreamContext&& context, + StreamContext&& context, const SourceMetadata& sourceMetadata, const std::optional& offloadInfo, std::shared_ptr* result) { - return createStreamInstance(result, sourceMetadata, std::move(context), + return createStreamInstance(result, std::move(context), sourceMetadata, offloadInfo); } diff --git a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp index 6d5185b346..53d4aa61ab 100644 --- a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp +++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp @@ -29,8 +29,8 @@ using aidl::android::media::audio::common::MicrophoneInfo; namespace aidl::android::hardware::audio::core { -StreamRemoteSubmix::StreamRemoteSubmix(const Metadata& metadata, StreamContext&& context) - : StreamCommonImpl(metadata, std::move(context)), +StreamRemoteSubmix::StreamRemoteSubmix(const StreamContext& context, const Metadata& metadata) + : StreamCommonImpl(context, metadata), mPortId(context.getPortId()), mIsInput(isInput(metadata)) { mStreamConfig.frameSize = context.getFrameSize(); @@ -353,10 +353,11 @@ size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() { return ::android::OK; } -StreamInRemoteSubmix::StreamInRemoteSubmix(const SinkMetadata& sinkMetadata, - StreamContext&& context, +StreamInRemoteSubmix::StreamInRemoteSubmix(StreamContext&& context, + const SinkMetadata& sinkMetadata, const std::vector& microphones) - : StreamRemoteSubmix(sinkMetadata, std::move(context)), StreamIn(microphones) {} + : StreamIn(std::move(context), microphones), + StreamRemoteSubmix(StreamIn::mContext, sinkMetadata) {} ndk::ScopedAStatus StreamInRemoteSubmix::getActiveMicrophones( std::vector* _aidl_return) { @@ -365,9 +366,10 @@ ndk::ScopedAStatus StreamInRemoteSubmix::getActiveMicrophones( return ndk::ScopedAStatus::ok(); } -StreamOutRemoteSubmix::StreamOutRemoteSubmix(const SourceMetadata& sourceMetadata, - StreamContext&& context, +StreamOutRemoteSubmix::StreamOutRemoteSubmix(StreamContext&& context, + const SourceMetadata& sourceMetadata, const std::optional& offloadInfo) - : StreamRemoteSubmix(sourceMetadata, std::move(context)), StreamOut(offloadInfo) {} + : StreamOut(std::move(context), offloadInfo), + StreamRemoteSubmix(StreamOut::mContext, sourceMetadata) {} } // namespace aidl::android::hardware::audio::core diff --git a/audio/aidl/default/stub/ModuleStub.cpp b/audio/aidl/default/stub/ModuleStub.cpp index 72f2241c03..5e4cd88ff6 100644 --- a/audio/aidl/default/stub/ModuleStub.cpp +++ b/audio/aidl/default/stub/ModuleStub.cpp @@ -63,18 +63,18 @@ ndk::ScopedAStatus ModuleStub::getBluetoothLe(std::shared_ptr* _ai return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus ModuleStub::createInputStream(const SinkMetadata& sinkMetadata, - StreamContext&& context, +ndk::ScopedAStatus ModuleStub::createInputStream(StreamContext&& context, + const SinkMetadata& sinkMetadata, const std::vector& microphones, std::shared_ptr* result) { - return createStreamInstance(result, sinkMetadata, std::move(context), + return createStreamInstance(result, std::move(context), sinkMetadata, microphones); } ndk::ScopedAStatus ModuleStub::createOutputStream( - const SourceMetadata& sourceMetadata, StreamContext&& context, + StreamContext&& context, const SourceMetadata& sourceMetadata, const std::optional& offloadInfo, std::shared_ptr* result) { - return createStreamInstance(result, sourceMetadata, std::move(context), + return createStreamInstance(result, std::move(context), sourceMetadata, offloadInfo); } diff --git a/audio/aidl/default/stub/StreamStub.cpp b/audio/aidl/default/stub/StreamStub.cpp index 2dcf4d4d42..e916fea0fd 100644 --- a/audio/aidl/default/stub/StreamStub.cpp +++ b/audio/aidl/default/stub/StreamStub.cpp @@ -31,8 +31,8 @@ using aidl::android::media::audio::common::MicrophoneInfo; namespace aidl::android::hardware::audio::core { -StreamStub::StreamStub(const Metadata& metadata, StreamContext&& context) - : StreamCommonImpl(metadata, std::move(context)), +StreamStub::StreamStub(const StreamContext& context, const Metadata& metadata) + : StreamCommonImpl(context, metadata), mFrameSizeBytes(getContext().getFrameSize()), mSampleRate(getContext().getSampleRate()), mIsAsynchronous(!!getContext().getAsyncCallback()), @@ -118,12 +118,12 @@ void StreamStub::shutdown() { mIsInitialized = false; } -StreamInStub::StreamInStub(const SinkMetadata& sinkMetadata, StreamContext&& context, +StreamInStub::StreamInStub(StreamContext&& context, const SinkMetadata& sinkMetadata, const std::vector& microphones) - : StreamStub(sinkMetadata, std::move(context)), StreamIn(microphones) {} + : StreamIn(std::move(context), microphones), StreamStub(StreamIn::mContext, sinkMetadata) {} -StreamOutStub::StreamOutStub(const SourceMetadata& sourceMetadata, StreamContext&& context, +StreamOutStub::StreamOutStub(StreamContext&& context, const SourceMetadata& sourceMetadata, const std::optional& offloadInfo) - : StreamStub(sourceMetadata, std::move(context)), StreamOut(offloadInfo) {} + : StreamOut(std::move(context), offloadInfo), StreamStub(StreamOut::mContext, sourceMetadata) {} } // namespace aidl::android::hardware::audio::core diff --git a/audio/aidl/default/usb/ModuleUsb.cpp b/audio/aidl/default/usb/ModuleUsb.cpp index a812e4d3a1..f926e09399 100644 --- a/audio/aidl/default/usb/ModuleUsb.cpp +++ b/audio/aidl/default/usb/ModuleUsb.cpp @@ -68,22 +68,22 @@ ndk::ScopedAStatus ModuleUsb::setMicMute(bool in_mute __unused) { return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } -ndk::ScopedAStatus ModuleUsb::createInputStream(const SinkMetadata& sinkMetadata, - StreamContext&& context, +ndk::ScopedAStatus ModuleUsb::createInputStream(StreamContext&& context, + const SinkMetadata& sinkMetadata, const std::vector& microphones, std::shared_ptr* result) { - return createStreamInstance(result, sinkMetadata, std::move(context), microphones); + return createStreamInstance(result, std::move(context), sinkMetadata, microphones); } -ndk::ScopedAStatus ModuleUsb::createOutputStream(const SourceMetadata& sourceMetadata, - StreamContext&& context, +ndk::ScopedAStatus ModuleUsb::createOutputStream(StreamContext&& context, + const SourceMetadata& sourceMetadata, const std::optional& offloadInfo, std::shared_ptr* result) { if (offloadInfo.has_value()) { LOG(ERROR) << __func__ << ": offload is not supported"; return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } - return createStreamInstance(result, sourceMetadata, std::move(context), + return createStreamInstance(result, std::move(context), sourceMetadata, offloadInfo); } diff --git a/audio/aidl/default/usb/StreamUsb.cpp b/audio/aidl/default/usb/StreamUsb.cpp index f6642450c8..def12e094c 100644 --- a/audio/aidl/default/usb/StreamUsb.cpp +++ b/audio/aidl/default/usb/StreamUsb.cpp @@ -35,8 +35,8 @@ using aidl::android::media::audio::common::MicrophoneInfo; namespace aidl::android::hardware::audio::core { -StreamUsb::StreamUsb(const Metadata& metadata, StreamContext&& context) - : StreamAlsa(metadata, std::move(context), 1 /*readWriteRetries*/) {} +StreamUsb::StreamUsb(const StreamContext& context, const Metadata& metadata) + : StreamAlsa(context, metadata, 1 /*readWriteRetries*/) {} ndk::ScopedAStatus StreamUsb::setConnectedDevices( const std::vector& connectedDevices) { @@ -55,7 +55,7 @@ ndk::ScopedAStatus StreamUsb::setConnectedDevices( } connectedDeviceProfiles.push_back(*profile); } - RETURN_STATUS_IF_ERROR(StreamCommonImpl::setConnectedDevices(connectedDevices)); + RETURN_STATUS_IF_ERROR(setConnectedDevices(connectedDevices)); std::lock_guard guard(mLock); mConnectedDeviceProfiles = std::move(connectedDeviceProfiles); mConnectedDevicesUpdated.store(true, std::memory_order_release); @@ -83,9 +83,9 @@ std::vector StreamUsb::getDeviceProfiles() { return connectedDevices; } -StreamInUsb::StreamInUsb(const SinkMetadata& sinkMetadata, StreamContext&& context, +StreamInUsb::StreamInUsb(StreamContext&& context, const SinkMetadata& sinkMetadata, const std::vector& microphones) - : StreamUsb(sinkMetadata, std::move(context)), StreamIn(microphones) {} + : StreamIn(std::move(context), microphones), StreamUsb(StreamIn::mContext, sinkMetadata) {} ndk::ScopedAStatus StreamInUsb::getActiveMicrophones( std::vector* _aidl_return __unused) { @@ -93,10 +93,10 @@ ndk::ScopedAStatus StreamInUsb::getActiveMicrophones( return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } -StreamOutUsb::StreamOutUsb(const SourceMetadata& sourceMetadata, StreamContext&& context, +StreamOutUsb::StreamOutUsb(StreamContext&& context, const SourceMetadata& sourceMetadata, const std::optional& offloadInfo) - : StreamUsb(sourceMetadata, std::move(context)), - StreamOut(offloadInfo), + : StreamOut(std::move(context), offloadInfo), + StreamUsb(StreamOut::mContext, sourceMetadata), mChannelCount(getChannelCount(getContext().getChannelLayout())) {} ndk::ScopedAStatus StreamOutUsb::getHwVolume(std::vector* _aidl_return) {