audio: Run VTS tests for streams of non-primary modules for HAL V6
Implement parsing of AudioPolicyManager config for finding out supported format configurations of streams. This only applies when running tests for HAL V6. Previously format configurations mandated by CDD were used for testing, this does not work well for non-primary modules. Fix the following issues found while running the tests for "r_submix" and "msd" modules: - IStream::getSupportedFormats must return a status to indicate that this capability is not supported by HAL; - it is allowed for IStream::setDevices to return NOT_SUPPORTED status. Other changes: - Factor out helper functions for generating format configurations; - Fix generation of the channel mask component in the names of tests that use AudioConfig, add sampling rate to test names. Bug: 141989952 Bug: 141847510 Test: atest VtsHalAudioV5_0TargetTest atest VtsHalAudioV6_0TargetTest also, run modified V5_0 test using generators for V6_0 Change-Id: If0d330881901908e546baab89f63d3333003e355
This commit is contained in:
parent
c8a6fd93da
commit
5b8fc1298a
7 changed files with 349 additions and 120 deletions
|
@ -123,9 +123,11 @@ interface IStream {
|
|||
* equivalent to getting AUDIO_PARAMETER_STREAM_SUP_FORMATS on the legacy
|
||||
* HAL.
|
||||
*
|
||||
* @return retval operation completion status.
|
||||
* @return formats supported audio formats.
|
||||
* Must be non empty if retval is OK.
|
||||
*/
|
||||
getSupportedFormats() generates (vec<AudioFormat> formats);
|
||||
getSupportedFormats() generates (Result retval, vec<AudioFormat> formats);
|
||||
|
||||
/**
|
||||
* Sets the audio format of the stream. Calling this method is equivalent to
|
||||
|
|
|
@ -175,8 +175,17 @@ Return<void> Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
|
|||
for (size_t i = 0; i < halFormats.size(); ++i) {
|
||||
formats[i] = AudioFormat(halFormats[i]);
|
||||
}
|
||||
// Legacy get_parameter does not return a status_t, thus can not advertise of failure.
|
||||
// Note that the method must not return an empty list if this capability is supported.
|
||||
if (formats.size() == 0) {
|
||||
result = Result::NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
#if MAJOR_VERSION <= 5
|
||||
_hidl_cb(formats);
|
||||
#elif MAJOR_VERSION >= 6
|
||||
_hidl_cb(result, formats);
|
||||
#endif
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
|
|
@ -172,9 +172,10 @@ static void testSetDevices(IStream* stream, const DeviceAddress& address) {
|
|||
DeviceAddress otherAddress = address;
|
||||
otherAddress.device = (address.device & AudioDevice::BIT_IN) == 0 ? AudioDevice::OUT_SPEAKER
|
||||
: AudioDevice::IN_BUILTIN_MIC;
|
||||
EXPECT_OK(stream->setDevices({otherAddress}));
|
||||
EXPECT_RESULT(okOrNotSupported, stream->setDevices({otherAddress}));
|
||||
|
||||
ASSERT_OK(stream->setDevices({address})); // Go back to the original value
|
||||
ASSERT_RESULT(okOrNotSupported,
|
||||
stream->setDevices({address})); // Go back to the original value
|
||||
}
|
||||
|
||||
TEST_IO_STREAM(SetDevices, "Check that the stream can be rerouted to SPEAKER or BUILTIN_MIC",
|
||||
|
|
|
@ -75,11 +75,18 @@ struct GetSupported {
|
|||
return res;
|
||||
}
|
||||
|
||||
#if MAJOR_VERSION <= 5
|
||||
static Result formats(IStream* stream, hidl_vec<AudioFormat>& capabilities) {
|
||||
EXPECT_OK(stream->getSupportedFormats(returnIn(capabilities)));
|
||||
// TODO: this should be an optional function
|
||||
return Result::OK;
|
||||
}
|
||||
#elif MAJOR_VERSION >= 6
|
||||
static Result formats(IStream* stream, hidl_vec<AudioFormat>& capabilities) {
|
||||
Result res;
|
||||
EXPECT_OK(stream->getSupportedFormats(returnIn(res, capabilities)));
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
|
|
@ -64,3 +64,77 @@ const std::vector<DeviceParameter>& getDeviceParameters() {
|
|||
}();
|
||||
return parameters;
|
||||
}
|
||||
|
||||
const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
|
||||
static std::vector<DeviceConfigParameter> parameters = [] {
|
||||
std::vector<DeviceConfigParameter> result;
|
||||
for (const auto& device : getDeviceParameters()) {
|
||||
auto module =
|
||||
getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
|
||||
for (const auto& ioProfile : module->getOutputProfiles()) {
|
||||
for (const auto& profile : ioProfile->getAudioProfiles()) {
|
||||
auto configs = ConfigHelper::combineAudioConfig(profile->getChannels(),
|
||||
profile->getSampleRates(),
|
||||
profile->getFormat());
|
||||
auto flags = ioProfile->getFlags();
|
||||
for (auto& config : configs) {
|
||||
// Some combinations of flags declared in the config file require special
|
||||
// treatment.
|
||||
bool special = false;
|
||||
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(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD));
|
||||
special = true;
|
||||
}
|
||||
if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
|
||||
!(flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
|
||||
result.emplace_back(device, config,
|
||||
AudioOutputFlag(AUDIO_OUTPUT_FLAG_DIRECT));
|
||||
special = true;
|
||||
}
|
||||
if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) { // ignore the flag
|
||||
flags &= ~AUDIO_OUTPUT_FLAG_PRIMARY;
|
||||
}
|
||||
if (!special) {
|
||||
result.emplace_back(device, config, AudioOutputFlag(flags));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}();
|
||||
return parameters;
|
||||
}
|
||||
|
||||
const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters() {
|
||||
static std::vector<DeviceConfigParameter> parameters = [] {
|
||||
std::vector<DeviceConfigParameter> result;
|
||||
for (const auto& device : getDeviceParameters()) {
|
||||
auto module =
|
||||
getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
|
||||
for (const auto& ioProfile : module->getInputProfiles()) {
|
||||
for (const auto& profile : ioProfile->getAudioProfiles()) {
|
||||
auto configs = ConfigHelper::combineAudioConfig(profile->getChannels(),
|
||||
profile->getSampleRates(),
|
||||
profile->getFormat());
|
||||
for (const auto& config : configs) {
|
||||
result.emplace_back(device, config, AudioInputFlag(ioProfile->getFlags()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}();
|
||||
return parameters;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
@ -97,7 +98,9 @@ using ::android::hardware::kSynchronizedReadWrite;
|
|||
using ::android::hardware::MessageQueue;
|
||||
using ::android::hardware::MQDescriptorSync;
|
||||
using ::android::hardware::Return;
|
||||
using ::android::hardware::audio::common::utils::EnumBitfield;
|
||||
using ::android::hardware::audio::common::utils::mkEnumBitfield;
|
||||
using ::android::hardware::details::toHexString;
|
||||
|
||||
using namespace ::android::hardware::audio::common::CPP_VERSION;
|
||||
using namespace ::android::hardware::audio::common::test::utility;
|
||||
|
@ -231,6 +234,9 @@ class PolicyConfig : private PolicyConfigData, public AudioPolicyConfig {
|
|||
}
|
||||
}
|
||||
const std::string& getFilePath() const { return mFilePath; }
|
||||
sp<const HwModule> getModuleFromName(const std::string& name) const {
|
||||
return getHwModules().getModuleFromName(name.c_str());
|
||||
}
|
||||
sp<const HwModule> getPrimaryModule() const { return mPrimaryModule; }
|
||||
const std::set<std::string>& getModulesWithDevicesNames() const {
|
||||
return mModulesWithDevicesNames;
|
||||
|
@ -550,91 +556,28 @@ TEST_P(AudioPatchHidlTest, AudioPatches) {
|
|||
INSTANTIATE_TEST_CASE_P(AudioPatchHidl, AudioPatchHidlTest,
|
||||
::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////// Required and recommended audio format support ///////////////
|
||||
// From:
|
||||
// https://source.android.com/compatibility/android-cdd.html#5_4_audio_recording
|
||||
// From:
|
||||
// https://source.android.com/compatibility/android-cdd.html#5_5_audio_playback
|
||||
/////////// TODO: move to the beginning of the file for easier update ////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ConfigHelper {
|
||||
// for retro compatibility only test the primary device IN_BUILTIN_MIC
|
||||
// FIXME: in the next audio HAL version, test all available devices
|
||||
static bool primaryHasMic() {
|
||||
auto& policyConfig = getCachedPolicyConfig();
|
||||
if (policyConfig.getStatus() != OK || policyConfig.getPrimaryModule() == nullptr) {
|
||||
return true; // Could not get the information, run all tests
|
||||
}
|
||||
auto getMic = [](auto& devs) { return devs.getDevice(
|
||||
AUDIO_DEVICE_IN_BUILTIN_MIC, {}, AUDIO_FORMAT_DEFAULT); };
|
||||
auto primaryMic = getMic(policyConfig.getPrimaryModule()->getDeclaredDevices());
|
||||
auto availableMic = getMic(policyConfig.getAvailableInputDevices());
|
||||
|
||||
return primaryMic != nullptr && primaryMic->equals(availableMic);
|
||||
}
|
||||
|
||||
// Cache result ?
|
||||
static const vector<AudioConfig> getRequiredSupportPlaybackAudioConfig() {
|
||||
return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
|
||||
{8000, 11025, 16000, 22050, 32000, 44100},
|
||||
{AudioFormat::PCM_16_BIT});
|
||||
}
|
||||
|
||||
static const vector<AudioConfig> getRecommendedSupportPlaybackAudioConfig() {
|
||||
return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
|
||||
{24000, 48000}, {AudioFormat::PCM_16_BIT});
|
||||
}
|
||||
|
||||
static const vector<AudioConfig> getSupportedPlaybackAudioConfig() {
|
||||
// TODO: retrieve audio config supported by the platform
|
||||
// as declared in the policy configuration
|
||||
return {};
|
||||
}
|
||||
|
||||
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});
|
||||
}
|
||||
static const vector<AudioConfig> getSupportedCaptureAudioConfig() {
|
||||
// TODO: retrieve audio config supported by the platform
|
||||
// as declared in the policy configuration
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
static const vector<AudioConfig> combineAudioConfig(vector<AudioChannelMask> channelMasks,
|
||||
vector<uint32_t> sampleRates,
|
||||
vector<AudioFormat> formats) {
|
||||
vector<AudioConfig> configs;
|
||||
for (auto channelMask : channelMasks) {
|
||||
for (auto sampleRate : sampleRates) {
|
||||
for (auto format : formats) {
|
||||
AudioConfig config{};
|
||||
// leave offloadInfo to 0
|
||||
config.channelMask = mkEnumBitfield(channelMask);
|
||||
config.sampleRateHz = sampleRate;
|
||||
config.format = format;
|
||||
// FIXME: leave frameCount to 0 ?
|
||||
configs.push_back(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
return configs;
|
||||
}
|
||||
};
|
||||
|
||||
// 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 };
|
||||
using DeviceConfigParameter = std::tuple<DeviceParameter, AudioConfig>;
|
||||
enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS };
|
||||
enum { INDEX_INPUT, INDEX_OUTPUT };
|
||||
using DeviceConfigParameter =
|
||||
std::tuple<DeviceParameter, AudioConfig, std::variant<AudioInputFlag, AudioOutputFlag>>;
|
||||
|
||||
#if MAJOR_VERSION >= 6
|
||||
const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters();
|
||||
const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters();
|
||||
#endif
|
||||
|
||||
#if MAJOR_VERSION >= 4
|
||||
static string SanitizeStringForGTestName(const string& s) {
|
||||
string result = s;
|
||||
for (size_t i = 0; i < result.size(); i++) {
|
||||
// gtest test names must only contain alphanumeric characters
|
||||
if (!std::isalnum(result[i])) result[i] = '_';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Generate a test name based on an audio config.
|
||||
*
|
||||
|
@ -652,7 +595,32 @@ static string DeviceConfigParameterToString(
|
|||
((config.channelMask == mkEnumBitfield(AudioChannelMask::OUT_MONO) ||
|
||||
config.channelMask == mkEnumBitfield(AudioChannelMask::IN_MONO))
|
||||
? "MONO"
|
||||
: ::testing::PrintToString(config.channelMask));
|
||||
#if MAJOR_VERSION == 2
|
||||
: ::testing::PrintToString(config.channelMask)
|
||||
#elif MAJOR_VERSION >= 4
|
||||
// In V4 and above the channel mask is a bitfield.
|
||||
// Printing its value using HIDL's toString for a bitfield emits a lot of extra
|
||||
// text due to overlapping constant values. Instead, we print the bitfield value
|
||||
// as if it was a single value + its hex representation
|
||||
: SanitizeStringForGTestName(
|
||||
::testing::PrintToString(AudioChannelMask(config.channelMask)) + "_" +
|
||||
toHexString(config.channelMask))
|
||||
#endif
|
||||
) +
|
||||
"_" +
|
||||
#if MAJOR_VERSION == 2
|
||||
std::visit([](auto&& arg) -> std::string { return ::testing::PrintToString(arg); },
|
||||
std::get<PARAM_FLAGS>(info.param));
|
||||
#elif MAJOR_VERSION >= 4
|
||||
SanitizeStringForGTestName(std::visit(
|
||||
[](auto&& arg) -> std::string {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
// Need to use FQN of toString to avoid confusing the compiler
|
||||
return ::android::hardware::audio::common::CPP_VERSION::toString<T>(
|
||||
hidl_bitfield<T>(arg));
|
||||
},
|
||||
std::get<PARAM_FLAGS>(info.param)));
|
||||
#endif
|
||||
}
|
||||
|
||||
class AudioHidlTestWithDeviceConfigParameter
|
||||
|
@ -671,8 +639,27 @@ class AudioHidlTestWithDeviceConfigParameter
|
|||
return std::get<PARAM_DEVICE_NAME>(std::get<PARAM_DEVICE>(GetParam()));
|
||||
}
|
||||
const AudioConfig& getConfig() const { return std::get<PARAM_CONFIG>(GetParam()); }
|
||||
#if MAJOR_VERSION == 2
|
||||
AudioInputFlag getInputFlags() const {
|
||||
return std::get<INDEX_INPUT>(std::get<PARAM_FLAGS>(GetParam()));
|
||||
}
|
||||
AudioOutputFlag getOutputFlags() const {
|
||||
return std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam()));
|
||||
}
|
||||
#elif MAJOR_VERSION >= 4
|
||||
hidl_bitfield<AudioInputFlag> getInputFlags() const {
|
||||
return hidl_bitfield<AudioInputFlag>(
|
||||
std::get<INDEX_INPUT>(std::get<PARAM_FLAGS>(GetParam())));
|
||||
}
|
||||
hidl_bitfield<AudioOutputFlag> getOutputFlags() const {
|
||||
return hidl_bitfield<AudioOutputFlag>(
|
||||
std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam())));
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#include "ConfigHelper.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// getInputBufferSize /////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -681,7 +668,7 @@ class AudioHidlTestWithDeviceConfigParameter
|
|||
// android.hardware.microphone
|
||||
// how to get this value ? is it a property ???
|
||||
|
||||
class AudioCaptureConfigPrimaryTest : public AudioHidlTestWithDeviceConfigParameter {
|
||||
class AudioCaptureConfigTest : public AudioHidlTestWithDeviceConfigParameter {
|
||||
protected:
|
||||
void inputBufferSizeTest(const AudioConfig& audioConfig, bool supportRequired) {
|
||||
uint64_t bufferSize;
|
||||
|
@ -704,42 +691,51 @@ class AudioCaptureConfigPrimaryTest : public AudioHidlTestWithDeviceConfigParame
|
|||
|
||||
// Test that the required capture config and those declared in the policy are
|
||||
// indeed supported
|
||||
class RequiredInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {};
|
||||
class RequiredInputBufferSizeTest : public AudioCaptureConfigTest {};
|
||||
TEST_P(RequiredInputBufferSizeTest, RequiredInputBufferSizeTest) {
|
||||
doc::test(
|
||||
"Input buffer size must be retrievable for a format with required "
|
||||
"support.");
|
||||
inputBufferSizeTest(getConfig(), true);
|
||||
}
|
||||
|
||||
// Test that the recommended capture config are supported or lead to a
|
||||
// INVALID_ARGUMENTS return
|
||||
class OptionalInputBufferSizeTest : public AudioCaptureConfigTest {};
|
||||
TEST_P(OptionalInputBufferSizeTest, OptionalInputBufferSizeTest) {
|
||||
doc::test(
|
||||
"Input buffer size should be retrievable for a format with recommended "
|
||||
"support.");
|
||||
inputBufferSizeTest(getConfig(), false);
|
||||
}
|
||||
|
||||
#if MAJOR_VERSION <= 5
|
||||
// For V2..5 test the primary device according to CDD requirements.
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
RequiredInputBufferSize, RequiredInputBufferSizeTest,
|
||||
// FIXME: uses primaryHasMic
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
|
||||
::testing::ValuesIn(ConfigHelper::getRequiredSupportCaptureAudioConfig())),
|
||||
::testing::ValuesIn(ConfigHelper::getRequiredSupportCaptureAudioConfig()),
|
||||
::testing::Values(AudioInputFlag::NONE)),
|
||||
&DeviceConfigParameterToString);
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SupportedInputBufferSize, RequiredInputBufferSizeTest,
|
||||
::testing::Combine(::testing::ValuesIn(getDeviceParameters()),
|
||||
::testing::ValuesIn(ConfigHelper::getSupportedCaptureAudioConfig())),
|
||||
::testing::ValuesIn(ConfigHelper::getSupportedCaptureAudioConfig()),
|
||||
::testing::Values(AudioInputFlag::NONE)),
|
||||
&DeviceConfigParameterToString);
|
||||
|
||||
// Test that the recommended capture config are supported or lead to a
|
||||
// INVALID_ARGUMENTS return
|
||||
class OptionalInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {};
|
||||
TEST_P(OptionalInputBufferSizeTest, OptionalInputBufferSizeTest) {
|
||||
doc::test(
|
||||
"Input buffer size should be retrievable for a format with recommended "
|
||||
"support.");
|
||||
inputBufferSizeTest(getConfig(), false);
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest,
|
||||
// FIXME: uses primaryHasMic
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
|
||||
::testing::ValuesIn(ConfigHelper::getRecommendedSupportCaptureAudioConfig())),
|
||||
::testing::ValuesIn(ConfigHelper::getRecommendedSupportCaptureAudioConfig()),
|
||||
::testing::Values(AudioInputFlag::NONE)),
|
||||
&DeviceConfigParameterToString);
|
||||
#elif MAJOR_VERSION >= 6
|
||||
INSTANTIATE_TEST_CASE_P(SupportedInputBufferSize, RequiredInputBufferSizeTest,
|
||||
::testing::ValuesIn(getInputDeviceConfigParameters()),
|
||||
&DeviceConfigParameterToString);
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////// setScreenState ///////////////////////////////
|
||||
|
@ -896,8 +892,7 @@ class OutputStreamTest : public OpenStreamTest<IStreamOut> {
|
|||
ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
|
||||
address.device = AudioDevice::OUT_DEFAULT;
|
||||
const AudioConfig& config = getConfig();
|
||||
// TODO: test all flag combination
|
||||
auto flags = mkEnumBitfield(AudioOutputFlag::NONE);
|
||||
auto flags = getOutputFlags();
|
||||
testOpen(
|
||||
[&](AudioIoHandle handle, AudioConfig config, auto cb) {
|
||||
#if MAJOR_VERSION == 2
|
||||
|
@ -924,25 +919,37 @@ TEST_P(OutputStreamTest, OpenOutputStreamTest) {
|
|||
"recommended config");
|
||||
// Open done in SetUp
|
||||
}
|
||||
// FIXME: Add instantiations for non-primary devices with configs harvested from the APM config file
|
||||
|
||||
#if MAJOR_VERSION <= 5
|
||||
// For V2..5 test the primary device according to CDD requirements.
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
RequiredOutputStreamConfigSupport, OutputStreamTest,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
|
||||
::testing::ValuesIn(ConfigHelper::getRequiredSupportPlaybackAudioConfig())),
|
||||
::testing::ValuesIn(ConfigHelper::getRequiredSupportPlaybackAudioConfig()),
|
||||
::testing::Values(AudioOutputFlag::NONE)),
|
||||
&DeviceConfigParameterToString);
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SupportedOutputStreamConfig, OutputStreamTest,
|
||||
::testing::Combine(::testing::ValuesIn(getDeviceParameters()),
|
||||
::testing::ValuesIn(ConfigHelper::getSupportedPlaybackAudioConfig())),
|
||||
::testing::ValuesIn(ConfigHelper::getSupportedPlaybackAudioConfig()),
|
||||
::testing::Values(AudioOutputFlag::NONE)),
|
||||
&DeviceConfigParameterToString);
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
RecommendedOutputStreamConfigSupport, OutputStreamTest,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
|
||||
::testing::ValuesIn(ConfigHelper::getRecommendedSupportPlaybackAudioConfig())),
|
||||
::testing::ValuesIn(ConfigHelper::getRecommendedSupportPlaybackAudioConfig()),
|
||||
::testing::Values(AudioOutputFlag::NONE)),
|
||||
&DeviceConfigParameterToString);
|
||||
#elif MAJOR_VERSION >= 6
|
||||
// For V6 and above test according to the audio policy manager configuration.
|
||||
// This is more correct as CDD is written from the apps perspective.
|
||||
// Audio system provides necessary format conversions for the missing configurations.
|
||||
INSTANTIATE_TEST_CASE_P(DeclaredOutputStreamConfigSupport, OutputStreamTest,
|
||||
::testing::ValuesIn(getOutputDeviceConfigParameters()),
|
||||
&DeviceConfigParameterToString);
|
||||
#endif
|
||||
|
||||
////////////////////////////// openInputStream //////////////////////////////
|
||||
|
||||
|
@ -951,8 +958,7 @@ class InputStreamTest : public OpenStreamTest<IStreamIn> {
|
|||
ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
|
||||
address.device = AudioDevice::IN_DEFAULT;
|
||||
const AudioConfig& config = getConfig();
|
||||
// TODO: test all supported flags and source
|
||||
auto flags = mkEnumBitfield(AudioInputFlag::NONE);
|
||||
auto flags = getInputFlags();
|
||||
testOpen(
|
||||
[&](AudioIoHandle handle, AudioConfig config, auto cb) {
|
||||
return getDevice()->openInputStream(handle, address, config, flags,
|
||||
|
@ -975,26 +981,36 @@ TEST_P(InputStreamTest, OpenInputStreamTest) {
|
|||
"recommended config");
|
||||
// Open done in setup
|
||||
}
|
||||
#if MAJOR_VERSION <= 5
|
||||
// For V2..5 test the primary device according to CDD requirements.
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
RequiredInputStreamConfigSupport, InputStreamTest,
|
||||
// FIXME: uses primaryHasMic
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
|
||||
::testing::ValuesIn(ConfigHelper::getRequiredSupportCaptureAudioConfig())),
|
||||
::testing::ValuesIn(ConfigHelper::getRequiredSupportCaptureAudioConfig()),
|
||||
::testing::Values(AudioInputFlag::NONE)),
|
||||
&DeviceConfigParameterToString);
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
SupportedInputStreamConfig, InputStreamTest,
|
||||
::testing::Combine(::testing::ValuesIn(getDeviceParameters()),
|
||||
::testing::ValuesIn(ConfigHelper::getSupportedCaptureAudioConfig())),
|
||||
::testing::ValuesIn(ConfigHelper::getSupportedCaptureAudioConfig()),
|
||||
::testing::Values(AudioInputFlag::NONE)),
|
||||
&DeviceConfigParameterToString);
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
RecommendedInputStreamConfigSupport, InputStreamTest,
|
||||
// FIXME: uses primaryHasMic
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
|
||||
::testing::ValuesIn(ConfigHelper::getRecommendedSupportCaptureAudioConfig())),
|
||||
::testing::ValuesIn(ConfigHelper::getRecommendedSupportCaptureAudioConfig()),
|
||||
::testing::Values(AudioInputFlag::NONE)),
|
||||
&DeviceConfigParameterToString);
|
||||
#elif MAJOR_VERSION >= 6
|
||||
// For V6 and above test according to the audio policy manager configuration.
|
||||
// This is more correct as CDD is written from the apps perspective.
|
||||
// Audio system provides necessary format conversions for the missing configurations.
|
||||
INSTANTIATE_TEST_CASE_P(DeclaredInputStreamConfigSupport, InputStreamTest,
|
||||
::testing::ValuesIn(getInputDeviceConfigParameters()),
|
||||
&DeviceConfigParameterToString);
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////// IStream getters ///////////////////////////////
|
||||
|
|
120
audio/core/all-versions/vts/functional/ConfigHelper.h
Normal file
120
audio/core/all-versions/vts/functional/ConfigHelper.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Code in this file uses 'getCachedPolicyConfig'
|
||||
#ifndef AUDIO_PRIMARY_HIDL_HAL_TEST
|
||||
#error Must be included from AudioPrimaryHidlTest.h
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////// Required and recommended audio format support ///////////////
|
||||
// From:
|
||||
// https://source.android.com/compatibility/android-cdd.html#5_4_audio_recording
|
||||
// From:
|
||||
// https://source.android.com/compatibility/android-cdd.html#5_5_audio_playback
|
||||
/////////// TODO: move to the beginning of the file for easier update ////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ConfigHelper {
|
||||
// for retro compatibility only test the primary device IN_BUILTIN_MIC
|
||||
// FIXME: in the next audio HAL version, test all available devices
|
||||
static bool primaryHasMic() {
|
||||
auto& policyConfig = getCachedPolicyConfig();
|
||||
if (policyConfig.getStatus() != OK || policyConfig.getPrimaryModule() == nullptr) {
|
||||
return true; // Could not get the information, run all tests
|
||||
}
|
||||
auto getMic = [](auto& devs) {
|
||||
return devs.getDevice(AUDIO_DEVICE_IN_BUILTIN_MIC, {}, AUDIO_FORMAT_DEFAULT);
|
||||
};
|
||||
auto primaryMic = getMic(policyConfig.getPrimaryModule()->getDeclaredDevices());
|
||||
auto availableMic = getMic(policyConfig.getAvailableInputDevices());
|
||||
|
||||
return primaryMic != nullptr && primaryMic->equals(availableMic);
|
||||
}
|
||||
|
||||
// Cache result ?
|
||||
static const vector<AudioConfig> getRequiredSupportPlaybackAudioConfig() {
|
||||
return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
|
||||
{8000, 11025, 16000, 22050, 32000, 44100},
|
||||
{AudioFormat::PCM_16_BIT});
|
||||
}
|
||||
|
||||
static const vector<AudioConfig> getRecommendedSupportPlaybackAudioConfig() {
|
||||
return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
|
||||
{24000, 48000}, {AudioFormat::PCM_16_BIT});
|
||||
}
|
||||
|
||||
static const vector<AudioConfig> getSupportedPlaybackAudioConfig() {
|
||||
// TODO: retrieve audio config supported by the platform
|
||||
// as declared in the policy configuration
|
||||
return {};
|
||||
}
|
||||
|
||||
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});
|
||||
}
|
||||
static const vector<AudioConfig> getSupportedCaptureAudioConfig() {
|
||||
// TODO: retrieve audio config supported by the platform
|
||||
// as declared in the policy configuration
|
||||
return {};
|
||||
}
|
||||
|
||||
static vector<AudioConfig> combineAudioConfig(android::ChannelMaskSet channelMasks,
|
||||
android::SampleRateSet sampleRates,
|
||||
audio_format_t format) {
|
||||
vector<AudioConfig> configs;
|
||||
configs.reserve(channelMasks.size() * sampleRates.size());
|
||||
for (auto channelMask : channelMasks) {
|
||||
for (auto sampleRate : sampleRates) {
|
||||
AudioConfig config{};
|
||||
// leave offloadInfo to 0
|
||||
config.channelMask = EnumBitfield<AudioChannelMask>(channelMask);
|
||||
config.sampleRateHz = sampleRate;
|
||||
config.format = AudioFormat(format);
|
||||
configs.push_back(config);
|
||||
}
|
||||
}
|
||||
return configs;
|
||||
}
|
||||
|
||||
static vector<AudioConfig> combineAudioConfig(vector<AudioChannelMask> channelMasks,
|
||||
vector<uint32_t> sampleRates,
|
||||
vector<AudioFormat> formats) {
|
||||
vector<AudioConfig> configs;
|
||||
configs.reserve(channelMasks.size() * sampleRates.size() * formats.size());
|
||||
for (auto channelMask : channelMasks) {
|
||||
for (auto sampleRate : sampleRates) {
|
||||
for (auto format : formats) {
|
||||
AudioConfig config{};
|
||||
// leave offloadInfo to 0
|
||||
config.channelMask = mkEnumBitfield(channelMask);
|
||||
config.sampleRateHz = sampleRate;
|
||||
config.format = format;
|
||||
// FIXME: leave frameCount to 0 ?
|
||||
configs.push_back(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
return configs;
|
||||
}
|
||||
};
|
Loading…
Reference in a new issue