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
diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp
index f548903..372e38a 100644
--- a/audio/aidl/default/alsa/StreamAlsa.cpp
+++ b/audio/aidl/default/alsa/StreamAlsa.cpp
@@ -75,6 +75,10 @@
}
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 @@
}
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 8d5c57d..600c377 100644
--- a/audio/aidl/default/include/core-impl/StreamPrimary.h
+++ b/audio/aidl/default/include/core-impl/StreamPrimary.h
@@ -25,7 +25,8 @@
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 @@
int64_t mStartTimeNs = 0;
long mFramesSinceStart = 0;
bool mSkipNextTransfer = false;
+
+ private:
+ static std::pair<int, int> getCardAndDeviceId(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices);
+ const std::pair<int, int> 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 7325a91..abf3a73 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 <cstdio>
+
#include <android-base/logging.h>
+#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <audio_utils/clock.h>
#include <error/Result.h>
@@ -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 @@
namespace aidl::android::hardware::audio::core {
-StreamPrimary::StreamPrimary(StreamContext* context, const Metadata& metadata)
+const static constexpr std::pair<int, int> 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 @@
}
std::vector<alsa::DeviceProfile> StreamPrimary::getDeviceProfiles() {
- static const std::vector<alsa::DeviceProfile> 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<alsa::DeviceProfile> kBuiltInSink{
- alsa::DeviceProfile{.card = primary::PrimaryMixer::kAlsaCard,
- .device = primary::PrimaryMixer::kAlsaDevice,
- .direction = PCM_OUT,
- .isExternal = false}};
- return mIsInput ? kBuiltInSource : kBuiltInSink;
+}
+
+std::pair<int, int> StreamPrimary::getCardAndDeviceId(const std::vector<AudioDevice>& devices) {
+ if (devices.empty() || devices[0].address.getTag() != AudioDeviceAddress::id) {
+ return kDefaultCardAndDeviceId;
+ }
+ std::string deviceAddress = devices[0].address.get<AudioDeviceAddress::id>();
+ std::pair<int, int> 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 @@
new InnerStreamWrapper<StreamStub>(context, metadata));
}
return std::unique_ptr<StreamCommonInterfaceEx>(
- new InnerStreamWrapper<StreamPrimary>(context, metadata));
+ new InnerStreamWrapper<StreamPrimary>(context, metadata, devices));
}
ndk::ScopedAStatus StreamInPrimary::getHwGain(std::vector<float>* _aidl_return) {
@@ -217,7 +238,7 @@
new InnerStreamWrapper<StreamStub>(context, metadata));
}
return std::unique_ptr<StreamCommonInterfaceEx>(
- new InnerStreamWrapper<StreamPrimary>(context, metadata));
+ new InnerStreamWrapper<StreamPrimary>(context, metadata, devices));
}
ndk::ScopedAStatus StreamOutPrimary::getHwVolume(std::vector<float>* _aidl_return) {