audio: Add microphone settings to IModule, IStreamIn

Add 'MicrophoneInfo' and 'MicrophoneDynamicInfo' parcelables.
Add IModule.getMicrophones method.
Add following methods to IStreamIn:
  - getActiveMicrophonesIds;
  - get/setMicrophoneDirection;
  - get/setMicrophoneFieldDimension.

Provide trivial implementations and VTS.

Also slightly refactor port retrieval from ModuleConfig
to unify common queries.

Bug: 205884982
Test: atest VtsHalAudioCoreTargetTest
Change-Id: I472c7733e2a331a67cea613cd9218889eff06a43
diff --git a/audio/aidl/vts/AudioHalBinderServiceUtil.h b/audio/aidl/vts/AudioHalBinderServiceUtil.h
index c8d81b1..b4b4632 100644
--- a/audio/aidl/vts/AudioHalBinderServiceUtil.h
+++ b/audio/aidl/vts/AudioHalBinderServiceUtil.h
@@ -31,7 +31,7 @@
   public:
     ndk::SpAIBinder connectToService(const std::string& serviceName) {
         mServiceName = serviceName;
-        mBinder = ndk::SpAIBinder(AServiceManager_getService(serviceName.c_str()));
+        mBinder = ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str()));
         if (mBinder == nullptr) {
             LOG(ERROR) << "Failed to get service " << serviceName;
         } else {
diff --git a/audio/aidl/vts/ModuleConfig.cpp b/audio/aidl/vts/ModuleConfig.cpp
index c081402..7e4b148 100644
--- a/audio/aidl/vts/ModuleConfig.cpp
+++ b/audio/aidl/vts/ModuleConfig.cpp
@@ -28,6 +28,7 @@
 
 using aidl::android::hardware::audio::core::IModule;
 using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioDeviceType;
 using aidl::android::media::audio::common::AudioEncapsulationMode;
 using aidl::android::media::audio::common::AudioFormatDescription;
 using aidl::android::media::audio::common::AudioFormatType;
@@ -62,6 +63,18 @@
     return {};
 }
 
+// static
+std::vector<aidl::android::media::audio::common::AudioPort> ModuleConfig::getBuiltInMicPorts(
+        const std::vector<aidl::android::media::audio::common::AudioPort>& ports) {
+    std::vector<AudioPort> result;
+    std::copy_if(ports.begin(), ports.end(), std::back_inserter(result), [](const auto& port) {
+        const auto type = port.ext.template get<AudioPortExt::Tag::device>().device.type;
+        return type.connection.empty() && (type.type == AudioDeviceType::IN_MICROPHONE ||
+                                           type.type == AudioDeviceType::IN_MICROPHONE_BACK);
+    });
+    return result;
+}
+
 template <typename T>
 auto findById(const std::vector<T>& v, int32_t id) {
     return std::find_if(v.begin(), v.end(), [&](const auto& p) { return p.id == id; });
@@ -107,38 +120,45 @@
     return result;
 }
 
-std::vector<AudioPort> ModuleConfig::getInputMixPorts() const {
+std::vector<AudioPort> ModuleConfig::getInputMixPorts(bool attachedOnly) const {
     std::vector<AudioPort> result;
-    std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [](const auto& port) {
+    std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
         return port.ext.getTag() == AudioPortExt::Tag::mix &&
-               port.flags.getTag() == AudioIoFlags::Tag::input;
+               port.flags.getTag() == AudioIoFlags::Tag::input &&
+               (!attachedOnly || !getAttachedSourceDevicesPortsForMixPort(port).empty());
     });
     return result;
 }
 
-std::vector<AudioPort> ModuleConfig::getOutputMixPorts() const {
+std::vector<AudioPort> ModuleConfig::getOutputMixPorts(bool attachedOnly) const {
     std::vector<AudioPort> result;
-    std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [](const auto& port) {
+    std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
         return port.ext.getTag() == AudioPortExt::Tag::mix &&
-               port.flags.getTag() == AudioIoFlags::Tag::output;
+               port.flags.getTag() == AudioIoFlags::Tag::output &&
+               (!attachedOnly || !getAttachedSinkDevicesPortsForMixPort(port).empty());
     });
     return result;
 }
 
 std::vector<AudioPort> ModuleConfig::getNonBlockingMixPorts(bool attachedOnly,
                                                             bool singlePort) const {
-    return findMixPorts(false /*isInput*/, singlePort, [&](const AudioPort& port) {
+    return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
         return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
-                                    AudioOutputFlags::NON_BLOCKING) &&
-               (!attachedOnly || !getAttachedSinkDevicesPortsForMixPort(port).empty());
+                                    AudioOutputFlags::NON_BLOCKING);
     });
 }
 
 std::vector<AudioPort> ModuleConfig::getOffloadMixPorts(bool attachedOnly, bool singlePort) const {
-    return findMixPorts(false /*isInput*/, singlePort, [&](const AudioPort& port) {
+    return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
         return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
-                                    AudioOutputFlags::COMPRESS_OFFLOAD) &&
-               (!attachedOnly || !getAttachedSinkDevicesPortsForMixPort(port).empty());
+                                    AudioOutputFlags::COMPRESS_OFFLOAD);
+    });
+}
+
+std::vector<AudioPort> ModuleConfig::getPrimaryMixPorts(bool attachedOnly, bool singlePort) const {
+    return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
+        return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
+                                    AudioOutputFlags::PRIMARY);
     });
 }
 
@@ -193,7 +213,7 @@
 
 std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getNonRoutableSrcSinkPair(
         bool isInput) const {
-    const auto mixPorts = getMixPorts(isInput);
+    const auto mixPorts = getMixPorts(isInput, false /*attachedOnly*/);
     std::set<std::pair<int32_t, int32_t>> allowedRoutes;
     for (const auto& route : mRoutes) {
         for (const auto srcPortId : route.sourcePortIds) {
@@ -344,9 +364,10 @@
 }
 
 std::vector<AudioPort> ModuleConfig::findMixPorts(
-        bool isInput, bool singlePort, std::function<bool(const AudioPort&)> pred) const {
+        bool isInput, bool attachedOnly, bool singlePort,
+        const std::function<bool(const AudioPort&)>& pred) const {
     std::vector<AudioPort> result;
-    const auto mixPorts = getMixPorts(isInput);
+    const auto mixPorts = getMixPorts(isInput, attachedOnly);
     for (auto mixPortIt = mixPorts.begin(); mixPortIt != mixPorts.end();) {
         mixPortIt = std::find_if(mixPortIt, mixPorts.end(), pred);
         if (mixPortIt == mixPorts.end()) break;
diff --git a/audio/aidl/vts/ModuleConfig.h b/audio/aidl/vts/ModuleConfig.h
index a85aa7f..7247f3b 100644
--- a/audio/aidl/vts/ModuleConfig.h
+++ b/audio/aidl/vts/ModuleConfig.h
@@ -37,22 +37,32 @@
     static std::optional<aidl::android::media::audio::common::AudioOffloadInfo>
     generateOffloadInfoIfNeeded(
             const aidl::android::media::audio::common::AudioPortConfig& portConfig);
+    static std::vector<aidl::android::media::audio::common::AudioPort> getBuiltInMicPorts(
+            const std::vector<aidl::android::media::audio::common::AudioPort>& ports);
 
     explicit ModuleConfig(aidl::android::hardware::audio::core::IModule* module);
     const ndk::ScopedAStatus& getStatus() const { return mStatus; }
     std::string getError() const { return mStatus.getMessage(); }
 
     std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicePorts() const;
+    std::vector<aidl::android::media::audio::common::AudioPort> getAttachedMicrophonePorts() const {
+        return getBuiltInMicPorts(getAttachedDevicePorts());
+    }
     std::vector<aidl::android::media::audio::common::AudioPort> getExternalDevicePorts() const;
-    std::vector<aidl::android::media::audio::common::AudioPort> getInputMixPorts() const;
-    std::vector<aidl::android::media::audio::common::AudioPort> getOutputMixPorts() const;
-    std::vector<aidl::android::media::audio::common::AudioPort> getMixPorts(bool isInput) const {
-        return isInput ? getInputMixPorts() : getOutputMixPorts();
+    std::vector<aidl::android::media::audio::common::AudioPort> getInputMixPorts(
+            bool attachedOnly) const;
+    std::vector<aidl::android::media::audio::common::AudioPort> getOutputMixPorts(
+            bool attachedOnly) const;
+    std::vector<aidl::android::media::audio::common::AudioPort> getMixPorts(
+            bool isInput, bool attachedOnly) const {
+        return isInput ? getInputMixPorts(attachedOnly) : getOutputMixPorts(attachedOnly);
     }
     std::vector<aidl::android::media::audio::common::AudioPort> getNonBlockingMixPorts(
             bool attachedOnly, bool singlePort) const;
     std::vector<aidl::android::media::audio::common::AudioPort> getOffloadMixPorts(
             bool attachedOnly, bool singlePort) const;
+    std::vector<aidl::android::media::audio::common::AudioPort> getPrimaryMixPorts(
+            bool attachedOnly, bool singlePort) const;
 
     std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicesPortsForMixPort(
             bool isInput, const aidl::android::media::audio::common::AudioPort& mixPort) const {
@@ -81,14 +91,17 @@
     }
     std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts()
             const {
-        auto inputs = generateAudioMixPortConfigs(getInputMixPorts(), true, false);
-        auto outputs = generateAudioMixPortConfigs(getOutputMixPorts(), false, false);
+        auto inputs =
+                generateAudioMixPortConfigs(getInputMixPorts(false /*attachedOnly*/), true, false);
+        auto outputs = generateAudioMixPortConfigs(getOutputMixPorts(false /*attachedOnly*/), false,
+                                                   false);
         inputs.insert(inputs.end(), outputs.begin(), outputs.end());
         return inputs;
     }
     std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
             bool isInput) const {
-        return generateAudioMixPortConfigs(getMixPorts(isInput), isInput, false);
+        return generateAudioMixPortConfigs(getMixPorts(isInput, false /*attachedOnly*/), isInput,
+                                           false);
     }
     std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
             bool isInput, const aidl::android::media::audio::common::AudioPort& port) const {
@@ -96,7 +109,8 @@
     }
     std::optional<aidl::android::media::audio::common::AudioPortConfig> getSingleConfigForMixPort(
             bool isInput) const {
-        const auto config = generateAudioMixPortConfigs(getMixPorts(isInput), isInput, true);
+        const auto config = generateAudioMixPortConfigs(
+                getMixPorts(isInput, false /*attachedOnly*/), isInput, true);
         if (!config.empty()) {
             return *config.begin();
         }
@@ -125,8 +139,9 @@
 
   private:
     std::vector<aidl::android::media::audio::common::AudioPort> findMixPorts(
-            bool isInput, bool singlePort,
-            std::function<bool(const aidl::android::media::audio::common::AudioPort&)> pred) const;
+            bool isInput, bool attachedOnly, bool singlePort,
+            const std::function<bool(const aidl::android::media::audio::common::AudioPort&)>& pred)
+            const;
     std::vector<aidl::android::media::audio::common::AudioPortConfig> generateAudioMixPortConfigs(
             const std::vector<aidl::android::media::audio::common::AudioPort>& ports, bool isInput,
             bool singleProfile) const;
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
index 79b20fe..c0c04f4 100644
--- a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
@@ -59,6 +59,8 @@
 using aidl::android::hardware::audio::core::IStreamIn;
 using aidl::android::hardware::audio::core::IStreamOut;
 using aidl::android::hardware::audio::core::ITelephony;
+using aidl::android::hardware::audio::core::MicrophoneDynamicInfo;
+using aidl::android::hardware::audio::core::MicrophoneInfo;
 using aidl::android::hardware::audio::core::ModuleDebug;
 using aidl::android::hardware::audio::core::StreamDescriptor;
 using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
@@ -192,6 +194,7 @@
         *isSupported = false;
         return;
     }
+    ASSERT_TRUE(status.isOk()) << "Unexpected status from a getter: " << status;
     *isSupported = true;
     for (const auto v : validValues) {
         EXPECT_IS_OK((inst->*setter)(v)) << "for valid value: " << v;
@@ -1567,6 +1570,42 @@
     // TODO: Test that mic mute actually mutes input.
 }
 
+TEST_P(AudioCoreModule, GetMicrophones) {
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    const std::vector<AudioPort> builtInMicPorts = moduleConfig->getAttachedMicrophonePorts();
+    std::vector<MicrophoneInfo> micInfos;
+    ScopedAStatus status = module->getMicrophones(&micInfos);
+    if (!status.isOk()) {
+        EXPECT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
+        ASSERT_FALSE(builtInMicPorts.empty())
+                << "When the HAL module does not have built-in microphones, IModule.getMicrophones"
+                << " must complete with no error and return an empty list";
+        GTEST_SKIP() << "Microphone info is not supported";
+    }
+    std::set<int32_t> micPortIdsWithInfo;
+    for (const auto& micInfo : micInfos) {
+        const auto& micDevice = micInfo.device;
+        const auto it =
+                std::find_if(builtInMicPorts.begin(), builtInMicPorts.end(), [&](const auto& port) {
+                    return port.ext.template get<AudioPortExt::Tag::device>().device == micDevice;
+                });
+        if (it != builtInMicPorts.end()) {
+            micPortIdsWithInfo.insert(it->id);
+        } else {
+            ADD_FAILURE() << "No device port found with a device specified for the microphone \""
+                          << micInfo.id << "\": " << micDevice.toString();
+        }
+    }
+    if (micPortIdsWithInfo.size() != builtInMicPorts.size()) {
+        std::vector<AudioPort> micPortsNoInfo;
+        std::copy_if(builtInMicPorts.begin(), builtInMicPorts.end(),
+                     std::back_inserter(micPortsNoInfo),
+                     [&](const auto& port) { return micPortIdsWithInfo.count(port.id) == 0; });
+        ADD_FAILURE() << "No MicrophoneInfo is provided for the following microphone device ports: "
+                      << ::android::internal::ToString(micPortsNoInfo);
+    }
+}
+
 TEST_P(AudioCoreModule, UpdateAudioMode) {
     for (const auto mode : ::ndk::enum_range<AudioMode>()) {
         EXPECT_IS_OK(module->updateAudioMode(mode)) << toString(mode);
@@ -1747,13 +1786,11 @@
 
     void OpenOverMaxCount() {
         constexpr bool isInput = IOTraits<Stream>::is_input;
-        auto ports = moduleConfig->getMixPorts(isInput);
+        auto ports = moduleConfig->getMixPorts(isInput, true /*attachedOnly*/);
         bool hasSingleRun = false;
         for (const auto& port : ports) {
             const size_t maxStreamCount = port.ext.get<AudioPortExt::Tag::mix>().maxOpenStreamCount;
-            if (maxStreamCount == 0 ||
-                moduleConfig->getAttachedDevicesPortsForMixPort(isInput, port).empty()) {
-                // No restrictions or no permanently attached devices.
+            if (maxStreamCount == 0) {
                 continue;
             }
             auto portConfigs = moduleConfig->getPortConfigsForMixPorts(isInput, port);
@@ -1878,20 +1915,127 @@
 TEST_IN_AND_OUT_STREAM(ResetPortConfigWithOpenStream);
 TEST_IN_AND_OUT_STREAM(SendInvalidCommand);
 
+namespace aidl::android::hardware::audio::core {
+std::ostream& operator<<(std::ostream& os, const IStreamIn::MicrophoneDirection& md) {
+    os << toString(md);
+    return os;
+}
+}  // namespace aidl::android::hardware::audio::core
+
+TEST_P(AudioStreamIn, ActiveMicrophones) {
+    std::vector<MicrophoneInfo> micInfos;
+    ScopedAStatus status = module->getMicrophones(&micInfos);
+    if (!status.isOk()) {
+        GTEST_SKIP() << "Microphone info is not supported";
+    }
+    const auto ports = moduleConfig->getInputMixPorts(true /*attachedOnly*/);
+    if (ports.empty()) {
+        GTEST_SKIP() << "No input mix ports for attached devices";
+    }
+    for (const auto& port : ports) {
+        const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
+        ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for input mix port";
+        WithStream<IStreamIn> stream(portConfig.value());
+        ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+        {
+            // The port of the stream is not connected, thus the list of active mics must be empty.
+            std::vector<MicrophoneDynamicInfo> activeMics;
+            EXPECT_IS_OK(stream.get()->getActiveMicrophones(&activeMics));
+            EXPECT_TRUE(activeMics.empty()) << "a stream on an unconnected port returns a "
+                                               "non-empty list of active microphones";
+        }
+        if (auto micDevicePorts = ModuleConfig::getBuiltInMicPorts(
+                    moduleConfig->getAttachedSourceDevicesPortsForMixPort(port));
+            !micDevicePorts.empty()) {
+            auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(micDevicePorts[0]);
+            WithAudioPatch patch(true /*isInput*/, stream.getPortConfig(), devicePortConfig);
+            ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
+            std::vector<MicrophoneDynamicInfo> activeMics;
+            EXPECT_IS_OK(stream.get()->getActiveMicrophones(&activeMics));
+            for (const auto& mic : activeMics) {
+                EXPECT_NE(micInfos.end(),
+                          std::find_if(micInfos.begin(), micInfos.end(),
+                                       [&](const auto& micInfo) { return micInfo.id == mic.id; }))
+                        << "active microphone \"" << mic.id << "\" is not listed in "
+                        << "microphone infos returned by the module: "
+                        << ::android::internal::ToString(micInfos);
+                EXPECT_NE(0UL, mic.channelMapping.size())
+                        << "No channels specified for the microphone \"" << mic.id << "\"";
+            }
+        }
+        {
+            // Now the port of the stream is not connected again, re-check that there are no
+            // active microphones.
+            std::vector<MicrophoneDynamicInfo> activeMics;
+            EXPECT_IS_OK(stream.get()->getActiveMicrophones(&activeMics));
+            EXPECT_TRUE(activeMics.empty()) << "a stream on an unconnected port returns a "
+                                               "non-empty list of active microphones";
+        }
+    }
+}
+
+TEST_P(AudioStreamIn, MicrophoneDirection) {
+    using MD = IStreamIn::MicrophoneDirection;
+    const auto ports = moduleConfig->getInputMixPorts(true /*attachedOnly*/);
+    if (ports.empty()) {
+        GTEST_SKIP() << "No input mix ports for attached devices";
+    }
+    bool isSupported = false;
+    for (const auto& port : ports) {
+        const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
+        ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for input mix port";
+        WithStream<IStreamIn> stream(portConfig.value());
+        ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+        EXPECT_NO_FATAL_FAILURE(
+                TestAccessors<MD>(stream.get(), &IStreamIn::getMicrophoneDirection,
+                                  &IStreamIn::setMicrophoneDirection,
+                                  std::vector<MD>(enum_range<MD>().begin(), enum_range<MD>().end()),
+                                  {}, &isSupported));
+        if (!isSupported) break;
+    }
+    if (!isSupported) {
+        GTEST_SKIP() << "Microphone direction is not supported";
+    }
+}
+
+TEST_P(AudioStreamIn, MicrophoneFieldDimension) {
+    const auto ports = moduleConfig->getInputMixPorts(true /*attachedOnly*/);
+    if (ports.empty()) {
+        GTEST_SKIP() << "No input mix ports for attached devices";
+    }
+    bool isSupported = false;
+    for (const auto& port : ports) {
+        const auto portConfig = moduleConfig->getSingleConfigForMixPort(true, port);
+        ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for input mix port";
+        WithStream<IStreamIn> stream(portConfig.value());
+        ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+        EXPECT_NO_FATAL_FAILURE(TestAccessors<float>(
+                stream.get(), &IStreamIn::getMicrophoneFieldDimension,
+                &IStreamIn::setMicrophoneFieldDimension,
+                {IStreamIn::MIC_FIELD_DIMENSION_WIDE_ANGLE,
+                 IStreamIn::MIC_FIELD_DIMENSION_WIDE_ANGLE / 2.0f,
+                 IStreamIn::MIC_FIELD_DIMENSION_NO_ZOOM,
+                 IStreamIn::MIC_FIELD_DIMENSION_MAX_ZOOM / 2.0f,
+                 IStreamIn::MIC_FIELD_DIMENSION_MAX_ZOOM},
+                {IStreamIn::MIC_FIELD_DIMENSION_WIDE_ANGLE * 2,
+                 IStreamIn::MIC_FIELD_DIMENSION_MAX_ZOOM * 2,
+                 IStreamIn::MIC_FIELD_DIMENSION_WIDE_ANGLE * 1.1f,
+                 IStreamIn::MIC_FIELD_DIMENSION_MAX_ZOOM * 1.1f, -INFINITY, INFINITY, -NAN, NAN},
+                &isSupported));
+        if (!isSupported) break;
+    }
+    if (!isSupported) {
+        GTEST_SKIP() << "Microphone direction is not supported";
+    }
+}
+
 TEST_P(AudioStreamOut, OpenTwicePrimary) {
-    const auto mixPorts = moduleConfig->getMixPorts(false);
-    auto primaryPortIt = std::find_if(mixPorts.begin(), mixPorts.end(), [](const AudioPort& port) {
-        return port.flags.getTag() == AudioIoFlags::Tag::output &&
-               isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
-                                    AudioOutputFlags::PRIMARY);
-    });
-    if (primaryPortIt == mixPorts.end()) {
-        GTEST_SKIP() << "No primary mix port";
+    const auto mixPorts =
+            moduleConfig->getPrimaryMixPorts(true /*attachedOnly*/, true /*singlePort*/);
+    if (mixPorts.empty()) {
+        GTEST_SKIP() << "No primary mix port which could be routed to attached devices";
     }
-    if (moduleConfig->getAttachedSinkDevicesPortsForMixPort(*primaryPortIt).empty()) {
-        GTEST_SKIP() << "Primary mix port can not be routed to any of attached devices";
-    }
-    const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, *primaryPortIt);
+    const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, *mixPorts.begin());
     ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for the primary mix port";
     EXPECT_NO_FATAL_FAILURE(OpenTwiceSamePortConfigImpl(portConfig.value()));
 }