diff --git a/audio/core/all-versions/default/TEST_MAPPING b/audio/core/all-versions/default/TEST_MAPPING index d53c97afaa..1e2944060b 100644 --- a/audio/core/all-versions/default/TEST_MAPPING +++ b/audio/core/all-versions/default/TEST_MAPPING @@ -2,6 +2,12 @@ "presubmit": [ { "name": "android.hardware.audio@7.0-util_tests" + }, + { + "name": "HalAudioV6_0GeneratorTest" + }, + { + "name": "HalAudioV7_0GeneratorTest" } ] } 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 0ebe4c24ff..8af4c7855a 100644 --- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp @@ -17,105 +17,6 @@ // pull in all the <= 5.0 tests #include "5.0/AudioPrimaryHidlHalTest.cpp" -#if MAJOR_VERSION <= 6 -static std::vector generateOutputDeviceConfigParameters( - bool oneProfilePerDevice) { - std::vector result; - for (const auto& device : getDeviceParameters()) { - auto module = - getCachedPolicyConfig().getModuleFromName(std::get(device)); - for (const auto& ioProfile : module->getOutputProfiles()) { - for (const auto& profile : ioProfile->getAudioProfiles()) { - const auto& channels = profile->getChannels(); - const auto& sampleRates = profile->getSampleRates(); - auto configs = ConfigHelper::combineAudioConfig( - std::vector(channels.begin(), channels.end()), - std::vector(sampleRates.begin(), sampleRates.end()), - profile->getFormat()); - auto flags = ioProfile->getFlags(); - for (auto& config : configs) { - // Some combinations of flags declared in the config file require special - // treatment. - if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { - config.offloadInfo.sampleRateHz = config.sampleRateHz; - config.offloadInfo.channelMask = config.channelMask; - config.offloadInfo.format = config.format; - config.offloadInfo.streamType = AudioStreamType::MUSIC; - config.offloadInfo.bitRatePerSecond = 320; - config.offloadInfo.durationMicroseconds = -1; - config.offloadInfo.bitWidth = 16; - config.offloadInfo.bufferSize = 256; // arbitrary value - config.offloadInfo.usage = AudioUsage::MEDIA; - result.emplace_back(device, config, - AudioOutputFlag(AudioOutputFlag::COMPRESS_OFFLOAD | - AudioOutputFlag::DIRECT)); - } else { - if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) { // ignore the flag - flags &= ~AUDIO_OUTPUT_FLAG_PRIMARY; - } - result.emplace_back(device, config, AudioOutputFlag(flags)); - } - if (oneProfilePerDevice) break; - } - if (oneProfilePerDevice) break; - } - if (oneProfilePerDevice) break; - } - } - return result; -} - -const std::vector& getOutputDeviceConfigParameters() { - static std::vector parameters = - generateOutputDeviceConfigParameters(false); - return parameters; -} - -const std::vector& getOutputDeviceSingleConfigParameters() { - static std::vector parameters = - generateOutputDeviceConfigParameters(true); - return parameters; -} - -static std::vector generateInputDeviceConfigParameters( - bool oneProfilePerDevice) { - std::vector result; - for (const auto& device : getDeviceParameters()) { - auto module = - getCachedPolicyConfig().getModuleFromName(std::get(device)); - for (const auto& ioProfile : module->getInputProfiles()) { - for (const auto& profile : ioProfile->getAudioProfiles()) { - const auto& channels = profile->getChannels(); - const auto& sampleRates = profile->getSampleRates(); - auto configs = ConfigHelper::combineAudioConfig( - std::vector(channels.begin(), channels.end()), - std::vector(sampleRates.begin(), sampleRates.end()), - profile->getFormat()); - for (const auto& config : configs) { - result.emplace_back(device, config, AudioInputFlag(ioProfile->getFlags())); - if (oneProfilePerDevice) break; - } - if (oneProfilePerDevice) break; - } - if (oneProfilePerDevice) break; - } - } - return result; -} - -const std::vector& getInputDeviceConfigParameters() { - static std::vector parameters = - generateInputDeviceConfigParameters(false); - return parameters; -} - -const std::vector& getInputDeviceSingleConfigParameters() { - static std::vector parameters = - generateInputDeviceConfigParameters(true); - return parameters; -} -#endif // MAJOR_VERSION <= 6 - class SingleConfigOutputStreamTest : public OutputStreamTest {}; TEST_P(SingleConfigOutputStreamTest, CloseDeviceWithOpenedOutputStreams) { doc::test("Verify that a device can't be closed if there are output streams opened"); diff --git a/audio/core/all-versions/vts/functional/6.0/Generators.cpp b/audio/core/all-versions/vts/functional/6.0/Generators.cpp new file mode 100644 index 0000000000..6b4dbc17af --- /dev/null +++ b/audio/core/all-versions/vts/functional/6.0/Generators.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2021 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 + +#include "6.0/Generators.h" +#include "ConfigHelper.h" +#include "PolicyConfig.h" + +// clang-format off +#include PATH(android/hardware/audio/FILE_VERSION/types.h) +#include PATH(android/hardware/audio/common/FILE_VERSION/types.h) +// clang-format on + +// Forward declaration for functions that are substituted +// in generator unit tests. +const PolicyConfig& getCachedPolicyConfig(); +const std::vector& getDeviceParameters(); + +using namespace ::android::hardware::audio::common::CPP_VERSION; +using namespace ::android::hardware::audio::CPP_VERSION; + +std::vector generateOutputDeviceConfigParameters(bool oneProfilePerDevice) { + std::vector result; + for (const auto& device : getDeviceParameters()) { + auto module = + getCachedPolicyConfig().getModuleFromName(std::get(device)); + for (const auto& ioProfile : module->getOutputProfiles()) { + for (const auto& profile : ioProfile->getAudioProfiles()) { + const auto& channels = profile->getChannels(); + const auto& sampleRates = profile->getSampleRates(); + auto configs = ConfigHelper::combineAudioConfig( + std::vector(channels.begin(), channels.end()), + std::vector(sampleRates.begin(), sampleRates.end()), + profile->getFormat()); + auto flags = ioProfile->getFlags(); + for (auto& config : configs) { + // Some combinations of flags declared in the config file require special + // treatment. + if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { + config.offloadInfo.sampleRateHz = config.sampleRateHz; + config.offloadInfo.channelMask = config.channelMask; + config.offloadInfo.format = config.format; + config.offloadInfo.streamType = AudioStreamType::MUSIC; + config.offloadInfo.bitRatePerSecond = 320; + config.offloadInfo.durationMicroseconds = -1; + config.offloadInfo.bitWidth = 16; + config.offloadInfo.bufferSize = 256; // arbitrary value + config.offloadInfo.usage = AudioUsage::MEDIA; + result.emplace_back(device, config, + AudioOutputFlag(AudioOutputFlag::COMPRESS_OFFLOAD | + AudioOutputFlag::DIRECT)); + } else { + if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) { // ignore the flag + flags &= ~AUDIO_OUTPUT_FLAG_PRIMARY; + } + result.emplace_back(device, config, AudioOutputFlag(flags)); + } + if (oneProfilePerDevice) break; + } + if (oneProfilePerDevice) break; + } + if (oneProfilePerDevice) break; + } + } + return result; +} + +const std::vector& getOutputDeviceConfigParameters() { + static std::vector parameters = + generateOutputDeviceConfigParameters(false); + return parameters; +} + +const std::vector& getOutputDeviceSingleConfigParameters() { + static std::vector parameters = + generateOutputDeviceConfigParameters(true); + return parameters; +} + +std::vector generateInputDeviceConfigParameters(bool oneProfilePerDevice) { + std::vector result; + for (const auto& device : getDeviceParameters()) { + auto module = + getCachedPolicyConfig().getModuleFromName(std::get(device)); + for (const auto& ioProfile : module->getInputProfiles()) { + for (const auto& profile : ioProfile->getAudioProfiles()) { + const auto& channels = profile->getChannels(); + const auto& sampleRates = profile->getSampleRates(); + auto configs = ConfigHelper::combineAudioConfig( + std::vector(channels.begin(), channels.end()), + std::vector(sampleRates.begin(), sampleRates.end()), + profile->getFormat()); + for (const auto& config : configs) { + result.emplace_back(device, config, AudioInputFlag(ioProfile->getFlags())); + if (oneProfilePerDevice) break; + } + if (oneProfilePerDevice) break; + } + if (oneProfilePerDevice) break; + } + } + return result; +} + +const std::vector& getInputDeviceConfigParameters() { + static std::vector parameters = + generateInputDeviceConfigParameters(false); + return parameters; +} + +const std::vector& getInputDeviceSingleConfigParameters() { + static std::vector parameters = + generateInputDeviceConfigParameters(true); + return parameters; +} diff --git a/audio/core/all-versions/vts/functional/6.0/Generators.h b/audio/core/all-versions/vts/functional/6.0/Generators.h new file mode 100644 index 0000000000..1e87163477 --- /dev/null +++ b/audio/core/all-versions/vts/functional/6.0/Generators.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 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. + */ + +#pragma once + +#include + +#include "AudioTestDefinitions.h" + +const std::vector& getOutputDeviceConfigParameters(); +const std::vector& getOutputDeviceSingleConfigParameters(); +const std::vector& getInputDeviceConfigParameters(); +const std::vector& getInputDeviceSingleConfigParameters(); + +// For unit tests +std::vector generateOutputDeviceConfigParameters(bool oneProfilePerDevice); +std::vector generateInputDeviceConfigParameters(bool oneProfilePerDevice); 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 be1ffbbcfe..c1923f1230 100644 --- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp @@ -14,277 +14,11 @@ * limitations under the License. */ +#include "Generators.h" + // pull in all the <= 6.0 tests #include "6.0/AudioPrimaryHidlHalTest.cpp" -static std::vector combineAudioConfig(std::vector channelMasks, - std::vector sampleRates, - const std::string& format) { - std::vector configs; - configs.reserve(channelMasks.size() * sampleRates.size()); - for (auto channelMask : channelMasks) { - for (auto sampleRate : sampleRates) { - AudioConfig config{}; - config.base.channelMask = toString(channelMask); - config.base.sampleRateHz = sampleRate; - config.base.format = format; - configs.push_back(config); - } - } - return configs; -} - -static std::tuple, bool> generateOutFlags( - const xsd::MixPorts::MixPort& mixPort) { - static const std::vector offloadFlags = { - toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD), - toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_DIRECT)}; - std::vector flags; - 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; - } - } - return {flags, isOffload}; -} - -static AudioOffloadInfo generateOffloadInfo(const AudioConfigBase& base) { - return AudioOffloadInfo{ - .base = base, - .streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC), - .usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA), - .bitRatePerSecond = 320, - .durationMicroseconds = -1, - .bitWidth = 16, - .bufferSize = 256 // arbitrary value - }; -} - -static std::vector generateOutputDeviceConfigParameters( - bool oneProfilePerDevice) { - std::vector result; - for (const auto& device : getDeviceParameters()) { - auto module = - getCachedPolicyConfig().getModuleFromName(std::get(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 [flags, isOffload] = generateOutFlags(mixPort); - for (const auto& profile : mixPort.getProfile()) { - auto configs = combineAudioConfig(profile.getChannelMasks(), - profile.getSamplingRates(), profile.getFormat()); - for (auto& config : configs) { - // Some combinations of flags declared in the config file require special - // treatment. - if (isOffload) { - config.offloadInfo.info(generateOffloadInfo(config.base)); - } - result.emplace_back(device, config, flags); - if (oneProfilePerDevice) break; - } - if (oneProfilePerDevice) break; - } - if (oneProfilePerDevice) break; - } - } - return result; -} - -const std::vector& getOutputDeviceConfigParameters() { - static std::vector parameters = - generateOutputDeviceConfigParameters(false); - return parameters; -} - -const std::vector& getOutputDeviceSingleConfigParameters() { - static std::vector parameters = - generateOutputDeviceConfigParameters(true); - return parameters; -} - -const std::vector& getOutputDeviceInvalidConfigParameters( - bool generateInvalidFlags = true) { - static std::vector parameters = [&] { - std::vector result; - for (const auto& device : getDeviceParameters()) { - auto module = - getCachedPolicyConfig().getModuleFromName(std::get(device)); - if (!module || !module->getFirstMixPorts()) break; - bool hasRegularConfig = false, hasOffloadConfig = false; - for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) { - if (mixPort.getRole() != xsd::Role::source) continue; // not an output profile - auto [validFlags, isOffload] = generateOutFlags(mixPort); - if ((!isOffload && hasRegularConfig) || (isOffload && hasOffloadConfig)) continue; - for (const auto& profile : mixPort.getProfile()) { - if (!profile.hasFormat() || !profile.hasSamplingRates() || - !profile.hasChannelMasks()) - continue; - AudioConfigBase validBase = { - profile.getFormat(), - static_cast(profile.getSamplingRates()[0]), - toString(profile.getChannelMasks()[0])}; - { - AudioConfig config{.base = validBase}; - config.base.channelMask = "random_string"; - if (isOffload) { - config.offloadInfo.info(generateOffloadInfo(validBase)); - } - result.emplace_back(device, config, validFlags); - } - { - AudioConfig config{.base = validBase}; - config.base.format = "random_string"; - if (isOffload) { - config.offloadInfo.info(generateOffloadInfo(validBase)); - } - result.emplace_back(device, config, validFlags); - } - if (generateInvalidFlags) { - AudioConfig config{.base = validBase}; - if (isOffload) { - config.offloadInfo.info(generateOffloadInfo(validBase)); - } - std::vector flags = {"random_string", ""}; - result.emplace_back(device, config, flags); - } - if (isOffload) { - { - AudioConfig config{.base = validBase}; - config.offloadInfo.info(generateOffloadInfo(validBase)); - config.offloadInfo.info().base.channelMask = "random_string"; - } - { - AudioConfig config{.base = validBase}; - config.offloadInfo.info(generateOffloadInfo(validBase)); - config.offloadInfo.info().base.format = "random_string"; - } - { - AudioConfig config{.base = validBase}; - config.offloadInfo.info(generateOffloadInfo(validBase)); - config.offloadInfo.info().streamType = "random_string"; - } - { - AudioConfig config{.base = validBase}; - config.offloadInfo.info(generateOffloadInfo(validBase)); - config.offloadInfo.info().usage = "random_string"; - } - hasOffloadConfig = true; - } else { - hasRegularConfig = true; - } - break; - } - if (hasOffloadConfig && hasRegularConfig) break; - } - } - return result; - }(); - return parameters; -} - -static std::vector generateInputDeviceConfigParameters( - bool oneProfilePerDevice) { - std::vector result; - for (const auto& device : getDeviceParameters()) { - auto module = - getCachedPolicyConfig().getModuleFromName(std::get(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 flags; - 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(), - profile.getSamplingRates(), profile.getFormat()); - for (const auto& config : configs) { - result.emplace_back(device, config, flags); - if (oneProfilePerDevice) break; - } - if (oneProfilePerDevice) break; - } - if (oneProfilePerDevice) break; - } - } - return result; -} - -const std::vector& getInputDeviceConfigParameters() { - static std::vector parameters = - generateInputDeviceConfigParameters(false); - return parameters; -} - -const std::vector& getInputDeviceSingleConfigParameters() { - static std::vector parameters = - generateInputDeviceConfigParameters(true); - return parameters; -} - -const std::vector& getInputDeviceInvalidConfigParameters( - bool generateInvalidFlags = true) { - static std::vector parameters = [&] { - std::vector result; - for (const auto& device : getDeviceParameters()) { - auto module = - getCachedPolicyConfig().getModuleFromName(std::get(device)); - if (!module || !module->getFirstMixPorts()) break; - bool hasConfig = false; - for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) { - if (mixPort.getRole() != xsd::Role::sink) continue; // not an input profile - std::vector validFlags; - if (mixPort.hasFlags()) { - std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(), - std::back_inserter(validFlags), - [](auto flag) { return toString(flag); }); - } - for (const auto& profile : mixPort.getProfile()) { - if (!profile.hasFormat() || !profile.hasSamplingRates() || - !profile.hasChannelMasks()) - continue; - AudioConfigBase validBase = { - profile.getFormat(), - static_cast(profile.getSamplingRates()[0]), - toString(profile.getChannelMasks()[0])}; - { - AudioConfig config{.base = validBase}; - config.base.channelMask = "random_string"; - result.emplace_back(device, config, validFlags); - } - { - AudioConfig config{.base = validBase}; - config.base.format = "random_string"; - result.emplace_back(device, config, validFlags); - } - if (generateInvalidFlags) { - AudioConfig config{.base = validBase}; - std::vector flags = {"random_string", ""}; - result.emplace_back(device, config, flags); - } - hasConfig = true; - break; - } - if (hasConfig) break; - } - } - return result; - }(); - return parameters; -} - class InvalidInputConfigNoFlagsTest : public AudioHidlTestWithDeviceConfigParameter {}; TEST_P(InvalidInputConfigNoFlagsTest, InputBufferSizeTest) { doc::test("Verify that invalid config is rejected by IDevice::getInputBufferSize method."); diff --git a/audio/core/all-versions/vts/functional/7.0/Generators.cpp b/audio/core/all-versions/vts/functional/7.0/Generators.cpp new file mode 100644 index 0000000000..eafc813cf9 --- /dev/null +++ b/audio/core/all-versions/vts/functional/7.0/Generators.cpp @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2021 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 + +#include "7.0/Generators.h" +#include "7.0/PolicyConfig.h" + +// clang-format off +#include PATH(android/hardware/audio/FILE_VERSION/types.h) +#include PATH(android/hardware/audio/common/FILE_VERSION/types.h) +// clang-format on + +#include +#include + +// Forward declaration for functions that are substituted +// in generator unit tests. +const PolicyConfig& getCachedPolicyConfig(); +const std::vector& getDeviceParameters(); + +using namespace ::android::hardware::audio::common::CPP_VERSION; +using namespace ::android::hardware::audio::CPP_VERSION; +namespace xsd { +using namespace ::android::audio::policy::configuration::CPP_VERSION; +} + +static std::vector combineAudioConfig(std::vector channelMasks, + std::vector sampleRates, + const std::string& format) { + std::vector configs; + configs.reserve(channelMasks.size() * sampleRates.size()); + for (auto channelMask : channelMasks) { + for (auto sampleRate : sampleRates) { + AudioConfig config{}; + config.base.channelMask = toString(channelMask); + config.base.sampleRateHz = sampleRate; + config.base.format = format; + configs.push_back(config); + } + } + return configs; +} + +static std::tuple, bool> generateOutFlags( + const xsd::MixPorts::MixPort& mixPort) { + static const std::vector offloadFlags = { + toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD), + toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_DIRECT)}; + std::vector flags; + 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; + } + } + return {flags, isOffload}; +} + +static AudioOffloadInfo generateOffloadInfo(const AudioConfigBase& base) { + return AudioOffloadInfo{ + .base = base, + .streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC), + .usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA), + .bitRatePerSecond = 320, + .durationMicroseconds = -1, + .bitWidth = 16, + .bufferSize = 256 // arbitrary value + }; +} + +std::vector generateOutputDeviceConfigParameters(bool oneProfilePerDevice) { + std::vector result; + for (const auto& device : getDeviceParameters()) { + auto module = + getCachedPolicyConfig().getModuleFromName(std::get(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 [flags, isOffload] = generateOutFlags(mixPort); + for (const auto& profile : mixPort.getProfile()) { + auto configs = combineAudioConfig(profile.getChannelMasks(), + profile.getSamplingRates(), profile.getFormat()); + for (auto& config : configs) { + // Some combinations of flags declared in the config file require special + // treatment. + if (isOffload) { + config.offloadInfo.info(generateOffloadInfo(config.base)); + } + result.emplace_back(device, config, flags); + if (oneProfilePerDevice) break; + } + if (oneProfilePerDevice) break; + } + if (oneProfilePerDevice) break; + } + } + return result; +} + +const std::vector& getOutputDeviceConfigParameters() { + static std::vector parameters = + generateOutputDeviceConfigParameters(false); + return parameters; +} + +const std::vector& getOutputDeviceSingleConfigParameters() { + static std::vector parameters = + generateOutputDeviceConfigParameters(true); + return parameters; +} + +const std::vector& getOutputDeviceInvalidConfigParameters( + bool generateInvalidFlags) { + static std::vector parameters = [&] { + std::vector result; + for (const auto& device : getDeviceParameters()) { + auto module = + getCachedPolicyConfig().getModuleFromName(std::get(device)); + if (!module || !module->getFirstMixPorts()) break; + bool hasRegularConfig = false, hasOffloadConfig = false; + for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) { + if (mixPort.getRole() != xsd::Role::source) continue; // not an output profile + auto [validFlags, isOffload] = generateOutFlags(mixPort); + if ((!isOffload && hasRegularConfig) || (isOffload && hasOffloadConfig)) continue; + for (const auto& profile : mixPort.getProfile()) { + if (!profile.hasFormat() || !profile.hasSamplingRates() || + !profile.hasChannelMasks()) + continue; + AudioConfigBase validBase = { + profile.getFormat(), + static_cast(profile.getSamplingRates()[0]), + toString(profile.getChannelMasks()[0])}; + { + AudioConfig config{.base = validBase}; + config.base.channelMask = "random_string"; + if (isOffload) { + config.offloadInfo.info(generateOffloadInfo(validBase)); + } + result.emplace_back(device, config, validFlags); + } + { + AudioConfig config{.base = validBase}; + config.base.format = "random_string"; + if (isOffload) { + config.offloadInfo.info(generateOffloadInfo(validBase)); + } + result.emplace_back(device, config, validFlags); + } + if (generateInvalidFlags) { + AudioConfig config{.base = validBase}; + if (isOffload) { + config.offloadInfo.info(generateOffloadInfo(validBase)); + } + std::vector flags = {"random_string", ""}; + result.emplace_back(device, config, flags); + } + if (isOffload) { + { + AudioConfig config{.base = validBase}; + config.offloadInfo.info(generateOffloadInfo(validBase)); + config.offloadInfo.info().base.channelMask = "random_string"; + result.emplace_back(device, config, validFlags); + } + { + AudioConfig config{.base = validBase}; + config.offloadInfo.info(generateOffloadInfo(validBase)); + config.offloadInfo.info().base.format = "random_string"; + result.emplace_back(device, config, validFlags); + } + { + AudioConfig config{.base = validBase}; + config.offloadInfo.info(generateOffloadInfo(validBase)); + config.offloadInfo.info().streamType = "random_string"; + result.emplace_back(device, config, validFlags); + } + { + AudioConfig config{.base = validBase}; + config.offloadInfo.info(generateOffloadInfo(validBase)); + config.offloadInfo.info().usage = "random_string"; + result.emplace_back(device, config, validFlags); + } + hasOffloadConfig = true; + } else { + hasRegularConfig = true; + } + break; + } + if (hasOffloadConfig && hasRegularConfig) break; + } + } + return result; + }(); + return parameters; +} + +std::vector generateInputDeviceConfigParameters(bool oneProfilePerDevice) { + std::vector result; + for (const auto& device : getDeviceParameters()) { + auto module = + getCachedPolicyConfig().getModuleFromName(std::get(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 flags; + 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(), + profile.getSamplingRates(), profile.getFormat()); + for (const auto& config : configs) { + result.emplace_back(device, config, flags); + if (oneProfilePerDevice) break; + } + if (oneProfilePerDevice) break; + } + if (oneProfilePerDevice) break; + } + } + return result; +} + +const std::vector& getInputDeviceConfigParameters() { + static std::vector parameters = + generateInputDeviceConfigParameters(false); + return parameters; +} + +const std::vector& getInputDeviceSingleConfigParameters() { + static std::vector parameters = + generateInputDeviceConfigParameters(true); + return parameters; +} + +const std::vector& getInputDeviceInvalidConfigParameters( + bool generateInvalidFlags) { + static std::vector parameters = [&] { + std::vector result; + for (const auto& device : getDeviceParameters()) { + auto module = + getCachedPolicyConfig().getModuleFromName(std::get(device)); + if (!module || !module->getFirstMixPorts()) break; + bool hasConfig = false; + for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) { + if (mixPort.getRole() != xsd::Role::sink) continue; // not an input profile + std::vector validFlags; + if (mixPort.hasFlags()) { + std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(), + std::back_inserter(validFlags), + [](auto flag) { return toString(flag); }); + } + for (const auto& profile : mixPort.getProfile()) { + if (!profile.hasFormat() || !profile.hasSamplingRates() || + !profile.hasChannelMasks()) + continue; + AudioConfigBase validBase = { + profile.getFormat(), + static_cast(profile.getSamplingRates()[0]), + toString(profile.getChannelMasks()[0])}; + { + AudioConfig config{.base = validBase}; + config.base.channelMask = "random_string"; + result.emplace_back(device, config, validFlags); + } + { + AudioConfig config{.base = validBase}; + config.base.format = "random_string"; + result.emplace_back(device, config, validFlags); + } + if (generateInvalidFlags) { + AudioConfig config{.base = validBase}; + std::vector flags = {"random_string", ""}; + result.emplace_back(device, config, flags); + } + hasConfig = true; + break; + } + if (hasConfig) break; + } + } + return result; + }(); + return parameters; +} diff --git a/audio/core/all-versions/vts/functional/7.0/Generators.h b/audio/core/all-versions/vts/functional/7.0/Generators.h new file mode 100644 index 0000000000..e36cfad31b --- /dev/null +++ b/audio/core/all-versions/vts/functional/7.0/Generators.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 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. + */ + +#pragma once + +#include + +#include "AudioTestDefinitions.h" + +const std::vector& getOutputDeviceConfigParameters(); +const std::vector& getOutputDeviceSingleConfigParameters(); +const std::vector& getOutputDeviceInvalidConfigParameters( + bool generateInvalidFlags = true); +const std::vector& getInputDeviceConfigParameters(); +const std::vector& getInputDeviceSingleConfigParameters(); +const std::vector& getInputDeviceInvalidConfigParameters( + bool generateInvalidFlags = true); + +// For unit tests +std::vector generateOutputDeviceConfigParameters(bool oneProfilePerDevice); +std::vector generateInputDeviceConfigParameters(bool oneProfilePerDevice); 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 7d8864284c..feb4d4b3aa 100644 --- a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h +++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h @@ -16,11 +16,35 @@ #pragma once -// Note: it is assumed that this file is included from AudioPrimaryHidlTest.h -// and thus it doesn't have all '#include' and 'using' directives required -// for a standalone compilation. +#include +#include +#include +#include +#include + +#include +#include +#include + +// clang-format off +#include PATH(android/hardware/audio/FILE_VERSION/types.h) +#include PATH(android/hardware/audio/common/FILE_VERSION/types.h) +// clang-format on + +#include +#include + +#include "DeviceManager.h" + +using ::android::NO_INIT; +using ::android::OK; +using ::android::status_t; + +using namespace ::android::hardware::audio::common::CPP_VERSION; +using namespace ::android::hardware::audio::CPP_VERSION; namespace xsd { +using namespace ::android::audio::policy::configuration::CPP_VERSION; using Module = Modules::Module; } @@ -30,20 +54,13 @@ class PolicyConfig { : mConfigFileName{configFileName}, mFilePath{findExistingConfigurationFile(mConfigFileName)}, mConfig{xsd::read(mFilePath.c_str())} { - if (mConfig) { - mStatus = OK; - mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice); - 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()); - } - } - } - } - } + init(); + } + PolicyConfig(const std::string& configPath, const std::string& configFileName) + : mConfigFileName{configFileName}, + mFilePath{configPath + "/" + mConfigFileName}, + mConfig{xsd::read(mFilePath.c_str())} { + init(); } status_t getStatus() const { return mStatus; } std::string getError() const { @@ -87,6 +104,22 @@ class PolicyConfig { } return std::string{}; } + void init() { + if (mConfig) { + mStatus = OK; + mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice); + 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()); + } + } + } + } + } + } const std::string mConfigFileName; const std::string mFilePath; diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp index 4520dc3f8d..91c54dce35 100644 --- a/audio/core/all-versions/vts/functional/Android.bp +++ b/audio/core/all-versions/vts/functional/Android.bp @@ -126,6 +126,7 @@ cc_test { defaults: ["VtsHalAudioTargetTest_defaults"], srcs: [ "6.0/AudioPrimaryHidlHalTest.cpp", + "6.0/Generators.cpp", ], static_libs: [ "libaudiofoundation", @@ -152,6 +153,7 @@ cc_test { defaults: ["VtsHalAudioTargetTest_defaults"], srcs: [ "7.0/AudioPrimaryHidlHalTest.cpp", + "7.0/Generators.cpp", ], generated_headers: ["audio_policy_configuration_V7_0_parser"], generated_sources: ["audio_policy_configuration_V7_0_parser"], @@ -172,3 +174,57 @@ cc_test { // TODO(b/146104851): Add auto-gen rules and remove it. test_config: "VtsHalAudioV7_0TargetTest.xml", } + +// Note: the following aren't VTS tests, but rather unit tests +// to verify correctness of test parameter generator utilities. +cc_test { + name: "HalAudioV6_0GeneratorTest", + defaults: ["VtsHalAudioTargetTest_defaults"], + srcs: [ + "6.0/Generators.cpp", + "tests/generators_tests.cpp", + ], + static_libs: [ + "android.hardware.audio@6.0", + "android.hardware.audio.common@6.0", + "libaudiofoundation", + "libaudiopolicycomponents", + "libmedia_helper", + ], + cflags: [ + "-DMAJOR_VERSION=6", + "-DMINOR_VERSION=0", + "-include common/all-versions/VersionMacro.h", + ], + data: [ + "tests/apm_config_no_vx.xml", + "tests/apm_config_with_vx.xml", + ], + test_config: "tests/HalAudioV6_0GeneratorTest.xml", +} + +cc_test { + name: "HalAudioV7_0GeneratorTest", + defaults: ["VtsHalAudioTargetTest_defaults"], + srcs: [ + "7.0/Generators.cpp", + "tests/generators_tests.cpp", + ], + generated_headers: ["audio_policy_configuration_V7_0_parser"], + generated_sources: ["audio_policy_configuration_V7_0_parser"], + static_libs: [ + "android.hardware.audio@7.0", + "android.hardware.audio.common@7.0", + "android.hardware.audio.common@7.0-enums", + ], + cflags: [ + "-DMAJOR_VERSION=7", + "-DMINOR_VERSION=0", + "-include common/all-versions/VersionMacro.h", + ], + data: [ + "tests/apm_config_no_vx_7_0.xml", + "tests/apm_config_with_vx_7_0.xml", + ], + test_config: "tests/HalAudioV7_0GeneratorTest.xml", +} diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h index 61e99e8699..56939fe6e6 100644 --- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h +++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h @@ -59,6 +59,7 @@ #include "utility/ReturnIn.h" #include "utility/ValidateXml.h" +#include "AudioTestDefinitions.h" /** Provide version specific functions that are used in the generic tests */ #if MAJOR_VERSION == 2 #include "2.0/AudioPrimaryHidlHalUtils.h" @@ -107,7 +108,11 @@ static auto invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUP #include "DeviceManager.h" #if MAJOR_VERSION <= 6 #include "PolicyConfig.h" +#if MAJOR_VERSION == 6 +#include "6.0/Generators.h" +#endif #elif MAJOR_VERSION >= 7 +#include "7.0/Generators.h" #include "7.0/PolicyConfig.h" #endif @@ -175,9 +180,6 @@ TEST(CheckConfig, audioPolicyConfigurationValidation) { //////////////////// Test parameter types and definitions //////////////////// ////////////////////////////////////////////////////////////////////////////// -enum { PARAM_FACTORY_NAME, PARAM_DEVICE_NAME }; -using DeviceParameter = std::tuple; - static inline std::string DeviceParameterToString( const ::testing::TestParamInfo& info) { const auto& deviceName = std::get(info.param); @@ -509,24 +511,6 @@ INSTANTIATE_TEST_CASE_P(AudioPatchHidl, AudioPatchHidlTest, // list is empty, this isn't a problem. GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioPatchHidlTest); -// Nesting a tuple in another tuple allows to use GTest Combine function to generate -// all combinations of devices and configs. -enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS }; -#if MAJOR_VERSION <= 6 -enum { INDEX_INPUT, INDEX_OUTPUT }; -using DeviceConfigParameter = - std::tuple>; -#elif MAJOR_VERSION >= 7 -using DeviceConfigParameter = std::tuple>; -#endif - -#if MAJOR_VERSION >= 6 -const std::vector& getInputDeviceConfigParameters(); -const std::vector& getInputDeviceSingleConfigParameters(); -const std::vector& getOutputDeviceConfigParameters(); -const std::vector& getOutputDeviceSingleConfigParameters(); -#endif - #if MAJOR_VERSION >= 4 static std::string SanitizeStringForGTestName(const std::string& s) { std::string result = s; diff --git a/audio/core/all-versions/vts/functional/AudioTestDefinitions.h b/audio/core/all-versions/vts/functional/AudioTestDefinitions.h new file mode 100644 index 0000000000..5b14a216c9 --- /dev/null +++ b/audio/core/all-versions/vts/functional/AudioTestDefinitions.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 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. + */ + +#pragma once + +#include +#include +#include +#include + +// clang-format off +#include PATH(android/hardware/audio/FILE_VERSION/types.h) +#include PATH(android/hardware/audio/common/FILE_VERSION/types.h) +// clang-format on + +enum { PARAM_FACTORY_NAME, PARAM_DEVICE_NAME }; +using DeviceParameter = std::tuple; + +// Nesting a tuple in another tuple allows to use GTest Combine function to generate +// all combinations of devices and configs. +enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS }; +#if MAJOR_VERSION <= 6 +enum { INDEX_INPUT, INDEX_OUTPUT }; +using DeviceConfigParameter = + std::tuple>; +#elif MAJOR_VERSION >= 7 +using DeviceConfigParameter = + std::tuple>; +#endif diff --git a/audio/core/all-versions/vts/functional/ConfigHelper.h b/audio/core/all-versions/vts/functional/ConfigHelper.h index 1a1dbea939..a2bb1eecf0 100644 --- a/audio/core/all-versions/vts/functional/ConfigHelper.h +++ b/audio/core/all-versions/vts/functional/ConfigHelper.h @@ -16,10 +16,21 @@ #pragma once -// Code in this file uses 'getCachedPolicyConfig' -#ifndef AUDIO_PRIMARY_HIDL_HAL_TEST -#error Must be included from AudioPrimaryHidlTest.h -#endif +#include + +#include "PolicyConfig.h" + +// clang-format off +#include PATH(android/hardware/audio/FILE_VERSION/types.h) +#include PATH(android/hardware/audio/common/FILE_VERSION/types.h) +// clang-format on + +using ::android::hardware::audio::common::utils::EnumBitfield; +using ::android::hardware::audio::common::utils::mkEnumBitfield; + +// Forward declaration for functions that are substituted +// in generator unit tests. +const PolicyConfig& getCachedPolicyConfig(); ////////////////////////////////////////////////////////////////////////////// //////////////// Required and recommended audio format support /////////////// @@ -35,7 +46,7 @@ struct ConfigHelper { // FIXME: in the next audio HAL version, test all available devices static bool primaryHasMic() { auto& policyConfig = getCachedPolicyConfig(); - if (policyConfig.getStatus() != OK || policyConfig.getPrimaryModule() == nullptr) { + if (policyConfig.getStatus() != android::OK || policyConfig.getPrimaryModule() == nullptr) { return true; // Could not get the information, run all tests } auto getMic = [](auto& devs) { diff --git a/audio/core/all-versions/vts/functional/DeviceManager.h b/audio/core/all-versions/vts/functional/DeviceManager.h index 6efed7991e..6db78a77d6 100644 --- a/audio/core/all-versions/vts/functional/DeviceManager.h +++ b/audio/core/all-versions/vts/functional/DeviceManager.h @@ -16,9 +16,27 @@ #pragma once -// Note: it is assumed that this file is included from AudioPrimaryHidlTest.h -// and thus it doesn't have all '#include' and 'using' directives required -// for a standalone compilation. +#include + +#include + +#include +#include + +// clang-format off +#include PATH(android/hardware/audio/FILE_VERSION/IDevice.h) +#include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h) +#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) +// clang-format on + +#include "utility/ReturnIn.h" + +using ::android::sp; +using namespace ::android::hardware::audio::common::CPP_VERSION; +using namespace ::android::hardware::audio::common::test::utility; +using namespace ::android::hardware::audio::CPP_VERSION; template class InterfaceManager { @@ -56,7 +74,7 @@ class InterfaceManager { // 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(); + ::android::hardware::IPCThreadState::self()->flushCommands(); usleep(100 * 1000); } diff --git a/audio/core/all-versions/vts/functional/PolicyConfig.h b/audio/core/all-versions/vts/functional/PolicyConfig.h index c9e0c0dd5a..a94041c427 100644 --- a/audio/core/all-versions/vts/functional/PolicyConfig.h +++ b/audio/core/all-versions/vts/functional/PolicyConfig.h @@ -16,11 +16,19 @@ #pragma once -// Note: it is assumed that this file is included from AudioPrimaryHidlTest.h -// and thus it doesn't have all '#include' and 'using' directives required -// for a standalone compilation. +#include +#include +#include +#include #include +#include +#include + +#include "DeviceManager.h" + +using ::android::sp; +using ::android::status_t; struct PolicyConfigData { android::HwModuleCollection hwModules; @@ -42,28 +50,14 @@ class PolicyConfig : private PolicyConfigData, public android::AudioPolicyConfig break; } } - mStatus = android::deserializeAudioPolicyFile(mFilePath.c_str(), this); - if (mStatus == OK) { - mPrimaryModule = 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; - } - } - } - } + init(); + } + PolicyConfig(const std::string& configPath, const std::string& configFileName) + : android::AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices, + defaultOutputDevice), + mConfigFileName{configFileName}, + mFilePath{configPath + "/" + mConfigFileName} { + init(); } status_t getStatus() const { return mStatus; } std::string getError() const { @@ -88,8 +82,33 @@ class PolicyConfig : private PolicyConfigData, public android::AudioPolicyConfig } private: + void init() { + mStatus = android::deserializeAudioPolicyFileForVts(mFilePath.c_str(), this); + if (mStatus == android::OK) { + mPrimaryModule = 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; + } + } + } + } + } + const std::string mConfigFileName; - status_t mStatus = NO_INIT; + status_t mStatus = android::NO_INIT; std::string mFilePath; sp mPrimaryModule = nullptr; std::set mModulesWithDevicesNames; diff --git a/audio/core/all-versions/vts/functional/tests/HalAudioV6_0GeneratorTest.xml b/audio/core/all-versions/vts/functional/tests/HalAudioV6_0GeneratorTest.xml new file mode 100644 index 0000000000..0c85a05838 --- /dev/null +++ b/audio/core/all-versions/vts/functional/tests/HalAudioV6_0GeneratorTest.xml @@ -0,0 +1,34 @@ + + + + diff --git a/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml b/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml new file mode 100644 index 0000000000..2e794554c8 --- /dev/null +++ b/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml @@ -0,0 +1,34 @@ + + + + diff --git a/audio/core/all-versions/vts/functional/tests/apm_config_no_vx.xml b/audio/core/all-versions/vts/functional/tests/apm_config_no_vx.xml new file mode 100644 index 0000000000..61972b26d5 --- /dev/null +++ b/audio/core/all-versions/vts/functional/tests/apm_config_no_vx.xml @@ -0,0 +1,68 @@ + + + + + + + + + Speaker + Built-In Mic + + Speaker + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/core/all-versions/vts/functional/tests/apm_config_no_vx_7_0.xml b/audio/core/all-versions/vts/functional/tests/apm_config_no_vx_7_0.xml new file mode 100644 index 0000000000..abcdb1274c --- /dev/null +++ b/audio/core/all-versions/vts/functional/tests/apm_config_no_vx_7_0.xml @@ -0,0 +1,68 @@ + + + + + + + + + Speaker + Built-In Mic + + Speaker + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/core/all-versions/vts/functional/tests/apm_config_with_vx.xml b/audio/core/all-versions/vts/functional/tests/apm_config_with_vx.xml new file mode 100644 index 0000000000..aabb52e68c --- /dev/null +++ b/audio/core/all-versions/vts/functional/tests/apm_config_with_vx.xml @@ -0,0 +1,81 @@ + + + + + + + + + Speaker + Built-In Mic + + Speaker + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/core/all-versions/vts/functional/tests/apm_config_with_vx_7_0.xml b/audio/core/all-versions/vts/functional/tests/apm_config_with_vx_7_0.xml new file mode 100644 index 0000000000..8dd5f45db6 --- /dev/null +++ b/audio/core/all-versions/vts/functional/tests/apm_config_with_vx_7_0.xml @@ -0,0 +1,81 @@ + + + + + + + + + Speaker + Built-In Mic + + Speaker + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/core/all-versions/vts/functional/tests/generators_tests.cpp b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp new file mode 100644 index 0000000000..583ff01fc2 --- /dev/null +++ b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2021 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 +#include +#include + +#include +#include +#define LOG_TAG "Generators_Test" +#include + +#if MAJOR_VERSION == 6 +#include +#include "6.0/Generators.h" +#include "PolicyConfig.h" +#elif MAJOR_VERSION == 7 +#include "7.0/Generators.h" +#include "7.0/PolicyConfig.h" +#endif + +using namespace android; +using namespace ::android::hardware::audio::common::CPP_VERSION; +#if MAJOR_VERSION == 7 +namespace xsd { +using namespace ::android::audio::policy::configuration::CPP_VERSION; +} +#endif + +// Stringify the argument. +#define QUOTE(x) #x +#define STRINGIFY(x) QUOTE(x) + +struct PolicyConfigManager { + static PolicyConfigManager& getInstance() { + static PolicyConfigManager instance; + return instance; + } + bool init(const std::string& filePath, const std::string& fileName) { + mConfig = std::make_unique(filePath, fileName); + mDeviceParameters.clear(); + if (mConfig->getStatus() == OK) { + const auto devices = mConfig->getModulesWithDevicesNames(); + mDeviceParameters.reserve(devices.size()); + for (const auto& deviceName : devices) { + mDeviceParameters.emplace_back( + "android.hardware.audio.IDevicesFactory@" STRINGIFY(FILE_VERSION), + deviceName); + } + return true; + } else { + ALOGE("%s", mConfig->getError().c_str()); + return false; + } + } + const PolicyConfig& getConfig() { return *mConfig; } + const std::vector& getDeviceParameters() { return mDeviceParameters; } + + private: + std::unique_ptr mConfig; + std::vector mDeviceParameters; +}; + +// Test implementations +const PolicyConfig& getCachedPolicyConfig() { + return PolicyConfigManager::getInstance().getConfig(); +} + +const std::vector& getDeviceParameters() { + return PolicyConfigManager::getInstance().getDeviceParameters(); +} + +static const std::string kDataDir = "/data/local/tmp"; + +class GeneratorsTest : public ::testing::TestWithParam { + public: + static void validateConfig(const AudioConfig& config) { +#if MAJOR_VERSION == 6 + ASSERT_TRUE(audio_is_valid_format(static_cast(config.format))) + << "Audio format is invalid " << ::testing::PrintToString(config.format); + ASSERT_TRUE( + audio_channel_mask_is_valid(static_cast(config.channelMask))) + << "Audio channel mask is invalid " << ::testing::PrintToString(config.channelMask); +#elif MAJOR_VERSION == 7 + ASSERT_FALSE(xsd::isUnknownAudioFormat(config.base.format)) + << "Audio format is invalid " << ::testing::PrintToString(config.base.format); + ASSERT_FALSE(xsd::isUnknownAudioChannelMask(config.base.channelMask)) + << "Audio channel mask is invalid " + << ::testing::PrintToString(config.base.channelMask); +#endif + } + static void validateDeviceConfigs(const std::vector& params) { + for (const auto& param : params) { + ASSERT_NO_FATAL_FAILURE(validateConfig(std::get(param))); + } + } +}; + +TEST_P(GeneratorsTest, ValidateConfigs) { + ASSERT_TRUE(PolicyConfigManager::getInstance().init(kDataDir, GetParam())); + EXPECT_NE(nullptr, getCachedPolicyConfig().getPrimaryModule()); + EXPECT_FALSE(getCachedPolicyConfig().getModulesWithDevicesNames().empty()); + const auto allOutConfigs = generateOutputDeviceConfigParameters(false /*oneProfilePerDevice*/); + EXPECT_FALSE(allOutConfigs.empty()); + EXPECT_NO_FATAL_FAILURE(validateDeviceConfigs(allOutConfigs)); + const auto singleOutConfig = generateOutputDeviceConfigParameters(true /*oneProfilePerDevice*/); + EXPECT_FALSE(singleOutConfig.empty()); + EXPECT_NO_FATAL_FAILURE(validateDeviceConfigs(singleOutConfig)); + const auto allInConfigs = generateInputDeviceConfigParameters(false /*oneProfilePerDevice*/); + EXPECT_FALSE(allInConfigs.empty()); + EXPECT_NO_FATAL_FAILURE(validateDeviceConfigs(allInConfigs)); + const auto singleInConfig = generateInputDeviceConfigParameters(true /*oneProfilePerDevice*/); + EXPECT_FALSE(singleInConfig.empty()); + EXPECT_NO_FATAL_FAILURE(validateDeviceConfigs(singleInConfig)); +} + +// Target file names are the same for all versions, see 'HalAudioVx_0GeneratorTest.xml' test configs +INSTANTIATE_TEST_SUITE_P(Generators, GeneratorsTest, + ::testing::Values("apm_config_no_vx.xml", "apm_config_with_vx.xml"));