audio VTS: Refactor test parameter generation for I/O streams

Two changes that are necessary to test offloaded output:

1. Pass all mix port flags specified in the config to HAL when
   opening an output stream. Previously the generator was
   omitting the 'NON_BLOCKING' flag, however it is necessary
   for offloaded output to work. This also now passes
   the 'GAPLESS_OFFLOAD' flag to the stream opening call site.

2. Provide the DeviceAddress of the attached source/sink
   device to tests that use mix ports. Some tests were looking
   up the device address anyway. Also, HAL implementations
   seem to prefer to have the actual output device instead
   of 'DEFAULT' when opening offload streams.

Bug: 219767875
Test: atest VtsHalAudioV7_0TargetTest
Test: atest VtsHalAudioV7_1TargetTest
Test: atest HalAudioV7_0GeneratorTest
Change-Id: I0482376ecc7d6964f45f508a80716ffab18044b4
Merged-In: I0482376ecc7d6964f45f508a80716ffab18044b4
(cherry picked from commit 713d2c5590)
This commit is contained in:
Mikhail Naganov
2022-06-28 01:46:21 +00:00
parent 73e015a761
commit 1e703f182e
5 changed files with 68 additions and 87 deletions

View File

@@ -517,20 +517,10 @@ class PcmOnlyConfigOutputStreamTest : public OutputStreamTest {
}
bool canQueryPresentationPosition() const {
auto maybeSinkAddress =
getCachedPolicyConfig().getSinkDeviceForMixPort(getDeviceName(), getMixPortName());
// Returning 'true' when no sink is found so the test can fail later with a more clear
// problem description.
return !maybeSinkAddress.has_value() ||
!xsd::isTelephonyDevice(maybeSinkAddress.value().deviceType);
return !xsd::isTelephonyDevice(address.deviceType);
}
void createPatchIfNeeded() {
auto maybeSinkAddress =
getCachedPolicyConfig().getSinkDeviceForMixPort(getDeviceName(), getMixPortName());
ASSERT_TRUE(maybeSinkAddress.has_value())
<< "No sink device found for mix port " << getMixPortName() << " (module "
<< getDeviceName() << ")";
if (areAudioPatchesSupported()) {
AudioPortConfig source;
source.base.format.value(getConfig().base.format);
@@ -540,13 +530,13 @@ class PcmOnlyConfigOutputStreamTest : public OutputStreamTest {
source.ext.mix().ioHandle = helper.getIoHandle();
source.ext.mix().useCase.stream({});
AudioPortConfig sink;
sink.ext.device(maybeSinkAddress.value());
sink.ext.device(address);
EXPECT_OK(getDevice()->createAudioPatch(hidl_vec<AudioPortConfig>{source},
hidl_vec<AudioPortConfig>{sink},
returnIn(res, mPatchHandle)));
mHasPatch = res == Result::OK;
} else {
EXPECT_OK(stream->setDevices({maybeSinkAddress.value()}));
EXPECT_OK(stream->setDevices({address}));
}
}
@@ -556,10 +546,6 @@ class PcmOnlyConfigOutputStreamTest : public OutputStreamTest {
EXPECT_OK(getDevice()->releaseAudioPatch(mPatchHandle));
mHasPatch = false;
}
} else {
if (stream) {
EXPECT_OK(stream->setDevices({address}));
}
}
}
@@ -691,24 +677,12 @@ class PcmOnlyConfigInputStreamTest : public InputStreamTest {
InputStreamTest::TearDown();
}
bool canQueryCapturePosition() const {
auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
getDeviceName(), getMixPortName());
// Returning 'true' when no source is found so the test can fail later with a more clear
// problem description.
return !maybeSourceAddress.has_value() ||
!xsd::isTelephonyDevice(maybeSourceAddress.value().deviceType);
}
bool canQueryCapturePosition() const { return !xsd::isTelephonyDevice(address.deviceType); }
void createPatchIfNeeded() {
auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
getDeviceName(), getMixPortName());
ASSERT_TRUE(maybeSourceAddress.has_value())
<< "No source device found for mix port " << getMixPortName() << " (module "
<< getDeviceName() << ")";
if (areAudioPatchesSupported()) {
AudioPortConfig source;
source.ext.device(maybeSourceAddress.value());
source.ext.device(address);
AudioPortConfig sink;
sink.base.format.value(getConfig().base.format);
sink.base.sampleRateHz.value(getConfig().base.sampleRateHz);
@@ -721,7 +695,7 @@ class PcmOnlyConfigInputStreamTest : public InputStreamTest {
returnIn(res, mPatchHandle)));
mHasPatch = res == Result::OK;
} else {
EXPECT_OK(stream->setDevices({maybeSourceAddress.value()}));
EXPECT_OK(stream->setDevices({address}));
}
}
@@ -731,10 +705,6 @@ class PcmOnlyConfigInputStreamTest : public InputStreamTest {
EXPECT_OK(getDevice()->releaseAudioPatch(mPatchHandle));
mHasPatch = false;
}
} else {
if (stream) {
EXPECT_OK(stream->setDevices({address}));
}
}
}
@@ -864,14 +834,8 @@ TEST_P(MicrophoneInfoInputStreamTest, GetActiveMicrophones) {
}
ASSERT_OK(res);
auto maybeSourceAddress =
getCachedPolicyConfig().getSourceDeviceForMixPort(getDeviceName(), getMixPortName());
ASSERT_TRUE(maybeSourceAddress.has_value())
<< "No source device found for mix port " << getMixPortName() << " (module "
<< getDeviceName() << ")";
for (auto microphone : microphones) {
if (microphone.deviceAddress == maybeSourceAddress.value()) {
if (microphone.deviceAddress == address) {
StreamReader reader(stream.get(), stream->getBufferSize());
ASSERT_TRUE(reader.start());
reader.pause(); // This ensures that at least one read has happened.

View File

@@ -57,9 +57,6 @@ static std::vector<AudioConfig> combineAudioConfig(std::vector<xsd::AudioChannel
static std::tuple<std::vector<AudioInOutFlag>, bool> generateOutFlags(
const xsd::MixPorts::MixPort& mixPort) {
static const std::vector<AudioInOutFlag> offloadFlags = {
toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_DIRECT)};
std::vector<AudioInOutFlag> flags;
bool isOffload = false;
if (mixPort.hasFlags()) {
@@ -67,14 +64,10 @@ static std::tuple<std::vector<AudioInOutFlag>, bool> generateOutFlags(
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));
}
for (auto flag : xsdFlags) {
if (flag != xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_PRIMARY) {
flags.push_back(toString(flag));
}
} else {
flags = offloadFlags;
}
}
return {flags, isOffload};
@@ -100,11 +93,10 @@ std::vector<DeviceConfigParameter> generateOutputDeviceConfigParameters(bool one
if (!module || !module->getFirstMixPorts()) break;
for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
if (mixPort.getRole() != xsd::Role::source) continue; // not an output profile
if (getCachedPolicyConfig()
.getAttachedSinkDeviceForMixPort(moduleName, mixPort.getName())
.empty()) {
continue; // no attached device
}
const auto attachedDeviceAddress =
getCachedPolicyConfig().getDeviceAddressOfSinkDeviceAttachedToMixPort(
moduleName, mixPort.getName());
if (!attachedDeviceAddress.has_value()) continue;
auto [flags, isOffload] = generateOutFlags(mixPort);
for (const auto& profile : mixPort.getProfile()) {
if (!profile.hasFormat() || !profile.hasSamplingRates() ||
@@ -118,7 +110,8 @@ std::vector<DeviceConfigParameter> generateOutputDeviceConfigParameters(bool one
if (isOffload) {
config.offloadInfo.info(generateOffloadInfo(config.base));
}
result.emplace_back(device, mixPort.getName(), config, flags);
result.emplace_back(device, mixPort.getName(), attachedDeviceAddress.value(),
config, flags);
if (oneProfilePerDevice) break;
}
if (oneProfilePerDevice) break;
@@ -162,13 +155,16 @@ const std::vector<DeviceConfigParameter>& getOutputDeviceInvalidConfigParameters
profile.getFormat(),
static_cast<uint32_t>(profile.getSamplingRates()[0]),
toString(profile.getChannelMasks()[0])};
DeviceAddress defaultDevice = {
toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT), {}};
{
AudioConfig config{.base = validBase};
config.base.channelMask = "random_string";
if (isOffload) {
config.offloadInfo.info(generateOffloadInfo(validBase));
}
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
{
AudioConfig config{.base = validBase};
@@ -176,7 +172,8 @@ const std::vector<DeviceConfigParameter>& getOutputDeviceInvalidConfigParameters
if (isOffload) {
config.offloadInfo.info(generateOffloadInfo(validBase));
}
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
if (generateInvalidFlags) {
AudioConfig config{.base = validBase};
@@ -184,32 +181,37 @@ const std::vector<DeviceConfigParameter>& getOutputDeviceInvalidConfigParameters
config.offloadInfo.info(generateOffloadInfo(validBase));
}
std::vector<AudioInOutFlag> flags = {"random_string", ""};
result.emplace_back(device, mixPort.getName(), config, flags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
flags);
}
if (isOffload) {
{
AudioConfig config{.base = validBase};
config.offloadInfo.info(generateOffloadInfo(validBase));
config.offloadInfo.info().base.channelMask = "random_string";
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
{
AudioConfig config{.base = validBase};
config.offloadInfo.info(generateOffloadInfo(validBase));
config.offloadInfo.info().base.format = "random_string";
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
{
AudioConfig config{.base = validBase};
config.offloadInfo.info(generateOffloadInfo(validBase));
config.offloadInfo.info().streamType = "random_string";
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
{
AudioConfig config{.base = validBase};
config.offloadInfo.info(generateOffloadInfo(validBase));
config.offloadInfo.info().usage = "random_string";
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
hasOffloadConfig = true;
} else {
@@ -233,11 +235,10 @@ std::vector<DeviceConfigParameter> generateInputDeviceConfigParameters(bool oneP
if (!module || !module->getFirstMixPorts()) break;
for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
if (mixPort.getRole() != xsd::Role::sink) continue; // not an input profile
if (getCachedPolicyConfig()
.getAttachedSourceDeviceForMixPort(moduleName, mixPort.getName())
.empty()) {
continue; // no attached device
}
const auto attachedDeviceAddress =
getCachedPolicyConfig().getDeviceAddressOfSourceDeviceAttachedToMixPort(
moduleName, mixPort.getName());
if (!attachedDeviceAddress.has_value()) continue;
std::vector<AudioInOutFlag> flags;
if (mixPort.hasFlags()) {
std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(),
@@ -250,7 +251,8 @@ std::vector<DeviceConfigParameter> generateInputDeviceConfigParameters(bool oneP
auto configs = combineAudioConfig(profile.getChannelMasks(),
profile.getSamplingRates(), profile.getFormat());
for (const auto& config : configs) {
result.emplace_back(device, mixPort.getName(), config, flags);
result.emplace_back(device, mixPort.getName(), attachedDeviceAddress.value(),
config, flags);
if (oneProfilePerDevice) break;
}
if (oneProfilePerDevice) break;
@@ -298,20 +300,25 @@ const std::vector<DeviceConfigParameter>& getInputDeviceInvalidConfigParameters(
profile.getFormat(),
static_cast<uint32_t>(profile.getSamplingRates()[0]),
toString(profile.getChannelMasks()[0])};
DeviceAddress defaultDevice = {
toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT), {}};
{
AudioConfig config{.base = validBase};
config.base.channelMask = "random_string";
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
{
AudioConfig config{.base = validBase};
config.base.format = "random_string";
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
if (generateInvalidFlags) {
AudioConfig config{.base = validBase};
std::vector<AudioInOutFlag> flags = {"random_string", ""};
result.emplace_back(device, mixPort.getName(), config, flags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
flags);
}
hasConfig = true;
break;

View File

@@ -61,6 +61,18 @@ class PolicyConfig {
const std::set<std::string>& getModulesWithDevicesNames() const {
return mModulesWithDevicesNames;
}
std::optional<DeviceAddress> getDeviceAddressOfSinkDeviceAttachedToMixPort(
const std::string& moduleName, const std::string& mixPortName) const {
const auto attachedDevicePort = getAttachedSinkDeviceForMixPort(moduleName, mixPortName);
if (attachedDevicePort.empty()) return {};
return getDeviceAddressOfDevicePort(moduleName, attachedDevicePort);
}
std::optional<DeviceAddress> getDeviceAddressOfSourceDeviceAttachedToMixPort(
const std::string& moduleName, const std::string& mixPortName) const {
const auto attachedDevicePort = getAttachedSourceDeviceForMixPort(moduleName, mixPortName);
if (attachedDevicePort.empty()) return {};
return getDeviceAddressOfDevicePort(moduleName, attachedDevicePort);
}
std::string getAttachedSinkDeviceForMixPort(const std::string& moduleName,
const std::string& mixPortName) const {
return findAttachedDevice(getAttachedDevices(moduleName),
@@ -84,8 +96,6 @@ class PolicyConfig {
const std::vector<std::string>& getAttachedDevices(const std::string& moduleName) const;
std::optional<DeviceAddress> getDeviceAddressOfDevicePort(
const std::string& moduleName, const std::string& devicePortName) const;
std::string getDevicePortTagNameFromType(const std::string& moduleName,
const AudioDevice& deviceType) const;
std::set<std::string> getSinkDevicesForMixPort(const std::string& moduleName,
const std::string& mixPortName) const;
std::set<std::string> getSourceDevicesForMixPort(const std::string& moduleName,

View File

@@ -617,7 +617,8 @@ static std::string DeviceConfigParameterToString(
std::get<PARAM_FLAGS>(info.param)));
#elif MAJOR_VERSION >= 7
const auto configPart =
std::to_string(config.base.sampleRateHz) + "_" +
::testing::PrintToString(std::get<PARAM_ATTACHED_DEV_ADDR>(info.param).deviceType) +
"_" + std::to_string(config.base.sampleRateHz) + "_" +
// The channel masks and flags are vectors of strings, just need to sanitize them.
SanitizeStringForGTestName(::testing::PrintToString(config.base.channelMask)) + "_" +
SanitizeStringForGTestName(::testing::PrintToString(std::get<PARAM_FLAGS>(info.param)));
@@ -658,6 +659,9 @@ class AudioHidlTestWithDeviceConfigParameter
std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam())));
}
#elif MAJOR_VERSION >= 7
DeviceAddress getAttachedDeviceAddress() const {
return std::get<PARAM_ATTACHED_DEV_ADDR>(GetParam());
}
hidl_vec<AudioInOutFlag> getInputFlags() const { return std::get<PARAM_FLAGS>(GetParam()); }
hidl_vec<AudioInOutFlag> getOutputFlags() const { return std::get<PARAM_FLAGS>(GetParam()); }
#endif
@@ -1047,7 +1051,7 @@ class OutputStreamTest
#if MAJOR_VERSION <= 6
address.device = AudioDevice::OUT_DEFAULT;
#elif MAJOR_VERSION >= 7
address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT);
address = getAttachedDeviceAddress();
#endif
const AudioConfig& config = getConfig();
auto flags = getOutputFlags();
@@ -1243,16 +1247,11 @@ class InputStreamTest
#if MAJOR_VERSION <= 6
address.device = AudioDevice::IN_DEFAULT;
#elif MAJOR_VERSION >= 7
auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
getDeviceName(), getMixPortName());
address = getAttachedDeviceAddress();
auto& metadata = initMetadata.tracks[0];
if (maybeSourceAddress.has_value() &&
!xsd::isTelephonyDevice(maybeSourceAddress.value().deviceType)) {
address = maybeSourceAddress.value();
if (!xsd::isTelephonyDevice(address.deviceType)) {
metadata.source = toString(xsd::AudioSource::AUDIO_SOURCE_UNPROCESSED);
metadata.channelMask = getConfig().base.channelMask;
} else {
address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT);
}
#if MAJOR_VERSION == 7 && MINOR_VERSION >= 1
auto flagsIt = std::find(flags.begin(), flags.end(),

View File

@@ -39,9 +39,10 @@ using DeviceConfigParameter = std::tuple<
std::variant<android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioInputFlag,
android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioOutputFlag>>;
#elif MAJOR_VERSION >= 7
enum { PARAM_DEVICE, PARAM_PORT_NAME, PARAM_CONFIG, PARAM_FLAGS };
enum { PARAM_DEVICE, PARAM_PORT_NAME, PARAM_ATTACHED_DEV_ADDR, PARAM_CONFIG, PARAM_FLAGS };
using DeviceConfigParameter =
std::tuple<DeviceParameter, std::string,
android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::DeviceAddress,
android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioConfig,
std::vector<android::hardware::audio::CORE_TYPES_CPP_VERSION::AudioInOutFlag>>;
#endif