Audio VTS: Make the active microphone query test more robust in V7

Prior to V7 the test which exercises
IStreamIn.getActiveMicrophones was using a hardcoded
configuration for the input stream. This configuration no longer
works for some of new devices. To fix that, the part of the test
which calls getActiveMicrophones has been moved into a separate
test--a descendant of InputStreamTest which is parametrized
using the actual configuration of the DUT.

Tests for HAL versions prior to V7 are not affected
because they don't use a full parser for the DUT config.

Bug: 193849687
Test: atest VtsHalAudioV7_0TargetTest
Change-Id: I00fe8fedb6bfc6e034387b35c88f954cb2638dfa
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
index b96cc83..28bcd0b 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -53,6 +53,11 @@
         GTEST_SKIP() << "getMicrophones is not supported";  // returns
     }
     ASSERT_OK(res);
+
+#if MAJOR_VERSION <= 6
+    // In V7, 'getActiveMicrophones' is tested by the 'MicrophoneInfoInputStream'
+    // test which uses the actual configuration of the device.
+
     if (microphones.size() > 0) {
         // When there is microphone on the phone, try to open an input stream
         // and query for the active microphones.
@@ -60,30 +65,13 @@
             "Make sure getMicrophones always succeeds"
             "and getActiveMicrophones always succeeds when recording from these microphones.");
         AudioConfig config{};
-#if MAJOR_VERSION <= 6
         config.channelMask = mkEnumBitfield(AudioChannelMask::IN_MONO);
         config.sampleRateHz = 8000;
         config.format = AudioFormat::PCM_16_BIT;
         auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
         const SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
-#elif MAJOR_VERSION >= 7
-        config.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO);
-        config.base.sampleRateHz = 8000;
-        config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
-        hidl_vec<hidl_string> flags;
-        const SinkMetadata initMetadata = {
-                {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC),
-                  .gain = 1,
-                  .tags = {},
-                  .channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
-#endif
         for (auto microphone : microphones) {
-#if MAJOR_VERSION <= 6
             if (microphone.deviceAddress.device != AudioDevice::IN_BUILTIN_MIC) {
-#elif MAJOR_VERSION >= 7
-            if (xsd::stringToAudioDevice(microphone.deviceAddress.deviceType) !=
-                xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC) {
-#endif
                 continue;
             }
             sp<IStreamIn> stream;
@@ -106,6 +94,7 @@
             EXPECT_NE(0U, activeMicrophones.size());
         }
     }
+#endif  // MAJOR_VERSION <= 6
 }
 
 TEST_P(AudioHidlDeviceTest, SetConnectedState) {
diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
index 0b3098b..0cc6a5b 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -839,3 +839,64 @@
                         ::testing::ValuesIn(getInputDevicePcmOnlyConfigParameters()),
                         &DeviceConfigParameterToString);
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PcmOnlyConfigInputStreamTest);
+
+static const std::vector<DeviceConfigParameter>& getBuiltinMicConfigParameters() {
+    static const std::vector<DeviceConfigParameter> parameters = [] {
+        auto allParams = getInputDeviceConfigParameters();
+        std::vector<DeviceConfigParameter> builtinMicParams;
+        std::copy_if(allParams.begin(), allParams.end(), std::back_inserter(builtinMicParams),
+                     [](auto cfg) {
+                         // The built in mic may participate in various scenarios:
+                         // FAST, HW_HOTWORD, MMAP NOIRQ, which are indicated by flags.
+                         // We are only interested in testing the simplest scenario w/o any flags.
+                         if (!std::get<PARAM_FLAGS>(cfg).empty()) return false;
+                         auto maybeSourceDevice = getCachedPolicyConfig().getSourceDeviceForMixPort(
+                                 std::get<PARAM_DEVICE_NAME>(std::get<PARAM_DEVICE>(cfg)),
+                                 std::get<PARAM_PORT_NAME>(cfg));
+                         return maybeSourceDevice.has_value() &&
+                                xsd::stringToAudioDevice(maybeSourceDevice.value().deviceType) ==
+                                        xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC;
+                     });
+        return builtinMicParams;
+    }();
+    return parameters;
+}
+
+class MicrophoneInfoInputStreamTest : public InputStreamTest {};
+
+TEST_P(MicrophoneInfoInputStreamTest, GetActiveMicrophones) {
+    doc::test(
+            "Make sure getActiveMicrophones always succeeds when recording "
+            "from the built-in microphone.");
+    hidl_vec<MicrophoneInfo> microphones;
+    ASSERT_OK(getDevice()->getMicrophones(returnIn(res, microphones)));
+    if (res == Result::NOT_SUPPORTED) {
+        GTEST_SKIP() << "getMicrophones is not supported";  // returns
+    }
+    ASSERT_OK(res);
+
+    auto maybeSourceAddress =
+            getCachedPolicyConfig().getSourceDeviceForMixPort(getDeviceName(), getMixPortName());
+    ASSERT_TRUE(maybeSourceAddress.has_value())
+            << "No source device found for mix port " << getMixPortName() << " (module "
+            << getDeviceName() << ")";
+
+    for (auto microphone : microphones) {
+        if (microphone.deviceAddress == maybeSourceAddress.value()) {
+            StreamReader reader(stream.get(), stream->getBufferSize());
+            ASSERT_TRUE(reader.start());
+            reader.pause();  // This ensures that at least one read has happened.
+            EXPECT_FALSE(reader.hasError());
+
+            hidl_vec<MicrophoneInfo> activeMicrophones;
+            ASSERT_OK(stream->getActiveMicrophones(returnIn(res, activeMicrophones)));
+            ASSERT_OK(res);
+            EXPECT_NE(0U, activeMicrophones.size());
+        }
+    }
+}
+
+INSTANTIATE_TEST_CASE_P(MicrophoneInfoInputStream, MicrophoneInfoInputStreamTest,
+                        ::testing::ValuesIn(getBuiltinMicConfigParameters()),
+                        &DeviceConfigParameterToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MicrophoneInfoInputStreamTest);