Merge "Support multiple output devices in refrence audio HAL" into main am: 09b66d053e

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/3291062

Change-Id: I16ff52f05bb6cdff9d1b4dba7852058754fbca49
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
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) {