diff --git a/audio/6.0/IStream.hal b/audio/6.0/IStream.hal index f4c91f826d..451e1162bf 100644 --- a/audio/6.0/IStream.hal +++ b/audio/6.0/IStream.hal @@ -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 formats); + getSupportedFormats() generates (Result retval, vec formats); /** * Sets the audio format of the stream. Calling this method is equivalent to diff --git a/audio/core/all-versions/default/Stream.cpp b/audio/core/all-versions/default/Stream.cpp index e62f6d3b0a..5f24a5d781 100644 --- a/audio/core/all-versions/default/Stream.cpp +++ b/audio/core/all-versions/default/Stream.cpp @@ -175,8 +175,17 @@ Return 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(); } diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp index cd93643b95..e267a5ea72 100644 --- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp @@ -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", diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h index 8415053ffc..7a52d0e364 100644 --- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h +++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h @@ -75,11 +75,18 @@ struct GetSupported { return res; } +#if MAJOR_VERSION <= 5 static Result formats(IStream* stream, hidl_vec& 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& capabilities) { + Result res; + EXPECT_OK(stream->getSupportedFormats(returnIn(res, capabilities))); + return res; + } +#endif }; template 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 937de0a18d..30f8a7ade7 100644 --- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp @@ -64,3 +64,83 @@ const std::vector& getDeviceParameters() { }(); return parameters; } + +const std::vector& getOutputDeviceConfigParameters() { + static std::vector parameters = [] { + 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( + vector(channels.begin(), channels.end()), + 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. + 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& getInputDeviceConfigParameters() { + static std::vector parameters = [] { + 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( + vector(channels.begin(), channels.end()), + vector(sampleRates.begin(), sampleRates.end()), + profile->getFormat()); + for (const auto& config : configs) { + result.emplace_back(device, config, AudioInputFlag(ioProfile->getFlags())); + } + } + } + } + return result; + }(); + return parameters; +} diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h index 7bdc5e1eb1..468f9b2da6 100644 --- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h +++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -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 getModuleFromName(const std::string& name) const { + return getHwModules().getModuleFromName(name.c_str()); + } sp getPrimaryModule() const { return mPrimaryModule; } const std::set& 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 getRequiredSupportPlaybackAudioConfig() { - return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, - {8000, 11025, 16000, 22050, 32000, 44100}, - {AudioFormat::PCM_16_BIT}); - } - - static const vector getRecommendedSupportPlaybackAudioConfig() { - return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, - {24000, 48000}, {AudioFormat::PCM_16_BIT}); - } - - static const vector getSupportedPlaybackAudioConfig() { - // TODO: retrieve audio config supported by the platform - // as declared in the policy configuration - return {}; - } - - static const vector getRequiredSupportCaptureAudioConfig() { - if (!primaryHasMic()) return {}; - return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100}, - {AudioFormat::PCM_16_BIT}); - } - static const vector getRecommendedSupportCaptureAudioConfig() { - if (!primaryHasMic()) return {}; - return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000}, - {AudioFormat::PCM_16_BIT}); - } - static const vector getSupportedCaptureAudioConfig() { - // TODO: retrieve audio config supported by the platform - // as declared in the policy configuration - return {}; - } - - private: - static const vector combineAudioConfig(vector channelMasks, - vector sampleRates, - vector formats) { - vector 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; +enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS }; +enum { INDEX_INPUT, INDEX_OUTPUT }; +using DeviceConfigParameter = + std::tuple>; + +#if MAJOR_VERSION >= 6 +const std::vector& getInputDeviceConfigParameters(); +const std::vector& 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(info.param)); +#elif MAJOR_VERSION >= 4 + SanitizeStringForGTestName(std::visit( + [](auto&& arg) -> std::string { + using T = std::decay_t; + // Need to use FQN of toString to avoid confusing the compiler + return ::android::hardware::audio::common::CPP_VERSION::toString( + hidl_bitfield(arg)); + }, + std::get(info.param))); +#endif } class AudioHidlTestWithDeviceConfigParameter @@ -671,8 +639,27 @@ class AudioHidlTestWithDeviceConfigParameter return std::get(std::get(GetParam())); } const AudioConfig& getConfig() const { return std::get(GetParam()); } +#if MAJOR_VERSION == 2 + AudioInputFlag getInputFlags() const { + return std::get(std::get(GetParam())); + } + AudioOutputFlag getOutputFlags() const { + return std::get(std::get(GetParam())); + } +#elif MAJOR_VERSION >= 4 + hidl_bitfield getInputFlags() const { + return hidl_bitfield( + std::get(std::get(GetParam()))); + } + hidl_bitfield getOutputFlags() const { + return hidl_bitfield( + std::get(std::get(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 { 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 { 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 /////////////////////////////// diff --git a/audio/core/all-versions/vts/functional/ConfigHelper.h b/audio/core/all-versions/vts/functional/ConfigHelper.h new file mode 100644 index 0000000000..48aae8c5b3 --- /dev/null +++ b/audio/core/all-versions/vts/functional/ConfigHelper.h @@ -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 getRequiredSupportPlaybackAudioConfig() { + return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, + {8000, 11025, 16000, 22050, 32000, 44100}, + {AudioFormat::PCM_16_BIT}); + } + + static const vector getRecommendedSupportPlaybackAudioConfig() { + return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, + {24000, 48000}, {AudioFormat::PCM_16_BIT}); + } + + static const vector getSupportedPlaybackAudioConfig() { + // TODO: retrieve audio config supported by the platform + // as declared in the policy configuration + return {}; + } + + static const vector getRequiredSupportCaptureAudioConfig() { + if (!primaryHasMic()) return {}; + return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100}, + {AudioFormat::PCM_16_BIT}); + } + static const vector getRecommendedSupportCaptureAudioConfig() { + if (!primaryHasMic()) return {}; + return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000}, + {AudioFormat::PCM_16_BIT}); + } + static const vector getSupportedCaptureAudioConfig() { + // TODO: retrieve audio config supported by the platform + // as declared in the policy configuration + return {}; + } + + static vector combineAudioConfig(vector channelMasks, + vector sampleRates, + audio_format_t format) { + vector configs; + configs.reserve(channelMasks.size() * sampleRates.size()); + for (auto channelMask : channelMasks) { + for (auto sampleRate : sampleRates) { + AudioConfig config{}; + // leave offloadInfo to 0 + config.channelMask = EnumBitfield(channelMask); + config.sampleRateHz = sampleRate; + config.format = AudioFormat(format); + configs.push_back(config); + } + } + return configs; + } + + static vector combineAudioConfig(vector channelMasks, + vector sampleRates, + vector formats) { + vector 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; + } +};