diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp index 5478633d02..eb9cbc3445 100644 --- a/audio/aidl/default/Module.cpp +++ b/audio/aidl/default/Module.cpp @@ -675,7 +675,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()) { @@ -721,7 +721,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 cbb6730372..d8ea9e7731 100644 --- a/audio/aidl/default/ModulePrimary.cpp +++ b/audio/aidl/default/ModulePrimary.cpp @@ -38,22 +38,23 @@ 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(); } -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 215de94a31..f4194d23c1 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); } @@ -597,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(); } @@ -659,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 { @@ -723,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; @@ -780,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/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/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp index 17c7febdd1..c7fb02248a 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) - : 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)) {} + 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/Module.h b/audio/aidl/default/include/core-impl/Module.h index 294cc0e7b9..539221d5d2 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 e64c578b68..355d3b4cb8 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 { @@ -132,6 +133,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; } @@ -409,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(); @@ -460,13 +463,13 @@ 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; - std::shared_ptr mCommon; - ndk::SpAIBinder mCommonBinder; + ChildInterface mCommon; ConnectedDevices mConnectedDevices; }; @@ -474,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); } @@ -493,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); } @@ -534,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 5744d665f3..90d2e36df7 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 StreamContext& context, const Metadata& metadata, 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/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 44f742a4dd..7dc7296399 100644 --- a/audio/aidl/default/include/core-impl/StreamUsb.h +++ b/audio/aidl/default/include/core-impl/StreamUsb.h @@ -28,11 +28,8 @@ 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 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; @@ -47,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 a60075221d..5e4cd88ff6 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,22 +58,23 @@ 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(); } -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 da0ad11be2..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)) {} +StreamUsb::StreamUsb(const StreamContext& context, const Metadata& metadata) + : StreamAlsa(context, metadata, 1 /*readWriteRetries*/) {} ndk::ScopedAStatus StreamUsb::setConnectedDevices( const std::vector& connectedDevices) { @@ -55,28 +55,13 @@ 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); 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)) { @@ -98,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) { @@ -108,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) { 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);