Audio VTS: Improve stability, update config validation test

Major challenge: the configuration of HAL tests
depends on the APM XML configuration file which may be
invalid. The code that reads the configuration
has been updated to avoid crashes when the config
is invalid.

In CheckConfig_audioPolicyConfigurationValidation the
dependency on the config parser was removed. Previously,
a failure to parse the config by the config parser would
lead to the test being skipped, which isn't correct
as it must fail in this case.

Minor fixes to V7 tests to pass on a real life legacy HAL.

Bug: 36733185
Test: run VtsHalAudioV7_0TargetTest on a device with V6
Test: run VtsHalAudioV7_0TargetTest on a device with
      a side-loaded V7 and invalid APM config file
Test: run VtsHalAudioV7_0TargetTest on a device with
      a side-loaded V7
Change-Id: I746339ff69ab455dc64eef9a17827d047b357329
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 1612d3c..9a4a8b2 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -140,20 +140,23 @@
 #if MAJOR_VERSION <= 6
     using AD = AudioDevice;
     for (auto deviceType : {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) {
+        SCOPED_TRACE("device=" + ::testing::PrintToString(deviceType));
 #elif MAJOR_VERSION >= 7
     using AD = xsd::AudioDevice;
-    for (auto deviceType :
-         {toString(AD::AUDIO_DEVICE_OUT_HDMI), toString(AD::AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
-          toString(AD::AUDIO_DEVICE_IN_USB_HEADSET)}) {
+    for (auto deviceType : {AD::AUDIO_DEVICE_OUT_HDMI, AD::AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+                            AD::AUDIO_DEVICE_IN_USB_HEADSET}) {
+        SCOPED_TRACE("device=" + toString(deviceType));
 #endif
-        SCOPED_TRACE("device=" + ::testing::PrintToString(deviceType));
         for (bool state : {true, false}) {
             SCOPED_TRACE("state=" + ::testing::PrintToString(state));
             DeviceAddress address = {};
 #if MAJOR_VERSION <= 6
             address.device = deviceType;
 #elif MAJOR_VERSION >= 7
-            address.deviceType = deviceType;
+            address.deviceType = toString(deviceType);
+            if (deviceType == AD::AUDIO_DEVICE_IN_USB_HEADSET) {
+                address.address.alsa({0, 0});
+            }
 #endif
             auto ret = getDevice()->setConnectedState(address, state);
             ASSERT_TRUE(ret.isOk());
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 941c4bd..6bb7995 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -44,22 +44,26 @@
         for (const auto& device : getDeviceParameters()) {
             auto module =
                     getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+            if (!module || !module->getFirstMixPorts()) break;
             for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
                 if (mixPort.getRole() != xsd::Role::source) continue;  // not an output profile
-                auto xsdFlags = mixPort.getFlags();
-                const bool isOffload =
-                        std::find(xsdFlags.begin(), xsdFlags.end(),
-                                  xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) !=
-                        xsdFlags.end();
                 std::vector<AudioInOutFlag> flags;
-                if (!isOffload) {
-                    for (auto flag : xsdFlags) {
-                        if (flag != xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_PRIMARY) {
-                            flags.push_back(toString(flag));
+                bool isOffload = false;
+                if (mixPort.hasFlags()) {
+                    auto xsdFlags = mixPort.getFlags();
+                    isOffload =
+                            std::find(xsdFlags.begin(), xsdFlags.end(),
+                                      xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) !=
+                            xsdFlags.end();
+                    if (!isOffload) {
+                        for (auto flag : xsdFlags) {
+                            if (flag != xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_PRIMARY) {
+                                flags.push_back(toString(flag));
+                            }
                         }
+                    } else {
+                        flags = offloadFlags;
                     }
-                } else {
-                    flags = offloadFlags;
                 }
                 for (const auto& profile : mixPort.getProfile()) {
                     auto configs =
@@ -94,11 +98,15 @@
         for (const auto& device : getDeviceParameters()) {
             auto module =
                     getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+            if (!module || !module->getFirstMixPorts()) break;
             for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
                 if (mixPort.getRole() != xsd::Role::sink) continue;  // not an input profile
                 std::vector<AudioInOutFlag> flags;
-                std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(), flags.begin(),
-                               [](auto flag) { return toString(flag); });
+                if (mixPort.hasFlags()) {
+                    std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(),
+                                   std::back_inserter(flags),
+                                   [](auto flag) { return toString(flag); });
+                }
                 for (const auto& profile : mixPort.getProfile()) {
                     auto configs =
                             combineAudioConfig(profile.getChannelMasks(),
diff --git a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
index d790b34..7d88642 100644
--- a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
+++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
@@ -33,10 +33,14 @@
         if (mConfig) {
             mStatus = OK;
             mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice);
-            for (const auto& module : mConfig->getFirstModules()->get_module()) {
-                auto attachedDevices = module.getFirstAttachedDevices()->getItem();
-                if (!attachedDevices.empty()) {
-                    mModulesWithDevicesNames.insert(module.getName());
+            if (mConfig->getFirstModules()) {
+                for (const auto& module : mConfig->getFirstModules()->get_module()) {
+                    if (module.getFirstAttachedDevices()) {
+                        auto attachedDevices = module.getFirstAttachedDevices()->getItem();
+                        if (!attachedDevices.empty()) {
+                            mModulesWithDevicesNames.insert(module.getName());
+                        }
+                    }
                 }
             }
         }
@@ -52,7 +56,7 @@
     }
     const std::string& getFilePath() const { return mFilePath; }
     const xsd::Module* getModuleFromName(const std::string& name) const {
-        if (mConfig) {
+        if (mConfig && mConfig->getFirstModules()) {
             for (const auto& module : mConfig->getFirstModules()->get_module()) {
                 if (module.getName() == name) return &module;
             }
@@ -65,8 +69,10 @@
     }
     bool haveInputProfilesInModule(const std::string& name) const {
         auto module = getModuleFromName(name);
-        for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
-            if (mixPort.getRole() == xsd::Role::sink) return true;
+        if (module && module->getFirstMixPorts()) {
+            for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
+                if (mixPort.getRole() == xsd::Role::sink) return true;
+            }
         }
         return false;
     }
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index 05c9bf7..43c44cb 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -156,6 +156,21 @@
     return *policyConfig;
 }
 
+TEST(CheckConfig, audioPolicyConfigurationValidation) {
+    const auto factories = ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
+    if (factories.size() == 0) {
+        GTEST_SKIP() << "Skipping audioPolicyConfigurationValidation because no factory instances "
+                        "are found.";
+    }
+    RecordProperty("description",
+                   "Verify that the audio policy configuration file "
+                   "is valid according to the schema");
+
+    const char* xsd = "/data/local/tmp/audio_policy_configuration_" STRINGIFY(CPP_VERSION) ".xsd";
+    EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(kConfigFileName,
+                                            android::audio_get_configuration_paths(), xsd);
+}
+
 //////////////////////////////////////////////////////////////////////////////
 //////////////////// Test parameter types and definitions ////////////////////
 //////////////////////////////////////////////////////////////////////////////
@@ -231,21 +246,6 @@
     }
 };
 
-TEST(CheckConfig, audioPolicyConfigurationValidation) {
-    auto deviceParameters = getDeviceParametersForFactoryTests();
-    if (deviceParameters.size() == 0) {
-        GTEST_SKIP() << "Skipping audioPolicyConfigurationValidation because no device parameter "
-                        "is found.";
-    }
-    RecordProperty("description",
-                   "Verify that the audio policy configuration file "
-                   "is valid according to the schema");
-
-    const char* xsd = "/data/local/tmp/audio_policy_configuration_" STRINGIFY(CPP_VERSION) ".xsd";
-    EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(kConfigFileName,
-                                            android::audio_get_configuration_paths(), xsd);
-}
-
 class AudioPolicyConfigTest : public AudioHidlTestWithDeviceParameter {
   public:
     void SetUp() override {