From e6111852bc79d903848c72c353be7bde0e1e95f2 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Tue, 26 Nov 2019 18:56:21 -0800 Subject: DO NOT MERGE: Audio HAL: do not test input stream if no Built-in mic on primary The test used to always test input stream, assuming that all devices had built-in device on the primary Module. Nevertheless, although uncommon, the mic could be on any module or even not exist. This patch makes sure that the input stream tests are only run if there is a Built-in mic on the primary module. This patch also fixes GetMicrophonesTest to accept NOT_SUPPORTED result. This patch is specific for Android P. Later versions already have these fixes. Bug: 114303641 Test: atest VtsHalAudioV4_0TargetTest on device with a built-in mic and on a device w/o Change-Id: I7289724e5a73c1ffd09ca990f681844bdc8f6b3e --- .../test/utility/include/utility/ValidateXml.h | 7 +++ .../all-versions/test/utility/src/ValidateXml.cpp | 63 ++++++++++++++++++---- audio/core/4.0/vts/functional/Android.bp | 1 + .../vts/functional/AudioPolicyConfiguration.cpp | 26 +++++++++ .../4.0/vts/functional/AudioPolicyConfiguration.h | 22 ++++++++ .../4.0/vts/functional/AudioPrimaryHidlHalTest.cpp | 29 ++++++++++ .../vts/functional/ValidateAudioConfiguration.cpp | 7 +-- 7 files changed, 143 insertions(+), 12 deletions(-) create mode 100644 audio/core/4.0/vts/functional/AudioPolicyConfiguration.cpp create mode 100644 audio/core/4.0/vts/functional/AudioPolicyConfiguration.h diff --git a/audio/common/all-versions/test/utility/include/utility/ValidateXml.h b/audio/common/all-versions/test/utility/include/utility/ValidateXml.h index 91adfc12c8..4abd3fa8e1 100644 --- a/audio/common/all-versions/test/utility/include/utility/ValidateXml.h +++ b/audio/common/all-versions/test/utility/include/utility/ValidateXml.h @@ -34,6 +34,10 @@ namespace utility { ::testing::AssertionResult validateXml(const char* xmlFilePathExpr, const char* xsdFilePathExpr, const char* xmlFilePath, const char* xsdFilePath); +std::vector findValidXmlFiles(const char* xsdFilePathExpr, + const char* xmlFileName, std::vector xmlFileLocations, const char* xsdFilePath, + std::vector* errors = nullptr); + /** Helper gtest ASSERT to test XML validity against an XSD. */ #define ASSERT_VALID_XML(xmlFilePath, xsdFilePath) \ ASSERT_PRED_FORMAT2(::android::hardware::audio::common::test::utility::validateXml, \ @@ -78,6 +82,9 @@ template ::android::hardware::audio::common::test::utility::validateXmlMultipleLocations, \ xmlFileName, xmlFileLocations, xsdFilePath) +::testing::AssertionResult isNonEmptyXpath( + const char* xmlFilePath, const char* xpathQuery, bool* result); + } // namespace utility } // namespace test } // namespace common diff --git a/audio/common/all-versions/test/utility/src/ValidateXml.cpp b/audio/common/all-versions/test/utility/src/ValidateXml.cpp index 1a906d668b..126873d6f0 100644 --- a/audio/common/all-versions/test/utility/src/ValidateXml.cpp +++ b/audio/common/all-versions/test/utility/src/ValidateXml.cpp @@ -23,6 +23,8 @@ #include #define LIBXML_XINCLUDE_ENABLED #include +#define LIBXML_XPATH_ENABLED +#include #include #include @@ -47,6 +49,10 @@ template <> constexpr auto xmlDeleter = xmlSchemaFreeParserCtxt; template <> constexpr auto xmlDeleter = xmlSchemaFreeValidCtxt; +template <> +constexpr auto xmlDeleter = xmlXPathFreeContext; +template <> +constexpr auto xmlDeleter = xmlXPathFreeObject; /** @return a unique_ptr with the correct deleter for the libxml2 object. */ template @@ -129,27 +135,37 @@ struct Libxml2Global { return ::testing::AssertionSuccess(); } -template -::testing::AssertionResult validateXmlMultipleLocations( - const char* xmlFileNameExpr, const char* xmlFileLocationsExpr, const char* xsdFilePathExpr, - const char* xmlFileName, std::vector xmlFileLocations, const char* xsdFilePath) { +std::vector findValidXmlFiles( + const char* xsdFilePathExpr, + const char* xmlFileName, std::vector xmlFileLocations, const char* xsdFilePath, + std::vector* errors) { using namespace std::string_literals; - - std::vector errors; std::vector foundFiles; - for (const char* location : xmlFileLocations) { std::string xmlFilePath = location + "/"s + xmlFileName; if (access(xmlFilePath.c_str(), F_OK) != 0) { // If the file does not exist ignore this location and fallback on the next one continue; } - foundFiles.push_back(" " + xmlFilePath + '\n'); auto result = validateXml("xmlFilePath", xsdFilePathExpr, xmlFilePath.c_str(), xsdFilePath); if (!result) { - errors.push_back(result.message()); + if (errors != nullptr) errors->push_back(result.message()); + } else { + foundFiles.push_back(xmlFilePath); } } + return foundFiles; +} + +template +::testing::AssertionResult validateXmlMultipleLocations( + const char* xmlFileNameExpr, const char* xmlFileLocationsExpr, const char* xsdFilePathExpr, + const char* xmlFileName, std::vector xmlFileLocations, const char* xsdFilePath) { + using namespace std::string_literals; + + std::vector errors; + std::vector foundFiles = findValidXmlFiles( + xsdFilePathExpr, xmlFileName, xmlFileLocations, xsdFilePath, &errors); if (atLeastOneRequired && foundFiles.empty()) { errors.push_back("No xml file found in provided locations.\n"); @@ -175,6 +191,35 @@ template ::testing::AssertionResult validateXmlMultipleLocations(const ch std::vector, const char*); +::testing::AssertionResult isNonEmptyXpath( + const char* xmlFilePath, const char* xpathQuery, bool* result) { + Libxml2Global libxml2; + + auto context = [&]() { + return std::string() + " In: " + xmlFilePath + "\nLibxml2 errors:\n" + libxml2.getErrors(); + }; + + auto doc = make_xmlUnique(xmlReadFile(xmlFilePath, nullptr, 0)); + if (doc == nullptr) { + return ::testing::AssertionFailure() << "Failed to parse xml\n" << context(); + } + if (xmlXIncludeProcess(doc.get()) == -1) { + return ::testing::AssertionFailure() << "Failed to resolve xincludes in xml\n" << context(); + } + auto xpathCtxt = make_xmlUnique(xmlXPathNewContext(doc.get())); + if (xpathCtxt == nullptr) { + return ::testing::AssertionFailure() << "Failed to create xpath context\n" << context(); + } + auto xpathObj = make_xmlUnique(xmlXPathEvalExpression(BAD_CAST xpathQuery, xpathCtxt.get())); + if (xpathObj == nullptr) { + return ::testing::AssertionFailure() << + "Failed to evaluate xpath: \'" << xpathQuery << "\'\n" << context(); + } + auto nodeSet = xpathObj.get()->nodesetval; + *result = nodeSet ? nodeSet->nodeNr != 0 : false; + return ::testing::AssertionSuccess(); +} + } // namespace utility } // namespace test } // namespace common diff --git a/audio/core/4.0/vts/functional/Android.bp b/audio/core/4.0/vts/functional/Android.bp index e3b376ca88..48a98b1feb 100644 --- a/audio/core/4.0/vts/functional/Android.bp +++ b/audio/core/4.0/vts/functional/Android.bp @@ -18,6 +18,7 @@ cc_test { name: "VtsHalAudioV4_0TargetTest", defaults: ["VtsHalTargetTestDefaults"], srcs: [ + "AudioPolicyConfiguration.cpp", "AudioPrimaryHidlHalTest.cpp", "ValidateAudioConfiguration.cpp" ], diff --git a/audio/core/4.0/vts/functional/AudioPolicyConfiguration.cpp b/audio/core/4.0/vts/functional/AudioPolicyConfiguration.cpp new file mode 100644 index 0000000000..254c018e37 --- /dev/null +++ b/audio/core/4.0/vts/functional/AudioPolicyConfiguration.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2019 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 "AudioPolicyConfiguration.h" + +const char* kAudioPolicyConfigurationXml = "audio_policy_configuration.xml"; +const char* kAudioPolicyConfigurationXsd = + "/data/local/tmp/audio_policy_configuration_V4_0.xsd"; + +const std::vector& getApmConfigLocations() { + static const std::vector locations = {"/odm/etc", "/vendor/etc", "/system/etc"}; + return locations; +} diff --git a/audio/core/4.0/vts/functional/AudioPolicyConfiguration.h b/audio/core/4.0/vts/functional/AudioPolicyConfiguration.h new file mode 100644 index 0000000000..13a62ed730 --- /dev/null +++ b/audio/core/4.0/vts/functional/AudioPolicyConfiguration.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2019 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 + +extern const char* kAudioPolicyConfigurationXml; +extern const char* kAudioPolicyConfigurationXsd; + +const std::vector& getApmConfigLocations(); diff --git a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp index 71d91db360..308a4b51d1 100644 --- a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp @@ -45,12 +45,14 @@ #include +#include "AudioPolicyConfiguration.h" #include "utility/AssertOk.h" #include "utility/Documentation.h" #include "utility/EnvironmentTearDown.h" #define AUDIO_HAL_VERSION V4_0 #include "utility/PrettyPrintAudioTypes.h" #include "utility/ReturnIn.h" +#include "utility/ValidateXml.h" using std::initializer_list; using std::string; @@ -348,8 +350,29 @@ TEST_F(AudioPatchPrimaryHidlTest, AudioPatches) { /////////// TODO: move to the beginning of the file for easier update //////// ////////////////////////////////////////////////////////////////////////////// +static void hasDeviceTypeInModule( + const std::string& module, const std::string& device, bool* result) { + const std::vector configs = findValidXmlFiles( + "", kAudioPolicyConfigurationXml, getApmConfigLocations(), + kAudioPolicyConfigurationXsd); + *result = true; // If could not get the information, run all tests + ASSERT_EQ(1U, configs.size()); + std::string query = "/audioPolicyConfiguration/modules/module[@name=\"" + module + "\"]" + + "/devicePorts/devicePort[@type=\"" + device + "\"]"; + ASSERT_NO_FATAL_FAILURE(isNonEmptyXpath(configs[0].c_str(), query.c_str(), result)); +} + class AudioConfigPrimaryTest : public AudioPatchPrimaryHidlTest { public: + static bool primaryHasMic() { + static const bool hasMic = []() { + bool result; + hasDeviceTypeInModule("primary", "AUDIO_DEVICE_IN_BUILTIN_MIC", &result); + return result; + }(); + return hasMic; + } + // Cache result ? static const vector getRequiredSupportPlaybackAudioConfig() { return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, @@ -369,10 +392,12 @@ class AudioConfigPrimaryTest : public AudioPatchPrimaryHidlTest { } static const vector getRequiredSupportCaptureAudioConfig() { + if (!primaryHasMic()) return {}; return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100}, {AudioFormat::PCM_16_BIT}); } static const vector getRecommendedSupportCaptureAudioConfig() { + if (!primaryHasMic()) return {}; return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000}, {AudioFormat::PCM_16_BIT}); } @@ -515,6 +540,10 @@ TEST_F(AudioPrimaryHidlTest, GetMicrophonesTest) { doc::test("Make sure getMicrophones always succeeds"); hidl_vec microphones; ASSERT_OK(device->getMicrophones(returnIn(res, microphones))); + if (res == Result::NOT_SUPPORTED) { + doc::partialTest("getMicrophones is not supported"); + return; + } ASSERT_OK(res); if (microphones.size() > 0) { // When there is microphone on the phone, try to open an input stream diff --git a/audio/core/4.0/vts/functional/ValidateAudioConfiguration.cpp b/audio/core/4.0/vts/functional/ValidateAudioConfiguration.cpp index a64513fc81..7d929ce560 100644 --- a/audio/core/4.0/vts/functional/ValidateAudioConfiguration.cpp +++ b/audio/core/4.0/vts/functional/ValidateAudioConfiguration.cpp @@ -18,13 +18,14 @@ #include #include "utility/ValidateXml.h" +#include "AudioPolicyConfiguration.h" TEST(CheckConfig, audioPolicyConfigurationValidation) { RecordProperty("description", "Verify that the audio policy configuration file " "is valid according to the schema"); - std::vector locations = {"/odm/etc", "/vendor/etc", "/system/etc"}; - EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS("audio_policy_configuration.xml", locations, - "/data/local/tmp/audio_policy_configuration_V4_0.xsd"); + EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS( + kAudioPolicyConfigurationXml, getApmConfigLocations(), + kAudioPolicyConfigurationXsd); } -- cgit v1.2.3