Merge changes from topic "policy-xml-vts"

* changes:
  Audio VTS: Reset HAL after setConnectionState
  Audio HAL: do not test input stream if no Built-in mic on primary
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 41b3841..e7c1e58 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -16,6 +16,17 @@
 
 #include "AudioPrimaryHidlHalTest.h"
 
+static void waitForDeviceDestruction() {
+    // FIXME: there is no way to know when the remote IDevice is being destroyed
+    //        Binder does not support testing if an object is alive, thus
+    //        wait for 100ms to let the binder destruction propagates and
+    //        the remote device has the time to be destroyed.
+    //        flushCommand makes sure all local command are sent, thus should reduce
+    //        the latency between local and remote destruction.
+    IPCThreadState::self()->flushCommands();
+    usleep(100);
+}
+
 TEST_F(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) {
     doc::test("Calling openDevice(\"primary\") should return the primary device.");
     {
@@ -29,14 +40,7 @@
         ASSERT_TRUE(primaryDevice.isOk());
         ASSERT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
     }  // Destroy local IDevice proxy
-    // FIXME: there is no way to know when the remote IDevice is being destroyed
-    //        Binder does not support testing if an object is alive, thus
-    //        wait for 100ms to let the binder destruction propagates and
-    //        the remote device has the time to be destroyed.
-    //        flushCommand makes sure all local command are sent, thus should reduce
-    //        the latency between local and remote destruction.
-    IPCThreadState::self()->flushCommands();
-    usleep(100);
+    waitForDeviceDestruction();
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -133,11 +137,17 @@
             ASSERT_TRUE(ret.isOk());
             if (ret == Result::NOT_SUPPORTED) {
                 doc::partialTest("setConnectedState is not supported");
-                return;
+                break;  // other deviceType might be supported
             }
             ASSERT_OK(ret);
         }
     }
+
+    // Because there is no way of knowing if the devices were connected before
+    // calling setConnectedState, there is no way to restore the HAL to its
+    // initial state. To workaround this, destroy the HAL at the end of this test.
+    device.clear();
+    waitForDeviceDestruction();
 }
 
 static void testGetDevices(IStream* stream, AudioDevice expectedDevice) {
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index 366a03e..519e359 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -17,13 +17,12 @@
 cc_defaults {
     name: "VtsHalAudioTargetTest_defaults",
     defaults: ["VtsHalTargetTestDefaults"],
-    srcs: [
-        "ValidateAudioConfiguration.cpp"
-    ],
     static_libs: [
         "android.hardware.audio.common.test.utility",
+        "libaudiopolicycomponents",
         "libicuuc",
         "libicuuc_stubdata",
+        "libmedia_helper",
         "libxml2",
     ],
     shared_libs: [
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index fd061da..24f4238 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -40,6 +40,8 @@
 #include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
 #include PATH(android/hardware/audio/FILE_VERSION/types.h)
 #include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+
+#include <Serializer.h>
 #include <fmq/EventFlag.h>
 #include <fmq/MessageQueue.h>
 
@@ -50,6 +52,7 @@
 #include "utility/EnvironmentTearDown.h"
 #include "utility/PrettyPrintAudioTypes.h"
 #include "utility/ReturnIn.h"
+#include "utility/ValidateXml.h"
 
 /** Provide version specific functions that are used in the generic tests */
 #if MAJOR_VERSION == 2
@@ -64,7 +67,12 @@
 using std::to_string;
 using std::vector;
 
+using ::android::AudioPolicyConfig;
+using ::android::HwModule;
+using ::android::NO_INIT;
+using ::android::OK;
 using ::android::sp;
+using ::android::status_t;
 using ::android::hardware::EventFlag;
 using ::android::hardware::hidl_bitfield;
 using ::android::hardware::hidl_enum_range;
@@ -120,6 +128,10 @@
 static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
 static auto invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUPPORTED};
 
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////// Environment /////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
 class AudioHidlTestEnvironment : public ::Environment {
    public:
     virtual void registerTestServices() override { registerTestService<IDevicesFactory>(); }
@@ -135,11 +147,103 @@
 };
 
 //////////////////////////////////////////////////////////////////////////////
+////////////////////////// Audio policy configuration ////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static const std::vector<const char*> kConfigLocations = {"/odm/etc", "/vendor/etc", "/system/etc"};
+static constexpr char kConfigFileName[] = "audio_policy_configuration.xml";
+
+// Stringify the argument.
+#define QUOTE(x) #x
+#define STRINGIFY(x) QUOTE(x)
+
+TEST(CheckConfig, audioPolicyConfigurationValidation) {
+    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, kConfigLocations, xsd);
+}
+
+struct PolicyConfigData {
+    android::HwModuleCollection hwModules;
+    android::DeviceVector availableOutputDevices;
+    android::DeviceVector availableInputDevices;
+    sp<android::DeviceDescriptor> defaultOutputDevice;
+    android::VolumeCurvesCollection volumes;
+};
+
+class PolicyConfig : private PolicyConfigData, public AudioPolicyConfig {
+   public:
+    PolicyConfig()
+        : AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices,
+                            defaultOutputDevice, &volumes) {
+        for (const char* location : kConfigLocations) {
+            std::string path = std::string(location) + '/' + kConfigFileName;
+            if (access(path.c_str(), F_OK) == 0) {
+                mFilePath = path;
+                break;
+            }
+        }
+        mStatus = android::deserializeAudioPolicyFile(mFilePath.c_str(), this);
+        if (mStatus == OK) {
+            mPrimaryModule = getHwModules().getModuleFromName("primary");
+        }
+    }
+    status_t getStatus() const { return mStatus; }
+    std::string getError() const {
+        if (mFilePath.empty()) {
+            return std::string{"Could not find "} + kConfigFileName +
+                   " file in: " + testing::PrintToString(kConfigLocations);
+        } else {
+            return "Invalid config file: " + mFilePath;
+        }
+    }
+    const std::string& getFilePath() const { return mFilePath; }
+    sp<const HwModule> getPrimaryModule() const { return mPrimaryModule; }
+
+   private:
+    status_t mStatus = NO_INIT;
+    std::string mFilePath;
+    sp<HwModule> mPrimaryModule = nullptr;
+};
+
+// Cached policy config after parsing for faster test startup
+const PolicyConfig& getCachedPolicyConfig() {
+    static std::unique_ptr<PolicyConfig> policyConfig = [] {
+        auto config = std::make_unique<PolicyConfig>();
+        environment->registerTearDown([] { policyConfig.reset(); });
+        return config;
+    }();
+    return *policyConfig;
+}
+
+class AudioPolicyConfigTest : public HidlTest {
+   public:
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(HidlTest::SetUp());  // setup base
+
+        auto& policyConfig = getCachedPolicyConfig();
+        ASSERT_EQ(0, policyConfig.getStatus()) << policyConfig.getError();
+
+        mPrimaryConfig = policyConfig.getPrimaryModule();
+        ASSERT_TRUE(mPrimaryConfig) << "Could not find primary module in configuration file: "
+                                    << policyConfig.getFilePath();
+    }
+    sp<const HwModule> mPrimaryConfig = nullptr;
+};
+
+TEST_F(AudioPolicyConfigTest, LoadAudioPolicyXMLConfiguration) {
+    doc::test("Test parsing audio_policy_configuration.xml (called in SetUp)");
+}
+
+//////////////////////////////////////////////////////////////////////////////
 ////////////////////// getService audio_devices_factory //////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
 // Test all audio devices
-class AudioHidlTest : public HidlTest {
+class AudioHidlTest : public AudioPolicyConfigTest {
    public:
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(HidlTest::SetUp());  // setup base
@@ -346,6 +450,20 @@
 
 class AudioConfigPrimaryTest : public AudioPatchPrimaryHidlTest {
    public:
+    // for retro compatibility only test the primary device IN_BUILTIN_MIC
+    // FIXME: in the next audio HAL version, test all available devices
+    static bool primaryHasMic() {
+        auto& policyConfig = getCachedPolicyConfig();
+        if (policyConfig.getStatus() != OK || policyConfig.getPrimaryModule() == nullptr) {
+            return true;  // Could not get the information, run all tests
+        }
+        auto getMic = [](auto& devs) { return devs.getDevice(AUDIO_DEVICE_IN_BUILTIN_MIC, {}); };
+        auto primaryMic = getMic(policyConfig.getPrimaryModule()->getDeclaredDevices());
+        auto availableMic = getMic(policyConfig.getAvailableInputDevices());
+
+        return primaryMic != nullptr && primaryMic->equals(availableMic);
+    }
+
     // Cache result ?
     static const vector<AudioConfig> getRequiredSupportPlaybackAudioConfig() {
         return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
@@ -365,10 +483,12 @@
     }
 
     static const vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
+        if (!primaryHasMic()) return {};
         return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100},
                                   {AudioFormat::PCM_16_BIT});
     }
     static const vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
+        if (!primaryHasMic()) return {};
         return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000},
                                   {AudioFormat::PCM_16_BIT});
     }
diff --git a/audio/core/all-versions/vts/functional/ValidateAudioConfiguration.cpp b/audio/core/all-versions/vts/functional/ValidateAudioConfiguration.cpp
deleted file mode 100644
index 5b6f378..0000000
--- a/audio/core/all-versions/vts/functional/ValidateAudioConfiguration.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <unistd.h>
-#include <string>
-
-#include "utility/ValidateXml.h"
-
-// Stringify the argument.
-#define QUOTE(x) #x
-#define STRINGIFY(x) QUOTE(x)
-
-TEST(CheckConfig, audioPolicyConfigurationValidation) {
-    RecordProperty("description",
-                   "Verify that the audio policy configuration file "
-                   "is valid according to the schema");
-
-    std::vector<const char*> locations = {"/odm/etc", "/vendor/etc", "/system/etc"};
-    const char* xsd = "/data/local/tmp/audio_policy_configuration_" STRINGIFY(CPP_VERSION) ".xsd";
-    EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS("audio_policy_configuration.xml", locations, xsd);
-}