From 29e51689d8222618fb7c8364c83bb261ffda9efa Mon Sep 17 00:00:00 2001 From: Weilin Xu Date: Wed, 2 Oct 2024 17:16:32 +0000 Subject: [PATCH] Support multiple output devices in refrence audio HAL Parsed card id and device id from output bus device address, and used them to write output data into corresponding PCM devices in stream alsa. Bug: 336370745 Test: atest VtsHalAudioCoreTargetTest (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4d71bd736be6f52a9e954dd518be0b6ece3ddc1b) Merged-In: I18efa2d1aea233375906efc0aa9c93c8f3b464e8 Change-Id: I18efa2d1aea233375906efc0aa9c93c8f3b464e8 --- audio/aidl/default/alsa/StreamAlsa.cpp | 7 +++ .../default/include/core-impl/StreamPrimary.h | 8 ++- audio/aidl/default/primary/StreamPrimary.cpp | 49 +++++++++++++------ 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp index f548903de2..372e38a5b3 100644 --- a/audio/aidl/default/alsa/StreamAlsa.cpp +++ b/audio/aidl/default/alsa/StreamAlsa.cpp @@ -75,6 +75,10 @@ StreamAlsa::~StreamAlsa() { } decltype(mAlsaDeviceProxies) alsaDeviceProxies; for (const auto& device : getDeviceProfiles()) { + if ((device.direction == PCM_OUT && mIsInput) || + (device.direction == PCM_IN && !mIsInput)) { + continue; + } alsa::DeviceProxy proxy; if (device.isExternal) { // Always ask alsa configure as required since the configuration should be supported @@ -92,6 +96,9 @@ StreamAlsa::~StreamAlsa() { } alsaDeviceProxies.push_back(std::move(proxy)); } + if (alsaDeviceProxies.empty()) { + return ::android::NO_INIT; + } mAlsaDeviceProxies = std::move(alsaDeviceProxies); return ::android::OK; } diff --git a/audio/aidl/default/include/core-impl/StreamPrimary.h b/audio/aidl/default/include/core-impl/StreamPrimary.h index 8d5c57da4b..600c3779cd 100644 --- a/audio/aidl/default/include/core-impl/StreamPrimary.h +++ b/audio/aidl/default/include/core-impl/StreamPrimary.h @@ -25,7 +25,8 @@ namespace aidl::android::hardware::audio::core { class StreamPrimary : public StreamAlsa { public: - StreamPrimary(StreamContext* context, const Metadata& metadata); + StreamPrimary(StreamContext* context, const Metadata& metadata, + const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices); ::android::status_t start() override; ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount, @@ -39,6 +40,11 @@ class StreamPrimary : public StreamAlsa { int64_t mStartTimeNs = 0; long mFramesSinceStart = 0; bool mSkipNextTransfer = false; + + private: + static std::pair getCardAndDeviceId( + const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices); + const std::pair mCardAndDeviceId; }; class StreamInPrimary final : public StreamIn, public StreamSwitcher, public StreamInHwGainHelper { diff --git a/audio/aidl/default/primary/StreamPrimary.cpp b/audio/aidl/default/primary/StreamPrimary.cpp index 7325a91b49..abf3a731ad 100644 --- a/audio/aidl/default/primary/StreamPrimary.cpp +++ b/audio/aidl/default/primary/StreamPrimary.cpp @@ -15,7 +15,11 @@ */ #define LOG_TAG "AHAL_StreamPrimary" + +#include + #include +#include #include #include #include @@ -28,6 +32,7 @@ using aidl::android::hardware::audio::common::SinkMetadata; using aidl::android::hardware::audio::common::SourceMetadata; using aidl::android::media::audio::common::AudioDevice; +using aidl::android::media::audio::common::AudioDeviceAddress; using aidl::android::media::audio::common::AudioDeviceDescription; using aidl::android::media::audio::common::AudioDeviceType; using aidl::android::media::audio::common::AudioOffloadInfo; @@ -36,9 +41,15 @@ using android::base::GetBoolProperty; namespace aidl::android::hardware::audio::core { -StreamPrimary::StreamPrimary(StreamContext* context, const Metadata& metadata) +const static constexpr std::pair kDefaultCardAndDeviceId = { + primary::PrimaryMixer::kAlsaCard, primary::PrimaryMixer::kAlsaDevice}; + +StreamPrimary::StreamPrimary( + StreamContext* context, const Metadata& metadata, + const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) : StreamAlsa(context, metadata, 3 /*readWriteRetries*/), - mIsAsynchronous(!!getContext().getAsyncCallback()) { + mIsAsynchronous(!!getContext().getAsyncCallback()), + mCardAndDeviceId(getCardAndDeviceId(devices)) { context->startStreamDataProcessor(); } @@ -92,17 +103,27 @@ StreamPrimary::StreamPrimary(StreamContext* context, const Metadata& metadata) } std::vector StreamPrimary::getDeviceProfiles() { - static const std::vector kBuiltInSource{ - alsa::DeviceProfile{.card = primary::PrimaryMixer::kAlsaCard, - .device = primary::PrimaryMixer::kAlsaDevice, - .direction = PCM_IN, + return {alsa::DeviceProfile{.card = mCardAndDeviceId.first, + .device = mCardAndDeviceId.second, + .direction = mIsInput ? PCM_IN : PCM_OUT, .isExternal = false}}; - static const std::vector kBuiltInSink{ - alsa::DeviceProfile{.card = primary::PrimaryMixer::kAlsaCard, - .device = primary::PrimaryMixer::kAlsaDevice, - .direction = PCM_OUT, - .isExternal = false}}; - return mIsInput ? kBuiltInSource : kBuiltInSink; +} + +std::pair StreamPrimary::getCardAndDeviceId(const std::vector& devices) { + if (devices.empty() || devices[0].address.getTag() != AudioDeviceAddress::id) { + return kDefaultCardAndDeviceId; + } + std::string deviceAddress = devices[0].address.get(); + std::pair cardAndDeviceId; + if (const size_t suffixPos = deviceAddress.rfind("CARD_"); + suffixPos == std::string::npos || + sscanf(deviceAddress.c_str() + suffixPos, "CARD_%d_DEV_%d", &cardAndDeviceId.first, + &cardAndDeviceId.second) != 2) { + return kDefaultCardAndDeviceId; + } + LOG(DEBUG) << __func__ << ": parsed with card id " << cardAndDeviceId.first << ", device id " + << cardAndDeviceId.second; + return cardAndDeviceId; } StreamInPrimary::StreamInPrimary(StreamContext&& context, const SinkMetadata& sinkMetadata, @@ -145,7 +166,7 @@ std::unique_ptr StreamInPrimary::createNewStream( new InnerStreamWrapper(context, metadata)); } return std::unique_ptr( - new InnerStreamWrapper(context, metadata)); + new InnerStreamWrapper(context, metadata, devices)); } ndk::ScopedAStatus StreamInPrimary::getHwGain(std::vector* _aidl_return) { @@ -217,7 +238,7 @@ std::unique_ptr StreamOutPrimary::createNewStream( new InnerStreamWrapper(context, metadata)); } return std::unique_ptr( - new InnerStreamWrapper(context, metadata)); + new InnerStreamWrapper(context, metadata, devices)); } ndk::ScopedAStatus StreamOutPrimary::getHwVolume(std::vector* _aidl_return) {