Audio: Add VTS tests for invalid enum-strings, Part 1
Add tests that try passing invalid enum-string values to HAL
methods taking enum-strings. Fix issues found in the default
wrapper.
Interface updates:
- Update AudioConfig structure to indicate whether
AudioOffloadInfo is specified.
- Add return value to IStreamIn.updateSinkMetadata
and IStreamOut.updateSourceMetadata to provide indication
of invalid arguments.
- Specify the behavior of IDevice.open{Input|Output}Stream
in the case of invalid arguments vs. rejected config.
Bug: 142480271
Test: atest VtsHalAudioV6_0TargetTest
Test: atest VtsHalAudioV7_0TargetTest
with side-loaded V7 default wrapper
Change-Id: I6bd7be3869cc7a8d5d00506565bbf0b3a050b630
diff --git a/audio/common/all-versions/default/7.0/HidlUtils.cpp b/audio/common/all-versions/default/7.0/HidlUtils.cpp
index c985a70..de19faf 100644
--- a/audio/common/all-versions/default/7.0/HidlUtils.cpp
+++ b/audio/common/all-versions/default/7.0/HidlUtils.cpp
@@ -21,6 +21,7 @@
#include <log/log.h>
#include <android_audio_policy_configuration_V7_0-enums.h>
+#include <common/all-versions/HidlSupport.h>
#include <common/all-versions/VersionUtils.h>
#include "HidlUtils.h"
@@ -306,7 +307,12 @@
audio_config_base_t halConfigBase = {halConfig.sample_rate, halConfig.channel_mask,
halConfig.format};
CONVERT_CHECKED(audioConfigBaseFromHal(halConfigBase, isInput, &config->base), result);
- CONVERT_CHECKED(audioOffloadInfoFromHal(halConfig.offload_info, &config->offloadInfo), result);
+ if (halConfig.offload_info.sample_rate != 0) {
+ config->offloadInfo.info({});
+ CONVERT_CHECKED(
+ audioOffloadInfoFromHal(halConfig.offload_info, &config->offloadInfo.info()),
+ result);
+ }
config->frameCount = halConfig.frame_count;
return result;
}
@@ -319,7 +325,11 @@
halConfig->sample_rate = halConfigBase.sample_rate;
halConfig->channel_mask = halConfigBase.channel_mask;
halConfig->format = halConfigBase.format;
- CONVERT_CHECKED(audioOffloadInfoToHal(config.offloadInfo, &halConfig->offload_info), result);
+ if (config.offloadInfo.getDiscriminator() ==
+ AudioConfig::OffloadInfo::hidl_discriminator::info) {
+ CONVERT_CHECKED(audioOffloadInfoToHal(config.offloadInfo.info(), &halConfig->offload_info),
+ result);
+ }
halConfig->frame_count = config.frameCount;
return result;
}
@@ -800,6 +810,47 @@
return result;
}
+status_t HidlUtils::audioTagsFromHal(const char* halTags, hidl_vec<AudioTag>* tags) {
+ std::vector<std::string> strTags = utils::splitString(halTags, sAudioTagSeparator);
+ status_t result = NO_ERROR;
+ tags->resize(strTags.size());
+ size_t to = 0;
+ for (size_t from = 0; from < strTags.size(); ++from) {
+ if (xsd::isVendorExtension(strTags[from])) {
+ (*tags)[to++] = strTags[from];
+ } else {
+ result = BAD_VALUE;
+ }
+ }
+ if (to != strTags.size()) {
+ tags->resize(to);
+ }
+ return result;
+}
+
+status_t HidlUtils::audioTagsToHal(const hidl_vec<AudioTag>& tags, char* halTags) {
+ memset(halTags, 0, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ status_t result = NO_ERROR;
+ std::ostringstream halTagsBuffer;
+ bool hasValue = false;
+ for (const auto& tag : tags) {
+ if (hasValue) {
+ halTagsBuffer << sAudioTagSeparator;
+ }
+ if (xsd::isVendorExtension(tag) && strchr(tag.c_str(), sAudioTagSeparator) == nullptr) {
+ halTagsBuffer << tag;
+ hasValue = true;
+ } else {
+ result = BAD_VALUE;
+ }
+ }
+ std::string fullHalTags{std::move(halTagsBuffer.str())};
+ strncpy(halTags, fullHalTags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ CONVERT_CHECKED(fullHalTags.length() <= AUDIO_ATTRIBUTES_TAGS_MAX_SIZE ? NO_ERROR : BAD_VALUE,
+ result);
+ return result;
+}
+
status_t HidlUtils::deviceAddressFromHal(audio_devices_t halDeviceType,
const char* halDeviceAddress, DeviceAddress* device) {
status_t result = NO_ERROR;
diff --git a/audio/common/all-versions/default/HidlUtils.h b/audio/common/all-versions/default/HidlUtils.h
index d8b7ba4..8e9275c 100644
--- a/audio/common/all-versions/default/HidlUtils.h
+++ b/audio/common/all-versions/default/HidlUtils.h
@@ -109,6 +109,8 @@
AudioStreamType* streamType);
static status_t audioStreamTypeToHal(const AudioStreamType& streamType,
audio_stream_type_t* halStreamType);
+ static status_t audioTagsFromHal(const char* halTags, hidl_vec<AudioTag>* tags);
+ static status_t audioTagsToHal(const hidl_vec<AudioTag>& tags, char* halTags);
private:
static status_t audioIndexChannelMaskFromHal(audio_channel_mask_t halChannelMask,
diff --git a/audio/common/all-versions/default/tests/hidlutils_tests.cpp b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
index 22571c0..fef88b4 100644
--- a/audio/common/all-versions/default/tests/hidlutils_tests.cpp
+++ b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
@@ -589,16 +589,29 @@
config.base.sampleRateHz = 44100;
config.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
- config.offloadInfo.base = config.base;
- config.offloadInfo.streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC);
- config.offloadInfo.bitRatePerSecond = 320;
- config.offloadInfo.durationMicroseconds = -1;
- config.offloadInfo.bitWidth = 16;
- config.offloadInfo.bufferSize = 1024;
- config.offloadInfo.usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA);
- config.offloadInfo.encapsulationMode = AudioEncapsulationMode::ELEMENTARY_STREAM;
- config.offloadInfo.contentId = 42;
- config.offloadInfo.syncId = 13;
+ audio_config_t halConfig;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigToHal(config, &halConfig));
+ AudioConfig configBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigFromHal(halConfig, false /*isInput*/, &configBack));
+ EXPECT_EQ(config, configBack);
+}
+
+TEST(HidlUtils, ConvertConfigWithOffloadInfo) {
+ AudioConfig config = {};
+ config.base.sampleRateHz = 44100;
+ config.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+ config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+ config.offloadInfo.info(
+ AudioOffloadInfo{.base = config.base,
+ .streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC),
+ .bitRatePerSecond = 320,
+ .durationMicroseconds = -1,
+ .bitWidth = 16,
+ .bufferSize = 1024,
+ .usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
+ .encapsulationMode = AudioEncapsulationMode::ELEMENTARY_STREAM,
+ .contentId = 42,
+ .syncId = 13});
audio_config_t halConfig;
EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigToHal(config, &halConfig));
AudioConfig configBack;
@@ -707,3 +720,43 @@
EXPECT_EQ(NO_ERROR, HidlUtils::audioPortToHal(portBack, &halPortBack));
EXPECT_TRUE(audio_ports_v7_are_equal(&halPort, &halPortBack));
}
+
+TEST(HidlUtils, ConvertInvalidAudioTags) {
+ char halTag[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE] = {};
+
+ hidl_vec<AudioTag> emptyTag = {{""}};
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioTagsToHal(emptyTag, halTag));
+
+ hidl_vec<AudioTag> longTag = {{std::string(AUDIO_ATTRIBUTES_TAGS_MAX_SIZE + 1, 'A')}};
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioTagsToHal(longTag, halTag));
+
+ hidl_vec<AudioTag> tagSeparator = {
+ {std::string(AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1, HidlUtils::sAudioTagSeparator)}};
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioTagsToHal(tagSeparator, halTag));
+
+ hidl_vec<AudioTag> notExtensions = {{"random string", "VX_", "VX_GOOGLE_$$"}};
+ EXPECT_EQ(BAD_VALUE, HidlUtils::audioTagsToHal(notExtensions, halTag));
+}
+
+TEST(HidlUtils, ConvertAudioTags) {
+ hidl_vec<AudioTag> emptyTags;
+ char halEmptyTags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE] = {};
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsToHal(emptyTags, halEmptyTags));
+ hidl_vec<AudioTag> emptyTagsBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsFromHal(halEmptyTags, &emptyTagsBack));
+ EXPECT_EQ(emptyTags, emptyTagsBack);
+
+ hidl_vec<AudioTag> oneTag = {{"VX_GOOGLE_VR"}};
+ char halOneTag[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE] = {};
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsToHal(oneTag, halOneTag));
+ hidl_vec<AudioTag> oneTagBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsFromHal(halOneTag, &oneTagBack));
+ EXPECT_EQ(oneTag, oneTagBack);
+
+ hidl_vec<AudioTag> twoTags = {{"VX_GOOGLE_VR_42", "VX_GOOGLE_1E100"}};
+ char halTwoTags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE] = {};
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsToHal(twoTags, halTwoTags));
+ hidl_vec<AudioTag> twoTagsBack;
+ EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsFromHal(halTwoTags, &twoTagsBack));
+ EXPECT_EQ(twoTags, twoTagsBack);
+}
diff --git a/audio/common/all-versions/util/include/common/all-versions/HidlSupport.h b/audio/common/all-versions/util/include/common/all-versions/HidlSupport.h
index b514a43..d7802cf 100644
--- a/audio/common/all-versions/util/include/common/all-versions/HidlSupport.h
+++ b/audio/common/all-versions/util/include/common/all-versions/HidlSupport.h
@@ -20,6 +20,9 @@
#include <hidl/HidlSupport.h>
#include <algorithm>
+#include <sstream>
+#include <string>
+#include <vector>
namespace android::hardware::audio::common::utils {
@@ -29,6 +32,16 @@
return std::find(values.begin(), values.end(), e) != values.end();
}
+static inline std::vector<std::string> splitString(const std::string& s, char separator) {
+ std::istringstream iss(s);
+ std::string t;
+ std::vector<std::string> result;
+ while (std::getline(iss, t, separator)) {
+ result.push_back(std::move(t));
+ }
+ return result;
+}
+
} // namespace android::hardware::audio::common::utils
#endif // android_hardware_audio_common_HidlSupport_H_