diff options
author | Mikhail Naganov <mnaganov@google.com> | 2019-11-26 18:56:21 -0800 |
---|---|---|
committer | Mikhail Naganov <mnaganov@google.com> | 2019-12-04 10:41:23 -0800 |
commit | e6111852bc79d903848c72c353be7bde0e1e95f2 (patch) | |
tree | bd3ff51f967d2f266cdb0deff0941eff360815f7 | |
parent | b0a0799f56c176bf6782f0a370cc3d9054adb55d (diff) | |
download | platform_hardware_interfaces-e6111852bc79d903848c72c353be7bde0e1e95f2.tar.gz platform_hardware_interfaces-e6111852bc79d903848c72c353be7bde0e1e95f2.tar.bz2 platform_hardware_interfaces-e6111852bc79d903848c72c353be7bde0e1e95f2.zip |
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
7 files changed, 143 insertions, 12 deletions
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<std::string> findValidXmlFiles(const char* xsdFilePathExpr, + const char* xmlFileName, std::vector<const char*> xmlFileLocations, const char* xsdFilePath, + std::vector<std::string>* 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 <bool atLeastOneRequired = true> ::android::hardware::audio::common::test::utility::validateXmlMultipleLocations<true>, \ 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 <libxml/xmlschemastypes.h> #define LIBXML_XINCLUDE_ENABLED #include <libxml/xinclude.h> +#define LIBXML_XPATH_ENABLED +#include <libxml/xpath.h> #include <memory> #include <string> @@ -47,6 +49,10 @@ template <> constexpr auto xmlDeleter<xmlSchemaParserCtxt> = xmlSchemaFreeParserCtxt; template <> constexpr auto xmlDeleter<xmlSchemaValidCtxt> = xmlSchemaFreeValidCtxt; +template <> +constexpr auto xmlDeleter<xmlXPathContext> = xmlXPathFreeContext; +template <> +constexpr auto xmlDeleter<xmlXPathObject> = xmlXPathFreeObject; /** @return a unique_ptr with the correct deleter for the libxml2 object. */ template <class T> @@ -129,27 +135,37 @@ struct Libxml2Global { return ::testing::AssertionSuccess(); } -template <bool atLeastOneRequired> -::testing::AssertionResult validateXmlMultipleLocations( - const char* xmlFileNameExpr, const char* xmlFileLocationsExpr, const char* xsdFilePathExpr, - const char* xmlFileName, std::vector<const char*> xmlFileLocations, const char* xsdFilePath) { +std::vector<std::string> findValidXmlFiles( + const char* xsdFilePathExpr, + const char* xmlFileName, std::vector<const char*> xmlFileLocations, const char* xsdFilePath, + std::vector<std::string>* errors) { using namespace std::string_literals; - - std::vector<std::string> errors; std::vector<std::string> 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 <bool atLeastOneRequired> +::testing::AssertionResult validateXmlMultipleLocations( + const char* xmlFileNameExpr, const char* xmlFileLocationsExpr, const char* xsdFilePathExpr, + const char* xmlFileName, std::vector<const char*> xmlFileLocations, const char* xsdFilePath) { + using namespace std::string_literals; + + std::vector<std::string> errors; + std::vector<std::string> 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<false>(const ch std::vector<const char*>, 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<const char*>& getApmConfigLocations() { + static const std::vector<const char*> 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 <vector> + +extern const char* kAudioPolicyConfigurationXml; +extern const char* kAudioPolicyConfigurationXsd; + +const std::vector<const char*>& 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 <common/all-versions/VersionUtils.h> +#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<std::string> 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<AudioConfig> getRequiredSupportPlaybackAudioConfig() { return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, @@ -369,10 +392,12 @@ class AudioConfigPrimaryTest : public AudioPatchPrimaryHidlTest { } 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}); } @@ -515,6 +540,10 @@ TEST_F(AudioPrimaryHidlTest, GetMicrophonesTest) { doc::test("Make sure getMicrophones always succeeds"); hidl_vec<MicrophoneInfo> 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 <string> #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<const char*> 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); } |