audio: Run VTS tests for non-primary modules for HAL V6

Implement parsing of AudioPolicyManager config for finding
out declared modules (IDevice instances) with permanently
attached devices and run tests for them. This only applies
when running tests for HAL V6.

Change class hierarchy to use IDevice interface as much as
possible, only use IPrimaryDevice for its specific methods.

Fix the following issues found while running the tests
for "r_submix" and "msd" modules:

- IDevice::getMicrophones can return NOT_SUPPORTED status;

- IDevice::get/setParameters can return NOT_SUPPORTED.

Other changes:

- Factor out common code for getting devices via DeviceManager;

- Factor out AudioPolicyConfigTest.HasPrimaryModule test from
  SetUp code;

- Add device parameter generator for primary device only.

Bug: 141989952
Bug: 141847510
Test: atest VtsHalAudioV5_0TargetTest
      atest VtsHalAudioV6_0TargetTest
      also, run modified V5_0 test using generators for V6_0

Change-Id: I51cec21670120d8dce75609954a18b886cc0c18d
Merged-In: I51cec21670120d8dce75609954a18b886cc0c18d
diff --git a/audio/6.0/IDevice.hal b/audio/6.0/IDevice.hal
index 42a545b..e885fe2 100644
--- a/audio/6.0/IDevice.hal
+++ b/audio/6.0/IDevice.hal
@@ -260,7 +260,8 @@
     /**
      * Returns an array with available microphones in device.
      *
-     * @return retval INVALID_STATE if the call is not successful,
+     * @return retval NOT_SUPPORTED if there are no microphones on this device
+     *                INVALID_STATE if the call is not successful,
      *                OK otherwise.
      *
      * @return microphones array with microphones info
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 b8defb6..cd93643 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -18,15 +18,16 @@
 
 TEST_P(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) {
     doc::test("Calling openDevice(\"primary\") should return the primary device.");
+    if (getDeviceName() != DeviceManager::kPrimaryDevice) {
+        GTEST_SKIP() << "No primary device on this factory";  // returns
+    }
+
     struct WaitExecutor {
         ~WaitExecutor() { DeviceManager::waitForInstanceDestruction(); }
     } waitExecutor;  // Make sure we wait for the device destruction on exiting from the test.
     Result result;
     sp<IDevice> baseDevice;
     ASSERT_OK(getDevicesFactory()->openDevice("primary", returnIn(result, baseDevice)));
-    if (result != Result::OK && isPrimaryDeviceOptional()) {
-        GTEST_SKIP() << "No primary device on this factory";  // returns
-    }
     ASSERT_OK(result);
     ASSERT_TRUE(baseDevice != nullptr);
 
@@ -39,10 +40,13 @@
 /////////////////////////// get(Active)Microphones ///////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
-TEST_P(AudioPrimaryHidlTest, GetMicrophonesTest) {
+TEST_P(AudioHidlDeviceTest, GetMicrophonesTest) {
     doc::test("Make sure getMicrophones always succeeds");
     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);
     if (microphones.size() > 0) {
         // When there is microphone on the phone, try to open an input stream
@@ -120,7 +124,7 @@
     }
 }
 
-TEST_P(AudioPrimaryHidlTest, SetConnectedState) {
+TEST_P(AudioHidlDeviceTest, SetConnectedState) {
     doc::test("Check that the HAL can be notified of device connection and deconnection");
     using AD = AudioDevice;
     for (auto deviceType : {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) {
@@ -142,7 +146,7 @@
     // 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.
-    ASSERT_TRUE(DeviceManager::getInstance().resetPrimary(getFactoryName()));
+    ASSERT_TRUE(resetDevice());
 }
 
 static void testGetDevices(IStream* stream, AudioDevice expectedDevice) {
diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
index 6314ea7..937de0a 100644
--- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
@@ -16,3 +16,51 @@
 
 // pull in all the <= 5.0 tests
 #include "5.0/AudioPrimaryHidlHalTest.cpp"
+
+const std::vector<DeviceParameter>& getDeviceParametersForFactoryTests() {
+    static std::vector<DeviceParameter> parameters = [] {
+        std::vector<DeviceParameter> result;
+        const auto factories =
+                ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
+        for (const auto& factoryName : factories) {
+            result.emplace_back(factoryName,
+                                DeviceManager::getInstance().getPrimary(factoryName) != nullptr
+                                        ? DeviceManager::kPrimaryDevice
+                                        : "");
+        }
+        return result;
+    }();
+    return parameters;
+}
+
+const std::vector<DeviceParameter>& getDeviceParametersForPrimaryDeviceTests() {
+    static std::vector<DeviceParameter> parameters = [] {
+        std::vector<DeviceParameter> result;
+        const auto primary = std::find_if(
+                getDeviceParameters().begin(), getDeviceParameters().end(), [](const auto& elem) {
+                    return std::get<PARAM_DEVICE_NAME>(elem) == DeviceManager::kPrimaryDevice;
+                });
+        if (primary != getDeviceParameters().end()) result.push_back(*primary);
+        return result;
+    }();
+    return parameters;
+}
+
+const std::vector<DeviceParameter>& getDeviceParameters() {
+    static std::vector<DeviceParameter> parameters = [] {
+        std::vector<DeviceParameter> result;
+        const auto factories =
+                ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
+        const auto devices = getCachedPolicyConfig().getModulesWithDevicesNames();
+        result.reserve(devices.size());
+        for (const auto& factoryName : factories) {
+            for (const auto& deviceName : devices) {
+                if (DeviceManager::getInstance().get(factoryName, deviceName) != nullptr) {
+                    result.emplace_back(factoryName, deviceName);
+                }
+            }
+        }
+        return result;
+    }();
+    return parameters;
+}
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index e59ab98..7bdc5e1 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -24,6 +24,7 @@
 #include <limits>
 #include <list>
 #include <map>
+#include <set>
 #include <string>
 #include <vector>
 
@@ -129,11 +130,31 @@
 #include "DeviceManager.h"
 
 #if MAJOR_VERSION <= 5
-class HidlTest : public ::testing::VtsHalHidlTargetTestBase {
+using HidlTestBase = ::testing::VtsHalHidlTargetTestBase;
 #elif MAJOR_VERSION >= 6
-class HidlTest : public ::testing::Test {
+using HidlTestBase = ::testing::Test;
 #endif
+
+class HidlTest : public HidlTestBase {
+  public:
+    virtual ~HidlTest() = default;
+
   protected:
+    // Factory and device name getters to be overridden in subclasses.
+    virtual const std::string& getFactoryName() const = 0;
+    virtual const std::string& getDeviceName() const = 0;
+
+    sp<IDevicesFactory> getDevicesFactory() const {
+        return DevicesFactoryManager::getInstance().get(getFactoryName());
+    }
+    sp<IDevice> getDevice() const {
+        return DeviceManager::getInstance().get(getFactoryName(), getDeviceName());
+    }
+    bool resetDevice() const {
+        return DeviceManager::getInstance().reset(getFactoryName(), getDeviceName());
+    }
+    bool areAudioPatchesSupported() { return extract(getDevice()->supportsAudioPatches()); }
+
     // Convenient member to store results
     Result res;
 };
@@ -179,7 +200,25 @@
         }
         mStatus = android::deserializeAudioPolicyFile(mFilePath.c_str(), this);
         if (mStatus == OK) {
-            mPrimaryModule = getHwModules().getModuleFromName("primary");
+            mPrimaryModule = getHwModules().getModuleFromName(DeviceManager::kPrimaryDevice);
+            // Available devices are not 'attached' to modules at this moment.
+            // Need to go over available devices and find their module.
+            for (const auto& device : availableOutputDevices) {
+                for (const auto& module : hwModules) {
+                    if (module->getDeclaredDevices().indexOf(device) >= 0) {
+                        mModulesWithDevicesNames.insert(module->getName());
+                        break;
+                    }
+                }
+            }
+            for (const auto& device : availableInputDevices) {
+                for (const auto& module : hwModules) {
+                    if (module->getDeclaredDevices().indexOf(device) >= 0) {
+                        mModulesWithDevicesNames.insert(module->getName());
+                        break;
+                    }
+                }
+            }
         }
     }
     status_t getStatus() const { return mStatus; }
@@ -193,11 +232,15 @@
     }
     const std::string& getFilePath() const { return mFilePath; }
     sp<const HwModule> getPrimaryModule() const { return mPrimaryModule; }
+    const std::set<std::string>& getModulesWithDevicesNames() const {
+        return mModulesWithDevicesNames;
+    }
 
    private:
     status_t mStatus = NO_INIT;
     std::string mFilePath;
     sp<HwModule> mPrimaryModule = nullptr;
+    std::set<std::string> mModulesWithDevicesNames;
 };
 
 // Cached policy config after parsing for faster test startup
@@ -210,40 +253,26 @@
     return *policyConfig;
 }
 
-class AudioPolicyConfigTest : public HidlTest {
-   public:
+class AudioPolicyConfigTest : public HidlTestBase {
+  public:
     void SetUp() override {
-        ASSERT_NO_FATAL_FAILURE(HidlTest::SetUp());  // setup base
-
+        ASSERT_NO_FATAL_FAILURE(HidlTestBase::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();
     }
-
-  protected:
-    sp<IDevicesFactory> getDevicesFactory(const std::string& factoryName) const {
-        return DevicesFactoryManager::getInstance().get(factoryName);
-    }
-
-    sp<IPrimaryDevice> getPrimaryDevice(const std::string& factoryName) const {
-        return DeviceManager::getInstance().getPrimary(factoryName);
-    }
-
-    bool isPrimaryDeviceOptional(const std::string& factoryName) const {
-        // It's OK not to have "primary" device on non-default audio HAL service.
-        return factoryName != kDefaultServiceName;
-    }
-
-    sp<const HwModule> mPrimaryConfig = nullptr;
 };
 
 TEST_F(AudioPolicyConfigTest, LoadAudioPolicyXMLConfiguration) {
     doc::test("Test parsing audio_policy_configuration.xml (called in SetUp)");
 }
 
+TEST_F(AudioPolicyConfigTest, HasPrimaryModule) {
+    auto& policyConfig = getCachedPolicyConfig();
+    ASSERT_TRUE(policyConfig.getPrimaryModule() != nullptr)
+            << "Could not find primary module in configuration file: "
+            << policyConfig.getFilePath();
+}
+
 //////////////////////////////////////////////////////////////////////////////
 //////////////////// Test parameter types and definitions ////////////////////
 //////////////////////////////////////////////////////////////////////////////
@@ -253,13 +282,13 @@
 
 static inline std::string DeviceParameterToString(
         const ::testing::TestParamInfo<DeviceParameter>& info) {
+    const auto& deviceName = std::get<PARAM_DEVICE_NAME>(info.param);
 #if MAJOR_VERSION <= 5
-    return std::get<PARAM_DEVICE_NAME>(info.param);
+    return !deviceName.empty() ? deviceName : std::to_string(info.index);
 #elif MAJOR_VERSION >= 6
     const auto factoryName =
             ::android::hardware::PrintInstanceNameToString(::testing::TestParamInfo<std::string>{
                     std::get<PARAM_FACTORY_NAME>(info.param), info.index});
-    const auto& deviceName = std::get<PARAM_DEVICE_NAME>(info.param);
     return !deviceName.empty() ? factoryName + "_" + deviceName : factoryName;
 #endif
 }
@@ -268,41 +297,48 @@
 // For V2..5 the factory is looked up using the instance name passed
 // in the environment, only one factory is returned. This is because the VTS
 // framework will call the test for each instance. Only the primary device of
-// the factory specified in the environment is tested.
-const std::vector<DeviceParameter>& getDeviceParameters() {
+// the default service factory can be tested.
+
+// Return a pair of <"default", "primary"> or <[non-default name], "">
+// This is used to parametrize device factory tests.
+// The device name is used to indicate whether IPrimaryDevice is required.
+const std::vector<DeviceParameter>& getDeviceParametersForFactoryTests() {
     static std::vector<DeviceParameter> parameters = {
-            {environment->getServiceName<IDevicesFactory>(), DeviceManager::kPrimaryDevice}};
+            {environment->getServiceName<IDevicesFactory>(),
+             environment->getServiceName<IDevicesFactory>() == kDefaultServiceName
+                     ? DeviceManager::kPrimaryDevice
+                     : ""}};
     return parameters;
 }
+// Return a pair of <"default", "primary"> or nothing.
+// This is used to parametrize primary device tests.
+const std::vector<DeviceParameter>& getDeviceParametersForPrimaryDeviceTests() {
+    static std::vector<DeviceParameter> parameters =
+            !std::get<PARAM_DEVICE_NAME>(*getDeviceParametersForFactoryTests().begin()).empty()
+                    ? getDeviceParametersForFactoryTests()
+                    : std::vector<DeviceParameter>{};
+    return parameters;
+}
+// In V2..5 device tests must only test the primary device.
+// No device tests are executed for non-primary devices.
+const std::vector<DeviceParameter>& getDeviceParameters() {
+    return getDeviceParametersForPrimaryDeviceTests();
+}
 #elif MAJOR_VERSION >= 6
-// FIXME: Will be replaced with code that analyzes the audio policy config file.
-const std::vector<DeviceParameter>& getDeviceParameters() {
-    static std::vector<DeviceParameter> parameters = [] {
-        const auto instances =
-                ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
-        std::vector<DeviceParameter> result;
-        result.reserve(instances.size());
-        for (const auto& instance : instances) {
-            result.emplace_back(instance, DeviceManager::kPrimaryDevice);
-        }
-        return result;
-    }();
-    return parameters;
-}
+// For V6 and above these functions are implemented in 6.0/AudioPrimaryHidlHalTest.cpp
+const std::vector<DeviceParameter>& getDeviceParametersForFactoryTests();
+const std::vector<DeviceParameter>& getDeviceParametersForPrimaryDeviceTests();
+const std::vector<DeviceParameter>& getDeviceParameters();
 #endif
 
-class AudioHidlTestWithDeviceParameter : public AudioPolicyConfigTest,
+class AudioHidlTestWithDeviceParameter : public HidlTest,
                                          public ::testing::WithParamInterface<DeviceParameter> {
   protected:
-    const std::string& getFactoryName() const { return std::get<PARAM_FACTORY_NAME>(GetParam()); }
-    bool isPrimaryDeviceOptional() const {
-        return AudioPolicyConfigTest::isPrimaryDeviceOptional(getFactoryName());
+    const std::string& getFactoryName() const override {
+        return std::get<PARAM_FACTORY_NAME>(GetParam());
     }
-    sp<IDevicesFactory> getDevicesFactory() const {
-        return AudioPolicyConfigTest::getDevicesFactory(getFactoryName());
-    }
-    sp<IPrimaryDevice> getPrimaryDevice() const {
-        return AudioPolicyConfigTest::getPrimaryDevice(getFactoryName());
+    const std::string& getDeviceName() const override {
+        return std::get<PARAM_DEVICE_NAME>(GetParam());
     }
 };
 
@@ -310,7 +346,7 @@
 ////////////////////// getService audio_devices_factory //////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
-// Test all audio devices
+// Test audio devices factory
 class AudioHidlTest : public AudioHidlTestWithDeviceParameter {
   public:
     void SetUp() override {
@@ -337,53 +373,75 @@
     ASSERT_TRUE(device == nullptr);
 }
 
-INSTANTIATE_TEST_CASE_P(AudioHidl, AudioHidlTest, ::testing::ValuesIn(getDeviceParameters()),
+INSTANTIATE_TEST_CASE_P(AudioHidl, AudioHidlTest,
+                        ::testing::ValuesIn(getDeviceParametersForFactoryTests()),
                         &DeviceParameterToString);
 
 //////////////////////////////////////////////////////////////////////////////
+/////////////////////////////// openDevice ///////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+// Test all audio devices
+class AudioHidlDeviceTest : public AudioHidlTest {
+  public:
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(AudioHidlTest::SetUp());  // setup base
+        ASSERT_TRUE(getDevice() != nullptr);
+    }
+};
+
+TEST_P(AudioHidlDeviceTest, OpenDevice) {
+    doc::test("Test openDevice (called during setup)");
+}
+
+TEST_P(AudioHidlDeviceTest, Init) {
+    doc::test("Test that the audio hal initialized correctly");
+    ASSERT_OK(getDevice()->initCheck());
+}
+
+INSTANTIATE_TEST_CASE_P(AudioHidlDevice, AudioHidlDeviceTest,
+                        ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
+
+//////////////////////////////////////////////////////////////////////////////
 /////////////////////////////// openDevice primary ///////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
 // Test the primary device
-class AudioPrimaryHidlTest : public AudioHidlTest {
-   public:
+class AudioPrimaryHidlTest : public AudioHidlDeviceTest {
+  public:
     void SetUp() override {
-        ASSERT_NO_FATAL_FAILURE(AudioHidlTest::SetUp());  // setup base
-        if (getDevice() == nullptr && isPrimaryDeviceOptional()) {
-            GTEST_SKIP() << "No primary device on this factory";
-        }
+        ASSERT_NO_FATAL_FAILURE(AudioHidlDeviceTest::SetUp());  // setup base
         ASSERT_TRUE(getDevice() != nullptr);
     }
 
-   protected:
-     sp<IPrimaryDevice> getDevice() const { return getPrimaryDevice(); }
+  protected:
+    sp<IPrimaryDevice> getDevice() const {
+        return DeviceManager::getInstance().getPrimary(getFactoryName());
+    }
 };
 
 TEST_P(AudioPrimaryHidlTest, OpenPrimaryDevice) {
-    doc::test("Test the openDevice (called during setup)");
-}
-
-TEST_P(AudioPrimaryHidlTest, Init) {
-    doc::test("Test that the audio primary hal initialized correctly");
-    ASSERT_OK(getDevice()->initCheck());
+    doc::test("Test openPrimaryDevice (called during setup)");
 }
 
 INSTANTIATE_TEST_CASE_P(AudioPrimaryHidl, AudioPrimaryHidlTest,
-                        ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
+                        ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
+                        &DeviceParameterToString);
 
 //////////////////////////////////////////////////////////////////////////////
 ///////////////////// {set,get}{Master,Mic}{Mute,Volume} /////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
-template <class Property>
-class AccessorPrimaryHidlTest : public AudioPrimaryHidlTest {
-   protected:
+template <class Property, class BaseTestClass = AudioHidlDeviceTest>
+class AccessorHidlTest : public BaseTestClass {
+  protected:
     enum Optionality { REQUIRED, OPTIONAL };
     struct Initial {  // Initial property value
         Initial(Property value, Optionality check = REQUIRED) : value(value), check(check) {}
         Property value;
         Optionality check;  // If this initial value should be checked
     };
+    using BaseTestClass::res;
     /** Test a property getter and setter.
      *  The getter and/or the setter may return NOT_SUPPORTED if optionality == OPTIONAL.
      */
@@ -395,7 +453,7 @@
                                       optionality == OPTIONAL ? Result::NOT_SUPPORTED : Result::OK};
 
         Property initialValue = expectedInitial.value;
-        ASSERT_OK((getDevice().get()->*getter)(returnIn(res, initialValue)));
+        ASSERT_OK((BaseTestClass::getDevice().get()->*getter)(returnIn(res, initialValue)));
         ASSERT_RESULT(expectedResults, res);
         if (res == Result::OK && expectedInitial.check == REQUIRED) {
             EXPECT_EQ(expectedInitial.value, initialValue);
@@ -406,7 +464,7 @@
         for (Property setValue : valuesToTest) {
             SCOPED_TRACE("Test " + propertyName + " getter and setter for " +
                          testing::PrintToString(setValue));
-            auto ret = (getDevice().get()->*setter)(setValue);
+            auto ret = (BaseTestClass::getDevice().get()->*setter)(setValue);
             ASSERT_RESULT(expectedResults, ret);
             if (ret == Result::NOT_SUPPORTED) {
                 doc::partialTest(propertyName + " setter is not supported");
@@ -414,7 +472,7 @@
             }
             Property getValue;
             // Make sure the getter returns the same value just set
-            ASSERT_OK((getDevice().get()->*getter)(returnIn(res, getValue)));
+            ASSERT_OK((BaseTestClass::getDevice().get()->*getter)(returnIn(res, getValue)));
             ASSERT_RESULT(expectedResults, res);
             if (res == Result::NOT_SUPPORTED) {
                 doc::partialTest(propertyName + " getter is not supported");
@@ -426,34 +484,40 @@
         for (Property invalidValue : invalidValues) {
             SCOPED_TRACE("Try to set " + propertyName + " with the invalid value " +
                          testing::PrintToString(invalidValue));
-            EXPECT_RESULT(invalidArgsOrNotSupported, (getDevice().get()->*setter)(invalidValue));
+            EXPECT_RESULT(invalidArgsOrNotSupported,
+                          (BaseTestClass::getDevice().get()->*setter)(invalidValue));
         }
 
         // Restore initial value
-        EXPECT_RESULT(expectedResults, (getDevice().get()->*setter)(initialValue));
+        EXPECT_RESULT(expectedResults, (BaseTestClass::getDevice().get()->*setter)(initialValue));
     }
 };
 
-using BoolAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<bool>;
+using BoolAccessorHidlTest = AccessorHidlTest<bool>;
+using BoolAccessorPrimaryHidlTest = AccessorHidlTest<bool, AudioPrimaryHidlTest>;
 
-TEST_P(BoolAccessorPrimaryHidlTest, MicMuteTest) {
+TEST_P(BoolAccessorHidlTest, MicMuteTest) {
     doc::test("Check that the mic can be muted and unmuted");
-    testAccessors("mic mute", Initial{false}, {true}, &IDevice::setMicMute, &IDevice::getMicMute);
+    testAccessors<OPTIONAL>("mic mute", Initial{false}, {true}, &IDevice::setMicMute,
+                            &IDevice::getMicMute);
     // TODO: check that the mic is really muted (all sample are 0)
 }
 
-TEST_P(BoolAccessorPrimaryHidlTest, MasterMuteTest) {
+TEST_P(BoolAccessorHidlTest, MasterMuteTest) {
     doc::test("If master mute is supported, try to mute and unmute the master output");
     testAccessors<OPTIONAL>("master mute", Initial{false}, {true}, &IDevice::setMasterMute,
                             &IDevice::getMasterMute);
     // TODO: check that the master volume is really muted
 }
 
-INSTANTIATE_TEST_CASE_P(BoolAccessorPrimaryHidl, BoolAccessorPrimaryHidlTest,
+INSTANTIATE_TEST_CASE_P(BoolAccessorHidl, BoolAccessorHidlTest,
                         ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
+INSTANTIATE_TEST_CASE_P(BoolAccessorPrimaryHidl, BoolAccessorPrimaryHidlTest,
+                        ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
+                        &DeviceParameterToString);
 
-using FloatAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<float>;
-TEST_P(FloatAccessorPrimaryHidlTest, MasterVolumeTest) {
+using FloatAccessorHidlTest = AccessorHidlTest<float>;
+TEST_P(FloatAccessorHidlTest, MasterVolumeTest) {
     doc::test("Test the master volume if supported");
     testAccessors<OPTIONAL>(
         "master volume", Initial{1}, {0, 0.5}, &IDevice::setMasterVolume, &IDevice::getMasterVolume,
@@ -461,28 +525,29 @@
     // TODO: check that the master volume is really changed
 }
 
-INSTANTIATE_TEST_CASE_P(FloatAccessorPrimaryHidl, FloatAccessorPrimaryHidlTest,
+INSTANTIATE_TEST_CASE_P(FloatAccessorHidl, FloatAccessorHidlTest,
                         ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
 
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////// AudioPatches ////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
-class AudioPatchPrimaryHidlTest : public AudioPrimaryHidlTest {
-   protected:
-     bool areAudioPatchesSupported() { return extract(getDevice()->supportsAudioPatches()); }
+class AudioPatchHidlTest : public AudioHidlDeviceTest {
+  public:
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(AudioHidlDeviceTest::SetUp());  // setup base
+        if (!areAudioPatchesSupported()) {
+            GTEST_SKIP() << "Audio patches are not supported";
+        }
+    }
 };
 
-TEST_P(AudioPatchPrimaryHidlTest, AudioPatches) {
+TEST_P(AudioPatchHidlTest, AudioPatches) {
     doc::test("Test if audio patches are supported");
-    if (!areAudioPatchesSupported()) {
-        doc::partialTest("Audio patches are not supported");
-        return;
-    }
     // TODO: test audio patches
 }
 
-INSTANTIATE_TEST_CASE_P(AudioPatchPrimaryHidl, AudioPatchPrimaryHidlTest,
+INSTANTIATE_TEST_CASE_P(AudioPatchHidl, AudioPatchHidlTest,
                         ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
 
 //////////////////////////////////////////////////////////////////////////////
@@ -591,24 +656,21 @@
 }
 
 class AudioHidlTestWithDeviceConfigParameter
-    : public AudioPolicyConfigTest,
+    : public HidlTest,
       public ::testing::WithParamInterface<DeviceConfigParameter> {
   protected:
-    const std::string& getFactoryName() const {
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(HidlTest::SetUp());  // setup base
+        ASSERT_TRUE(getDevicesFactory() != nullptr);
+        ASSERT_TRUE(getDevice() != nullptr);
+    }
+    const std::string& getFactoryName() const override {
         return std::get<PARAM_FACTORY_NAME>(std::get<PARAM_DEVICE>(GetParam()));
     }
-    bool isPrimaryDeviceOptional() const {
-        return AudioPolicyConfigTest::isPrimaryDeviceOptional(getFactoryName());
-    }
-    sp<IDevicesFactory> getDevicesFactory() const {
-        return AudioPolicyConfigTest::getDevicesFactory(getFactoryName());
-    }
-    sp<IPrimaryDevice> getPrimaryDevice() const {
-        return AudioPolicyConfigTest::getPrimaryDevice(getFactoryName());
+    const std::string& getDeviceName() const override {
+        return std::get<PARAM_DEVICE_NAME>(std::get<PARAM_DEVICE>(GetParam()));
     }
     const AudioConfig& getConfig() const { return std::get<PARAM_CONFIG>(GetParam()); }
-    // FIXME: Split out tests that don't require primary device
-    sp<IPrimaryDevice> getDevice() const { return getPrimaryDevice(); }
 };
 
 //////////////////////////////////////////////////////////////////////////////
@@ -620,16 +682,6 @@
 //        how to get this value ? is it a property ???
 
 class AudioCaptureConfigPrimaryTest : public AudioHidlTestWithDeviceConfigParameter {
-  public:
-    void SetUp() override {
-        ASSERT_NO_FATAL_FAILURE(AudioHidlTestWithDeviceConfigParameter::SetUp());  // setup base
-        ASSERT_TRUE(getDevicesFactory() != nullptr);
-        if (getDevice() == nullptr && isPrimaryDeviceOptional()) {
-            GTEST_SKIP() << "No primary device on this factory";
-        }
-        ASSERT_TRUE(getDevice() != nullptr);
-    }
-
   protected:
     void inputBufferSizeTest(const AudioConfig& audioConfig, bool supportRequired) {
         uint64_t bufferSize;
@@ -661,8 +713,9 @@
 }
 INSTANTIATE_TEST_CASE_P(
         RequiredInputBufferSize, RequiredInputBufferSizeTest,
+        // FIXME: uses primaryHasMic
         ::testing::Combine(
-                ::testing::ValuesIn(getDeviceParameters()),
+                ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
                 ::testing::ValuesIn(ConfigHelper::getRequiredSupportCaptureAudioConfig())),
         &DeviceConfigParameterToString);
 INSTANTIATE_TEST_CASE_P(
@@ -682,8 +735,9 @@
 }
 INSTANTIATE_TEST_CASE_P(
         RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest,
+        // FIXME: uses primaryHasMic
         ::testing::Combine(
-                ::testing::ValuesIn(getDeviceParameters()),
+                ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
                 ::testing::ValuesIn(ConfigHelper::getRecommendedSupportCaptureAudioConfig())),
         &DeviceConfigParameterToString);
 
@@ -691,7 +745,7 @@
 /////////////////////////////// setScreenState ///////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
-TEST_P(AudioPrimaryHidlTest, setScreenState) {
+TEST_P(AudioHidlDeviceTest, setScreenState) {
     doc::test("Check that the hal can receive the screen state");
     for (bool turnedOn : {false, true, true, false, false}) {
         ASSERT_RESULT(okOrNotSupported, getDevice()->setScreenState(turnedOn));
@@ -702,15 +756,16 @@
 //////////////////////////// {get,set}Parameters /////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
-TEST_P(AudioPrimaryHidlTest, getParameters) {
+TEST_P(AudioHidlDeviceTest, getParameters) {
     doc::test("Check that the hal can set and get parameters");
     hidl_vec<ParameterValue> context;
     hidl_vec<hidl_string> keys;
     hidl_vec<ParameterValue> values;
     ASSERT_OK(Parameters::get(getDevice(), keys, returnIn(res, values)));
-    ASSERT_OK(Parameters::set(getDevice(), values));
+    ASSERT_RESULT(okOrNotSupported, res);
+    ASSERT_RESULT(okOrNotSupported, Parameters::set(getDevice(), values));
     values.resize(0);
-    ASSERT_OK(Parameters::set(getDevice(), values));
+    ASSERT_RESULT(okOrNotSupported, Parameters::set(getDevice(), values));
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -751,12 +806,12 @@
     EXPECT_EQ(0, close(fds[1])) << errno;
 }
 
-TEST_P(AudioPrimaryHidlTest, DebugDump) {
+TEST_P(AudioHidlDeviceTest, DebugDump) {
     doc::test("Check that the hal can dump its state without error");
     testDebugDump([this](const auto& handle) { return dump(getDevice(), handle); });
 }
 
-TEST_P(AudioPrimaryHidlTest, DebugDumpInvalidArguments) {
+TEST_P(AudioHidlDeviceTest, DebugDumpInvalidArguments) {
     doc::test("Check that the hal dump doesn't crash on invalid arguments");
     ASSERT_OK(dump(getDevice(), hidl_handle()));
 }
@@ -768,15 +823,6 @@
 template <class Stream>
 class OpenStreamTest : public AudioHidlTestWithDeviceConfigParameter {
   protected:
-    void SetUp() override {
-        ASSERT_NO_FATAL_FAILURE(AudioHidlTestWithDeviceConfigParameter::SetUp());  // setup base
-        ASSERT_TRUE(getDevicesFactory() != nullptr);
-        if (getDevice() == nullptr && isPrimaryDeviceOptional()) {
-            GTEST_SKIP() << "No primary device on this factory";
-        }
-        ASSERT_TRUE(getDevice() != nullptr);
-    }
-
     template <class Open>
     void testOpen(Open openStream, const AudioConfig& config) {
         // FIXME: Open a stream without an IOHandle
@@ -828,14 +874,12 @@
         usleep(100 * 1000);
     }
 
-    bool areAudioPatchesSupported() { return extract(getDevice()->supportsAudioPatches()); }
-
   private:
     void TearDown() override {
         if (open) {
             ASSERT_OK(closeStream());
         }
-        AudioPolicyConfigTest::TearDown();
+        AudioHidlTestWithDeviceConfigParameter::TearDown();
     }
 
    protected:
@@ -850,7 +894,6 @@
 class OutputStreamTest : public OpenStreamTest<IStreamOut> {
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp());  // setup base
-        if (IsSkipped()) return;                           // do not attempt to use 'device'
         address.device = AudioDevice::OUT_DEFAULT;
         const AudioConfig& config = getConfig();
         // TODO: test all flag combination
@@ -881,10 +924,11 @@
         "recommended config");
     // Open done in SetUp
 }
+// FIXME: Add instantiations for non-primary devices with configs harvested from the APM config file
 INSTANTIATE_TEST_CASE_P(
         RequiredOutputStreamConfigSupport, OutputStreamTest,
         ::testing::Combine(
-                ::testing::ValuesIn(getDeviceParameters()),
+                ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
                 ::testing::ValuesIn(ConfigHelper::getRequiredSupportPlaybackAudioConfig())),
         &DeviceConfigParameterToString);
 INSTANTIATE_TEST_CASE_P(
@@ -896,7 +940,7 @@
 INSTANTIATE_TEST_CASE_P(
         RecommendedOutputStreamConfigSupport, OutputStreamTest,
         ::testing::Combine(
-                ::testing::ValuesIn(getDeviceParameters()),
+                ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
                 ::testing::ValuesIn(ConfigHelper::getRecommendedSupportPlaybackAudioConfig())),
         &DeviceConfigParameterToString);
 
@@ -905,7 +949,6 @@
 class InputStreamTest : public OpenStreamTest<IStreamIn> {
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp());  // setup base
-        if (IsSkipped()) return;                           // do not attempt to use 'device'
         address.device = AudioDevice::IN_DEFAULT;
         const AudioConfig& config = getConfig();
         // TODO: test all supported flags and source
@@ -934,8 +977,9 @@
 }
 INSTANTIATE_TEST_CASE_P(
         RequiredInputStreamConfigSupport, InputStreamTest,
+        // FIXME: uses primaryHasMic
         ::testing::Combine(
-                ::testing::ValuesIn(getDeviceParameters()),
+                ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
                 ::testing::ValuesIn(ConfigHelper::getRequiredSupportCaptureAudioConfig())),
         &DeviceConfigParameterToString);
 INSTANTIATE_TEST_CASE_P(
@@ -946,8 +990,9 @@
 
 INSTANTIATE_TEST_CASE_P(
         RecommendedInputStreamConfigSupport, InputStreamTest,
+        // FIXME: uses primaryHasMic
         ::testing::Combine(
-                ::testing::ValuesIn(getDeviceParameters()),
+                ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
                 ::testing::ValuesIn(ConfigHelper::getRecommendedSupportCaptureAudioConfig())),
         &DeviceConfigParameterToString);
 
@@ -1481,7 +1526,8 @@
                             &IPrimaryDevice::getBtScoWidebandEnabled);
 }
 
-using TtyModeAccessorPrimaryHidlTest = AccessorPrimaryHidlTest<IPrimaryDevice::TtyMode>;
+using TtyModeAccessorPrimaryHidlTest =
+        AccessorHidlTest<IPrimaryDevice::TtyMode, AudioPrimaryHidlTest>;
 TEST_P(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) {
     doc::test("Query and set the TTY mode state");
     testAccessors<OPTIONAL>(
@@ -1490,7 +1536,8 @@
         &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode);
 }
 INSTANTIATE_TEST_CASE_P(TtyModeAccessorPrimaryHidl, TtyModeAccessorPrimaryHidlTest,
-                        ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
+                        ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
+                        &DeviceParameterToString);
 
 TEST_P(BoolAccessorPrimaryHidlTest, setGetHac) {
     doc::test("Query and set the HAC state");