audio: Implement VTS tests for V7.0

The major change in V7.0 is use of enum values defined
in the Audio Policy Configuration XSD schema. This allows
decoupling types used at the HIDL layer from system/audio.h.
Added a header audio_policy_configuration_V7_0-enums.h
with utility functions analogous to ones from system/audio.h
but defined for the types generated from XSD schema.

Since the code of VTS tests is shared between versions,
ensured that the VTS tests for the previous HAL versions
didn't regress.

Bug: 142480271
Test: atest VtsHalAudioV6_0TargetTest
      atest VtsHalAudioEffectV6_0TargetTest
      atest VtsHalAudioV7_0TargetTest
      atest VtsHalAudioEffectV7_0TargetTest
Change-Id: Ia7c2d49a02783725080c8fed6a25853e91bba487
This commit is contained in:
Mikhail Naganov 2020-08-14 00:16:09 +00:00
parent c9e1607de4
commit 343450a074
14 changed files with 856 additions and 185 deletions

View file

@ -16,9 +16,12 @@ hidl_interface {
cc_library {
name: "android.hardware.audio.common@7.0-enums",
vendor_available: true,
generated_sources: ["audio_policy_configuration_V7_0"],
generated_headers: ["audio_policy_configuration_V7_0"],
generated_sources: ["audio_policy_configuration_V7_0"],
header_libs: ["libxsdc-utils"],
export_generated_headers: ["audio_policy_configuration_V7_0"],
export_header_lib_headers: ["libxsdc-utils"],
export_include_dirs: ["enums/include"],
shared_libs: [
"libbase",
"liblog",

View file

@ -0,0 +1,207 @@
/*
* Copyright (C) 2020 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.
*/
#ifndef AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H
#define AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H
#include <sys/types.h>
#include <audio_policy_configuration_V7_0.h>
namespace audio::policy::configuration::V7_0 {
static inline size_t getChannelCount(AudioChannelMask mask) {
switch (mask) {
case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO:
case AudioChannelMask::AUDIO_CHANNEL_IN_MONO:
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_1:
return 1;
case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO:
case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO_HAPTIC_A:
case AudioChannelMask::AUDIO_CHANNEL_OUT_HAPTIC_AB:
case AudioChannelMask::AUDIO_CHANNEL_IN_STEREO:
case AudioChannelMask::AUDIO_CHANNEL_IN_FRONT_BACK:
case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO:
case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO:
case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_CALL_MONO:
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_2:
return 2;
case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT1:
case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A:
case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB:
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_3:
return 3;
case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT0POINT2:
case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD:
case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD_BACK:
case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD_SIDE:
case AudioChannelMask::AUDIO_CHANNEL_OUT_SURROUND:
case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB:
case AudioChannelMask::AUDIO_CHANNEL_IN_2POINT0POINT2:
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_4:
return 4;
case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT1POINT2:
case AudioChannelMask::AUDIO_CHANNEL_OUT_3POINT0POINT2:
case AudioChannelMask::AUDIO_CHANNEL_OUT_PENTA:
case AudioChannelMask::AUDIO_CHANNEL_IN_2POINT1POINT2:
case AudioChannelMask::AUDIO_CHANNEL_IN_3POINT0POINT2:
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_5:
return 5;
case AudioChannelMask::AUDIO_CHANNEL_OUT_3POINT1POINT2:
case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1:
case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1_BACK:
case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1_SIDE:
case AudioChannelMask::AUDIO_CHANNEL_IN_6:
case AudioChannelMask::AUDIO_CHANNEL_IN_3POINT1POINT2:
case AudioChannelMask::AUDIO_CHANNEL_IN_5POINT1:
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_6:
return 6;
case AudioChannelMask::AUDIO_CHANNEL_OUT_6POINT1:
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_7:
return 7;
case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1POINT2:
case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1:
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_8:
return 8;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_9:
return 9;
case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1POINT4:
case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1POINT2:
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_10:
return 10;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_11:
return 11;
case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1POINT4:
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_12:
return 12;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_13:
return 13;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_14:
return 14;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_15:
return 15;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_16:
return 16;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_17:
return 17;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_18:
return 18;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_19:
return 19;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_20:
return 20;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_21:
return 21;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_22:
return 22;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_23:
return 23;
case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_24:
return 24;
case AudioChannelMask::UNKNOWN:
return 0;
// No default to make sure all cases are covered.
}
// This is to avoid undefined behavior if 'mask' isn't a valid enum value.
return 0;
}
static inline ssize_t getChannelCount(const std::string& mask) {
return getChannelCount(stringToAudioChannelMask(mask));
}
static inline bool isOutputDevice(AudioDevice device) {
switch (device) {
case AudioDevice::UNKNOWN:
case AudioDevice::AUDIO_DEVICE_NONE:
return false;
case AudioDevice::AUDIO_DEVICE_OUT_EARPIECE:
case AudioDevice::AUDIO_DEVICE_OUT_SPEAKER:
case AudioDevice::AUDIO_DEVICE_OUT_WIRED_HEADSET:
case AudioDevice::AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
case AudioDevice::AUDIO_DEVICE_OUT_AUX_DIGITAL:
case AudioDevice::AUDIO_DEVICE_OUT_HDMI:
case AudioDevice::AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET:
case AudioDevice::AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET:
case AudioDevice::AUDIO_DEVICE_OUT_USB_ACCESSORY:
case AudioDevice::AUDIO_DEVICE_OUT_USB_DEVICE:
case AudioDevice::AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
case AudioDevice::AUDIO_DEVICE_OUT_TELEPHONY_TX:
case AudioDevice::AUDIO_DEVICE_OUT_LINE:
case AudioDevice::AUDIO_DEVICE_OUT_HDMI_ARC:
case AudioDevice::AUDIO_DEVICE_OUT_SPDIF:
case AudioDevice::AUDIO_DEVICE_OUT_FM:
case AudioDevice::AUDIO_DEVICE_OUT_AUX_LINE:
case AudioDevice::AUDIO_DEVICE_OUT_SPEAKER_SAFE:
case AudioDevice::AUDIO_DEVICE_OUT_IP:
case AudioDevice::AUDIO_DEVICE_OUT_BUS:
case AudioDevice::AUDIO_DEVICE_OUT_PROXY:
case AudioDevice::AUDIO_DEVICE_OUT_USB_HEADSET:
case AudioDevice::AUDIO_DEVICE_OUT_HEARING_AID:
case AudioDevice::AUDIO_DEVICE_OUT_ECHO_CANCELLER:
case AudioDevice::AUDIO_DEVICE_OUT_DEFAULT:
case AudioDevice::AUDIO_DEVICE_OUT_STUB:
return true;
case AudioDevice::AUDIO_DEVICE_IN_COMMUNICATION:
case AudioDevice::AUDIO_DEVICE_IN_AMBIENT:
case AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC:
case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET:
case AudioDevice::AUDIO_DEVICE_IN_WIRED_HEADSET:
case AudioDevice::AUDIO_DEVICE_IN_AUX_DIGITAL:
case AudioDevice::AUDIO_DEVICE_IN_HDMI:
case AudioDevice::AUDIO_DEVICE_IN_VOICE_CALL:
case AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX:
case AudioDevice::AUDIO_DEVICE_IN_BACK_MIC:
case AudioDevice::AUDIO_DEVICE_IN_REMOTE_SUBMIX:
case AudioDevice::AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET:
case AudioDevice::AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET:
case AudioDevice::AUDIO_DEVICE_IN_USB_ACCESSORY:
case AudioDevice::AUDIO_DEVICE_IN_USB_DEVICE:
case AudioDevice::AUDIO_DEVICE_IN_FM_TUNER:
case AudioDevice::AUDIO_DEVICE_IN_TV_TUNER:
case AudioDevice::AUDIO_DEVICE_IN_LINE:
case AudioDevice::AUDIO_DEVICE_IN_SPDIF:
case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_A2DP:
case AudioDevice::AUDIO_DEVICE_IN_LOOPBACK:
case AudioDevice::AUDIO_DEVICE_IN_IP:
case AudioDevice::AUDIO_DEVICE_IN_BUS:
case AudioDevice::AUDIO_DEVICE_IN_PROXY:
case AudioDevice::AUDIO_DEVICE_IN_USB_HEADSET:
case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_BLE:
case AudioDevice::AUDIO_DEVICE_IN_HDMI_ARC:
case AudioDevice::AUDIO_DEVICE_IN_ECHO_REFERENCE:
case AudioDevice::AUDIO_DEVICE_IN_DEFAULT:
case AudioDevice::AUDIO_DEVICE_IN_STUB:
return false;
// No default to make sure all cases are covered.
}
// This is to avoid undefined behavior if 'device' isn't a valid enum value.
return false;
}
static inline bool isOutputDevice(const std::string& device) {
return isOutputDevice(stringToAudioDevice(device));
}
} // namespace audio::policy::configuration::V7_0
#endif // AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H

View file

@ -16,6 +16,13 @@
#include "AudioPrimaryHidlHalTest.h"
#if MAJOR_VERSION >= 7
#include <audio_policy_configuration_V7_0.h>
#include <xsdc/XsdcSupport.h>
using android::xsdc_enum_range;
#endif
TEST_P(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) {
doc::test("Calling openDevice(\"primary\") should return the primary device.");
if (getDeviceName() != DeviceManager::kPrimaryDevice) {
@ -53,14 +60,29 @@ TEST_P(AudioHidlDeviceTest, GetMicrophonesTest) {
"Make sure getMicrophones always succeeds"
"and getActiveMicrophones always succeeds when recording from these microphones.");
AudioConfig config{};
#if MAJOR_VERSION <= 6
config.channelMask = mkEnumBitfield(AudioChannelMask::IN_MONO);
config.sampleRateHz = 8000;
config.format = AudioFormat::PCM_16_BIT;
auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
const SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
#elif MAJOR_VERSION >= 7
config.base.channelMask.resize(1);
config.base.channelMask[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO);
config.base.sampleRateHz = 8000;
config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
hidl_vec<hidl_string> flags;
const SinkMetadata initMetadata = {
{{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC), .gain = 1}}};
#endif
EventFlag* efGroup;
for (auto microphone : microphones) {
#if MAJOR_VERSION <= 6
if (microphone.deviceAddress.device != AudioDevice::IN_BUILTIN_MIC) {
#elif MAJOR_VERSION >= 7
if (xsd::stringToAudioDevice(microphone.deviceAddress.deviceType) !=
xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC) {
#endif
continue;
}
sp<IStreamIn> stream;
@ -81,16 +103,16 @@ TEST_P(AudioHidlDeviceTest, GetMicrophonesTest) {
size_t frameSize = stream->getFrameSize();
size_t frameCount = stream->getBufferSize() / frameSize;
ASSERT_OK(stream->prepareForReading(
frameSize, frameCount, [&](auto r, auto& c, auto& d, auto&, auto&) {
readRes = r;
if (readRes == Result::OK) {
commandMQ.reset(new CommandMQ(c));
dataMQ.reset(new DataMQ(d));
if (dataMQ->isValid() && dataMQ->getEventFlagWord()) {
EventFlag::createEventFlag(dataMQ->getEventFlagWord(), &efGroup);
frameSize, frameCount, [&](auto r, auto& c, auto& d, auto&, auto) {
readRes = r;
if (readRes == Result::OK) {
commandMQ.reset(new CommandMQ(c));
dataMQ.reset(new DataMQ(d));
if (dataMQ->isValid() && dataMQ->getEventFlagWord()) {
EventFlag::createEventFlag(dataMQ->getEventFlagWord(), &efGroup);
}
}
}
}));
}));
ASSERT_OK(readRes);
IStreamIn::ReadParameters params;
params.command = IStreamIn::ReadCommand::READ;
@ -116,13 +138,24 @@ TEST_P(AudioHidlDeviceTest, GetMicrophonesTest) {
TEST_P(AudioHidlDeviceTest, SetConnectedState) {
doc::test("Check that the HAL can be notified of device connection and deconnection");
#if MAJOR_VERSION <= 6
using AD = AudioDevice;
for (auto deviceType : {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) {
#elif MAJOR_VERSION >= 7
using AD = xsd::AudioDevice;
for (auto deviceType :
{toString(AD::AUDIO_DEVICE_OUT_HDMI), toString(AD::AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
toString(AD::AUDIO_DEVICE_IN_USB_HEADSET)}) {
#endif
SCOPED_TRACE("device=" + ::testing::PrintToString(deviceType));
for (bool state : {true, false}) {
SCOPED_TRACE("state=" + ::testing::PrintToString(state));
DeviceAddress address = {};
#if MAJOR_VERSION <= 6
address.device = deviceType;
#elif MAJOR_VERSION >= 7
address.deviceType = deviceType;
#endif
auto ret = getDevice()->setConnectedState(address, state);
ASSERT_TRUE(ret.isOk());
if (ret == Result::NOT_SUPPORTED) {
@ -148,7 +181,11 @@ static void testGetDevices(IStream* stream, AudioDevice expectedDevice) {
}
// The stream was constructed with one device, thus getDevices must only return one
ASSERT_EQ(1U, devices.size());
#if MAJOR_VERSION <= 6
AudioDevice device = devices[0].device;
#elif MAJOR_VERSION >= 7
auto device = devices[0].deviceType;
#endif
ASSERT_TRUE(device == expectedDevice)
<< "Expected: " << ::testing::PrintToString(expectedDevice)
<< "\n Actual: " << ::testing::PrintToString(device);
@ -156,12 +193,22 @@ static void testGetDevices(IStream* stream, AudioDevice expectedDevice) {
TEST_IO_STREAM(GetDevices, "Check that the stream device == the one it was opened with",
areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported")
#if MAJOR_VERSION <= 6
: testGetDevices(stream.get(), address.device))
#elif MAJOR_VERSION >= 7
: testGetDevices(stream.get(), address.deviceType))
#endif
static void testSetDevices(IStream* stream, const DeviceAddress& address) {
DeviceAddress otherAddress = address;
#if MAJOR_VERSION <= 6
otherAddress.device = (address.device & AudioDevice::BIT_IN) == 0 ? AudioDevice::OUT_SPEAKER
: AudioDevice::IN_BUILTIN_MIC;
#elif MAJOR_VERSION >= 7
otherAddress.deviceType = xsd::isOutputDevice(address.deviceType)
? toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER)
: toString(xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC);
#endif
EXPECT_RESULT(okOrNotSupported, stream->setDevices({otherAddress}));
ASSERT_RESULT(okOrNotSupported,
@ -186,11 +233,19 @@ TEST_IO_STREAM(GetHwAvSync, "Get hardware sync can not fail", checkGetHwAVSync(g
TEST_P(InputStreamTest, updateSinkMetadata) {
doc::test("The HAL should not crash on metadata change");
#if MAJOR_VERSION <= 6
hidl_enum_range<AudioSource> range;
#elif MAJOR_VERSION >= 7
xsdc_enum_range<audio::policy::configuration::V7_0::AudioSource> range;
#endif
// Test all possible track configuration
for (AudioSource source : range) {
for (auto source : range) {
for (float volume : {0.0, 0.5, 1.0}) {
#if MAJOR_VERSION <= 6
const SinkMetadata metadata = {{{.source = source, .gain = volume}}};
#elif MAJOR_VERSION >= 7
const SinkMetadata metadata = {{{.source = toString(source), .gain = volume}}};
#endif
ASSERT_OK(stream->updateSinkMetadata(metadata))
<< "source=" << toString(source) << ", volume=" << volume;
}
@ -213,13 +268,22 @@ TEST_P(OutputStreamTest, SelectPresentation) {
TEST_P(OutputStreamTest, updateSourceMetadata) {
doc::test("The HAL should not crash on metadata change");
#if MAJOR_VERSION <= 6
hidl_enum_range<AudioUsage> usageRange;
hidl_enum_range<AudioContentType> contentRange;
#elif MAJOR_VERSION >= 7
xsdc_enum_range<audio::policy::configuration::V7_0::AudioUsage> usageRange;
xsdc_enum_range<audio::policy::configuration::V7_0::AudioContentType> contentRange;
#endif
// Test all possible track configuration
for (auto usage : usageRange) {
for (auto content : contentRange) {
for (float volume : {0.0, 0.5, 1.0}) {
#if MAJOR_VERSION <= 6
const SourceMetadata metadata = {{{usage, content, volume}}};
#elif MAJOR_VERSION >= 7
const SourceMetadata metadata = {{{toString(usage), toString(content), volume}}};
#endif
ASSERT_OK(stream->updateSourceMetadata(metadata))
<< "usage=" << toString(usage) << ", content=" << toString(content)
<< ", volume=" << volume;
@ -227,12 +291,26 @@ TEST_P(OutputStreamTest, updateSourceMetadata) {
}
}
// clang-format off
// Set many track of different configuration
ASSERT_OK(stream->updateSourceMetadata(
#if MAJOR_VERSION <= 6
{{{AudioUsage::MEDIA, AudioContentType::MUSIC, 0.1},
{AudioUsage::VOICE_COMMUNICATION, AudioContentType::SPEECH, 1.0},
{AudioUsage::ALARM, AudioContentType::SONIFICATION, 0.0},
{AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, 0.3}}}));
{AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, 0.3}}}
#elif MAJOR_VERSION >= 7
{{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC), 0.1},
{toString(xsd::AudioUsage::AUDIO_USAGE_VOICE_COMMUNICATION),
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SPEECH), 1.0},
{toString(xsd::AudioUsage::AUDIO_USAGE_ALARM),
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SONIFICATION), 0.0},
{toString(xsd::AudioUsage::AUDIO_USAGE_ASSISTANT),
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_UNKNOWN), 0.3}}}
#endif
));
// clang-format on
// Set no metadata as if all stream track had stopped
ASSERT_OK(stream->updateSourceMetadata({}));

View file

@ -56,6 +56,7 @@ struct Parameters {
}
};
#if MAJOR_VERSION <= 6
struct GetSupported {
static auto getFormat(IStream* stream) {
auto ret = stream->getFormat();
@ -80,7 +81,7 @@ struct GetSupported {
EXPECT_OK(stream->getSupportedFormats(returnIn(capabilities)));
return Result::OK;
}
#elif MAJOR_VERSION >= 6
#else // MAJOR_VERSION == 6
static Result formats(IStream* stream, hidl_vec<AudioFormat>& capabilities) {
Result res;
EXPECT_OK(stream->getSupportedFormats(returnIn(res, capabilities)));
@ -88,6 +89,7 @@ struct GetSupported {
}
#endif
};
#endif // MAJOR_VERSION <= 6
template <class T>
auto dump(T t, hidl_handle handle) {

View file

@ -17,6 +17,7 @@
// pull in all the <= 5.0 tests
#include "5.0/AudioPrimaryHidlHalTest.cpp"
#if MAJOR_VERSION <= 6
const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
static std::vector<DeviceConfigParameter> parameters = [] {
std::vector<DeviceConfigParameter> result;
@ -28,8 +29,8 @@ const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
const auto& channels = profile->getChannels();
const auto& sampleRates = profile->getSampleRates();
auto configs = ConfigHelper::combineAudioConfig(
vector<audio_channel_mask_t>(channels.begin(), channels.end()),
vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
std::vector<audio_channel_mask_t>(channels.begin(), channels.end()),
std::vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
profile->getFormat());
auto flags = ioProfile->getFlags();
for (auto& config : configs) {
@ -46,8 +47,8 @@ const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
config.offloadInfo.bufferSize = 256; // arbitrary value
config.offloadInfo.usage = AudioUsage::MEDIA;
result.emplace_back(device, config,
AudioOutputFlag(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
AUDIO_OUTPUT_FLAG_DIRECT));
AudioOutputFlag(AudioOutputFlag::COMPRESS_OFFLOAD |
AudioOutputFlag::DIRECT));
} else {
if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) { // ignore the flag
flags &= ~AUDIO_OUTPUT_FLAG_PRIMARY;
@ -74,8 +75,8 @@ const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters() {
const auto& channels = profile->getChannels();
const auto& sampleRates = profile->getSampleRates();
auto configs = ConfigHelper::combineAudioConfig(
vector<audio_channel_mask_t>(channels.begin(), channels.end()),
vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
std::vector<audio_channel_mask_t>(channels.begin(), channels.end()),
std::vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
profile->getFormat());
for (const auto& config : configs) {
result.emplace_back(device, config, AudioInputFlag(ioProfile->getFlags()));
@ -87,13 +88,22 @@ const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters() {
}();
return parameters;
}
#endif // MAJOR_VERSION <= 6
TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedOutputStreams) {
doc::test("Verify that a device can't be closed if there are streams opened");
#if MAJOR_VERSION <= 6
DeviceAddress address{.device = AudioDevice::OUT_DEFAULT};
AudioConfig config{};
auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE);
SourceMetadata initMetadata = {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 1 /* gain */}}};
auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE);
#elif MAJOR_VERSION >= 7
DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT)};
SourceMetadata initMetadata = {
{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC), 1 /* gain */}}};
hidl_vec<AudioInOutFlag> flags;
#endif
AudioConfig config{};
sp<IStreamOut> stream;
StreamHelper<IStreamOut> helper(stream);
AudioConfig suggestedConfig{};
@ -111,14 +121,20 @@ TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedOutputStreams) {
TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedInputStreams) {
doc::test("Verify that a device can't be closed if there are streams opened");
auto module = getCachedPolicyConfig().getModuleFromName(getDeviceName());
if (module->getInputProfiles().empty()) {
if (!getCachedPolicyConfig().haveInputProfilesInModule(getDeviceName())) {
GTEST_SKIP() << "Device doesn't have input profiles";
}
#if MAJOR_VERSION <= 6
DeviceAddress address{.device = AudioDevice::IN_DEFAULT};
AudioConfig config{};
auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
#elif MAJOR_VERSION >= 7
DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT)};
SinkMetadata initMetadata = {
{{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC), .gain = 1}}};
hidl_vec<AudioInOutFlag> flags;
#endif
AudioConfig config{};
sp<IStreamIn> stream;
StreamHelper<IStreamIn> helper(stream);
AudioConfig suggestedConfig{};
@ -137,9 +153,8 @@ TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedInputStreams) {
TEST_P(AudioPatchHidlTest, UpdatePatchInvalidHandle) {
doc::test("Verify that passing an invalid handle to updateAudioPatch is checked");
AudioPatchHandle ignored;
ASSERT_OK(getDevice()->updateAudioPatch(
static_cast<int32_t>(AudioHandleConsts::AUDIO_PATCH_HANDLE_NONE),
hidl_vec<AudioPortConfig>(), hidl_vec<AudioPortConfig>(), returnIn(res, ignored)));
ASSERT_OK(getDevice()->updateAudioPatch(AudioPatchHandle{}, hidl_vec<AudioPortConfig>(),
hidl_vec<AudioPortConfig>(), returnIn(res, ignored)));
ASSERT_RESULT(Result::INVALID_ARGUMENTS, res);
}

View file

@ -16,3 +16,101 @@
// pull in all the <= 6.0 tests
#include "6.0/AudioPrimaryHidlHalTest.cpp"
static std::vector<AudioConfig> combineAudioConfig(std::vector<xsd::AudioChannelMask> channelMasks,
std::vector<int64_t> sampleRates,
const std::string& format) {
std::vector<AudioConfig> configs;
configs.reserve(channelMasks.size() * sampleRates.size());
for (auto channelMask : channelMasks) {
for (auto sampleRate : sampleRates) {
AudioConfig config{};
// leave offloadInfo to 0
config.base.channelMask.resize(1);
config.base.channelMask[0] = toString(channelMask);
config.base.sampleRateHz = sampleRate;
config.base.format = format;
configs.push_back(config);
}
}
return configs;
}
const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
static std::vector<DeviceConfigParameter> parameters = [] {
std::vector<DeviceConfigParameter> result;
const std::vector<AudioInOutFlag> offloadFlags = {
toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_DIRECT)};
for (const auto& device : getDeviceParameters()) {
auto module =
getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
if (mixPort.getRole() != xsd::Role::source) continue; // not an output profile
auto xsdFlags = mixPort.getFlags();
const bool isOffload =
std::find(xsdFlags.begin(), xsdFlags.end(),
xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) !=
xsdFlags.end();
std::vector<AudioInOutFlag> flags;
if (!isOffload) {
for (auto flag : xsdFlags) {
if (flag != xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_PRIMARY) {
flags.push_back(toString(flag));
}
}
} else {
flags = offloadFlags;
}
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.base = config.base;
config.offloadInfo.streamType =
toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC);
config.offloadInfo.usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA);
config.offloadInfo.bitRatePerSecond = 320;
config.offloadInfo.durationMicroseconds = -1;
config.offloadInfo.bitWidth = 16;
config.offloadInfo.bufferSize = 256; // arbitrary value
}
result.emplace_back(device, config, 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& mixPort : module->getFirstMixPorts()->getMixPort()) {
if (mixPort.getRole() != xsd::Role::sink) continue; // not an input profile
std::vector<AudioInOutFlag> flags;
std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(), flags.begin(),
[](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);
}
}
}
}
return result;
}();
return parameters;
}

View file

@ -0,0 +1,91 @@
/*
* Copyright (C) 2020 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
// 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.
namespace xsd {
using Module = Modules::Module;
}
class PolicyConfig {
public:
explicit PolicyConfig(const std::string& configFileName)
: mConfigFileName{configFileName},
mFilePath{findExistingConfigurationFile(mConfigFileName)},
mConfig{xsd::read(mFilePath.c_str())} {
if (mConfig) {
mStatus = OK;
mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice);
for (const auto& module : mConfig->getFirstModules()->get_module()) {
auto attachedDevices = module.getFirstAttachedDevices()->getItem();
if (!attachedDevices.empty()) {
mModulesWithDevicesNames.insert(module.getName());
}
}
}
}
status_t getStatus() const { return mStatus; }
std::string getError() const {
if (mFilePath.empty()) {
return std::string{"Could not find "} + mConfigFileName +
" file in: " + testing::PrintToString(android::audio_get_configuration_paths());
} else {
return "Invalid config file: " + mFilePath;
}
}
const std::string& getFilePath() const { return mFilePath; }
const xsd::Module* getModuleFromName(const std::string& name) const {
if (mConfig) {
for (const auto& module : mConfig->getFirstModules()->get_module()) {
if (module.getName() == name) return &module;
}
}
return nullptr;
}
const xsd::Module* getPrimaryModule() const { return mPrimaryModule; }
const std::set<std::string>& getModulesWithDevicesNames() const {
return mModulesWithDevicesNames;
}
bool haveInputProfilesInModule(const std::string& name) const {
auto module = getModuleFromName(name);
for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
if (mixPort.getRole() == xsd::Role::sink) return true;
}
return false;
}
private:
static std::string findExistingConfigurationFile(const std::string& fileName) {
for (const auto& location : android::audio_get_configuration_paths()) {
std::string path = location + '/' + fileName;
if (access(path.c_str(), F_OK) == 0) {
return path;
}
}
return std::string{};
}
const std::string mConfigFileName;
const std::string mFilePath;
std::optional<xsd::AudioPolicyConfiguration> mConfig;
status_t mStatus = NO_INIT;
const xsd::Module* mPrimaryModule;
std::set<std::string> mModulesWithDevicesNames;
};

View file

@ -19,9 +19,6 @@ cc_defaults {
defaults: ["VtsHalTargetTestDefaults"],
static_libs: [
"android.hardware.audio.common.test.utility",
"libaudiofoundation",
"libaudiopolicycomponents",
"libmedia_helper",
"libxml2",
],
shared_libs: [
@ -44,6 +41,9 @@ cc_test {
"2.0/AudioPrimaryHidlHalTest.cpp",
],
static_libs: [
"libaudiofoundation",
"libaudiopolicycomponents",
"libmedia_helper",
"android.hardware.audio@2.0",
"android.hardware.audio.common@2.0",
],
@ -67,6 +67,9 @@ cc_test {
"4.0/AudioPrimaryHidlHalTest.cpp",
],
static_libs: [
"libaudiofoundation",
"libaudiopolicycomponents",
"libmedia_helper",
"android.hardware.audio@4.0",
"android.hardware.audio.common@4.0",
],
@ -90,6 +93,9 @@ cc_test {
"5.0/AudioPrimaryHidlHalTest.cpp",
],
static_libs: [
"libaudiofoundation",
"libaudiopolicycomponents",
"libmedia_helper",
"android.hardware.audio@5.0",
"android.hardware.audio.common@5.0",
],
@ -113,6 +119,9 @@ cc_test {
"6.0/AudioPrimaryHidlHalTest.cpp",
],
static_libs: [
"libaudiofoundation",
"libaudiopolicycomponents",
"libmedia_helper",
"android.hardware.audio@6.0",
"android.hardware.audio.common@6.0",
],
@ -130,7 +139,6 @@ cc_test {
}
cc_test {
enabled: false,
name: "VtsHalAudioV7_0TargetTest",
defaults: ["VtsHalAudioTargetTest_defaults"],
srcs: [
@ -139,6 +147,7 @@ cc_test {
static_libs: [
"android.hardware.audio@7.0",
"android.hardware.audio.common@7.0",
"android.hardware.audio.common@7.0-enums",
],
cflags: [
"-DMAJOR_VERSION=7",

View file

@ -42,8 +42,11 @@
#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)
#if MAJOR_VERSION >= 7
#include <audio_policy_configuration_V7_0-enums.h>
#include <audio_policy_configuration_V7_0.h>
#endif
#include <Serializer.h>
#include <fmq/EventFlag.h>
#include <fmq/MessageQueue.h>
#include <hidl/GtestPrinter.h>
@ -63,14 +66,6 @@
#include "4.0/AudioPrimaryHidlHalUtils.h"
#endif
using std::initializer_list;
using std::list;
using std::string;
using std::to_string;
using std::vector;
using ::android::AudioPolicyConfig;
using ::android::HwModule;
using ::android::NO_INIT;
using ::android::OK;
using ::android::sp;
@ -93,6 +88,12 @@ using ::android::hardware::details::toHexString;
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::common::test::utility;
using namespace ::android::hardware::audio::CPP_VERSION;
#if MAJOR_VERSION >= 7
// Make an alias for enumerations generated from the APM config XSD.
namespace xsd {
using namespace ::audio::policy::configuration::CPP_VERSION;
}
#endif
// Typical accepted results from interface methods
static auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED};
@ -103,8 +104,12 @@ static auto okOrInvalidStateOrNotSupported = {Result::OK, Result::INVALID_STATE,
static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED};
static auto invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUPPORTED};
#define AUDIO_PRIMARY_HIDL_HAL_TEST
#include "DeviceManager.h"
#if MAJOR_VERSION <= 6
#include "PolicyConfig.h"
#elif MAJOR_VERSION >= 7
#include "7.0/PolicyConfig.h"
#endif
class HidlTest : public ::testing::Test {
public:
@ -136,83 +141,16 @@ class HidlTest : public ::testing::Test {
////////////////////////// Audio policy configuration ////////////////////////
//////////////////////////////////////////////////////////////////////////////
static constexpr char kConfigFileName[] = "audio_policy_configuration.xml";
// Stringify the argument.
#define QUOTE(x) #x
#define STRINGIFY(x) QUOTE(x)
struct PolicyConfigData {
android::HwModuleCollection hwModules;
android::DeviceVector availableOutputDevices;
android::DeviceVector availableInputDevices;
sp<android::DeviceDescriptor> defaultOutputDevice;
};
class PolicyConfig : private PolicyConfigData, public AudioPolicyConfig {
public:
PolicyConfig()
: AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices,
defaultOutputDevice) {
for (const auto& location : android::audio_get_configuration_paths()) {
std::string path = location + '/' + kConfigFileName;
if (access(path.c_str(), F_OK) == 0) {
mFilePath = path;
break;
}
}
mStatus = android::deserializeAudioPolicyFile(mFilePath.c_str(), this);
if (mStatus == OK) {
mPrimaryModule = getHwModules().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;
}
}
}
}
}
status_t getStatus() const { return mStatus; }
std::string getError() const {
if (mFilePath.empty()) {
return std::string{"Could not find "} + kConfigFileName +
" file in: " + testing::PrintToString(android::audio_get_configuration_paths());
} else {
return "Invalid config file: " + mFilePath;
}
}
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;
}
private:
status_t mStatus = NO_INIT;
std::string mFilePath;
sp<HwModule> mPrimaryModule = nullptr;
std::set<std::string> mModulesWithDevicesNames;
};
static constexpr char kConfigFileName[] = "audio_policy_configuration.xml";
// Cached policy config after parsing for faster test startup
const PolicyConfig& getCachedPolicyConfig() {
static std::unique_ptr<PolicyConfig> policyConfig = [] {
auto config = std::make_unique<PolicyConfig>();
auto config = std::make_unique<PolicyConfig>(kConfigFileName);
return config;
}();
return *policyConfig;
@ -449,9 +387,10 @@ class AccessorHidlTest : public BaseTestClass {
* The getter and/or the setter may return NOT_SUPPORTED if optionality == OPTIONAL.
*/
template <Optionality optionality = REQUIRED, class IUTGetter, class Getter, class Setter>
void testAccessors(IUTGetter iutGetter, const string& propertyName,
const Initial expectedInitial, list<Property> valuesToTest, Setter setter,
Getter getter, const vector<Property>& invalidValues = {}) {
void testAccessors(IUTGetter iutGetter, const std::string& propertyName,
const Initial expectedInitial, std::list<Property> valuesToTest,
Setter setter, Getter getter,
const std::vector<Property>& invalidValues = {}) {
const auto expectedResults = {Result::OK,
optionality == OPTIONAL ? Result::NOT_SUPPORTED : Result::OK};
@ -495,9 +434,9 @@ class AccessorHidlTest : public BaseTestClass {
EXPECT_RESULT(expectedResults, ((this->*iutGetter)().get()->*setter)(initialValue));
}
template <Optionality optionality = REQUIRED, class Getter, class Setter>
void testAccessors(const string& propertyName, const Initial expectedInitial,
list<Property> valuesToTest, Setter setter, Getter getter,
const vector<Property>& invalidValues = {}) {
void testAccessors(const std::string& propertyName, const Initial expectedInitial,
std::list<Property> valuesToTest, Setter setter, Getter getter,
const std::vector<Property>& invalidValues = {}) {
testAccessors<optionality>(&BaseTestClass::getDevice, propertyName, expectedInitial,
valuesToTest, setter, getter, invalidValues);
}
@ -573,9 +512,13 @@ 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<DeviceParameter, AudioConfig, std::variant<AudioInputFlag, AudioOutputFlag>>;
#elif MAJOR_VERSION >= 7
using DeviceConfigParameter = std::tuple<DeviceParameter, AudioConfig, std::vector<AudioInOutFlag>>;
#endif
#if MAJOR_VERSION >= 6
const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters();
@ -583,8 +526,8 @@ const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters();
#endif
#if MAJOR_VERSION >= 4
static string SanitizeStringForGTestName(const string& s) {
string result = s;
static std::string SanitizeStringForGTestName(const std::string& s) {
std::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] = '_';
@ -598,43 +541,57 @@ static string SanitizeStringForGTestName(const string& s) {
* As the only parameter changing are channel mask and sample rate,
* only print those ones in the test name.
*/
static string DeviceConfigParameterToString(
static std::string DeviceConfigParameterToString(
const testing::TestParamInfo<DeviceConfigParameter>& info) {
const AudioConfig& config = std::get<PARAM_CONFIG>(info.param);
const auto deviceName = DeviceParameterToString(::testing::TestParamInfo<DeviceParameter>{
std::get<PARAM_DEVICE>(info.param), info.index});
return (deviceName.empty() ? "" : deviceName + "_") + to_string(info.index) + "__" +
to_string(config.sampleRateHz) + "_" +
// "MONO" is more clear than "FRONT_LEFT"
((config.channelMask == mkEnumBitfield(AudioChannelMask::OUT_MONO) ||
config.channelMask == mkEnumBitfield(AudioChannelMask::IN_MONO))
? "MONO"
const auto devicePart =
(deviceName.empty() ? "" : deviceName + "_") + std::to_string(info.index);
// The types had changed a lot between versions 2, 4..6 and 7. Use separate
// code sections for easier understanding.
#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)));
const auto configPart =
std::to_string(config.sampleRateHz) + "_" +
// "MONO" is more clear than "FRONT_LEFT"
(config.channelMask == AudioChannelMask::OUT_MONO ||
config.channelMask == AudioChannelMask::IN_MONO
? "MONO"
: ::testing::PrintToString(config.channelMask)) +
"_" +
std::visit([](auto&& arg) -> std::string { return ::testing::PrintToString(arg); },
std::get<PARAM_FLAGS>(info.param));
#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
const auto configPart =
std::to_string(config.sampleRateHz) + "_" +
// "MONO" is more clear than "FRONT_LEFT"
(config.channelMask == mkEnumBitfield(AudioChannelMask::OUT_MONO) ||
config.channelMask == mkEnumBitfield(AudioChannelMask::IN_MONO)
? "MONO"
// 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))) +
"_" +
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)));
#elif MAJOR_VERSION >= 7
const auto configPart =
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)));
#endif
return devicePart + "__" + configPart;
}
class AudioHidlTestWithDeviceConfigParameter
@ -660,7 +617,7 @@ class AudioHidlTestWithDeviceConfigParameter
AudioOutputFlag getOutputFlags() const {
return std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam()));
}
#elif MAJOR_VERSION >= 4
#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
hidl_bitfield<AudioInputFlag> getInputFlags() const {
return hidl_bitfield<AudioInputFlag>(
std::get<INDEX_INPUT>(std::get<PARAM_FLAGS>(GetParam())));
@ -669,10 +626,17 @@ class AudioHidlTestWithDeviceConfigParameter
return hidl_bitfield<AudioOutputFlag>(
std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam())));
}
#elif MAJOR_VERSION >= 7
hidl_vec<AudioInOutFlag> getInputFlags() const { return std::get<PARAM_FLAGS>(GetParam()); }
hidl_vec<AudioInOutFlag> getOutputFlags() const { return std::get<PARAM_FLAGS>(GetParam()); }
#endif
};
#if MAJOR_VERSION <= 6
#define AUDIO_PRIMARY_HIDL_HAL_TEST
#include "ConfigHelper.h"
#undef AUDIO_PRIMARY_HIDL_HAL_TEST
#endif
//////////////////////////////////////////////////////////////////////////////
///////////////////////////// getInputBufferSize /////////////////////////////
@ -839,7 +803,7 @@ class StreamHelper {
AudioConfig* suggestedConfigPtr) {
// FIXME: Open a stream without an IOHandle
// This is not required to be accepted by hal implementations
AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
AudioIoHandle ioHandle{};
AudioConfig suggestedConfig{};
bool retryWithSuggestedConfig = true;
if (suggestedConfigPtr == nullptr) {
@ -932,7 +896,11 @@ class OpenStreamTest : public AudioHidlTestWithDeviceConfigParameter {
class OutputStreamTest : public OpenStreamTest<IStreamOut> {
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
#if MAJOR_VERSION <= 6
address.device = AudioDevice::OUT_DEFAULT;
#elif MAJOR_VERSION >= 7
address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT);
#endif
const AudioConfig& config = getConfig();
auto flags = getOutputFlags();
testOpen(
@ -946,13 +914,19 @@ class OutputStreamTest : public OpenStreamTest<IStreamOut> {
},
config);
}
#if MAJOR_VERSION >= 4
#if MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
protected:
protected:
const SourceMetadata initMetadata = {
{ { AudioUsage::MEDIA,
AudioContentType::MUSIC,
1 /* gain */ } }};
#elif MAJOR_VERSION >= 7
protected:
const SourceMetadata initMetadata = {
{ { toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
1 /* gain */ } }};
#endif
};
TEST_P(OutputStreamTest, OpenOutputStreamTest) {
@ -995,7 +969,11 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OutputStreamTest);
class InputStreamTest : public OpenStreamTest<IStreamIn> {
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
#if MAJOR_VERSION <= 6
address.device = AudioDevice::IN_DEFAULT;
#elif MAJOR_VERSION <= 7
address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT);
#endif
const AudioConfig& config = getConfig();
auto flags = getInputFlags();
testOpen(
@ -1009,8 +987,11 @@ class InputStreamTest : public OpenStreamTest<IStreamIn> {
protected:
#if MAJOR_VERSION == 2
const AudioSource initMetadata = AudioSource::DEFAULT;
#elif MAJOR_VERSION >= 4
const SinkMetadata initMetadata = {{{.source = AudioSource::DEFAULT, .gain = 1}}};
#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
const SinkMetadata initMetadata = {{ {.source = AudioSource::DEFAULT, .gain = 1 } }};
#elif MAJOR_VERSION >= 7
const SinkMetadata initMetadata = {
{{.source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT), .gain = 1}}};
#endif
};
@ -1067,6 +1048,7 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InputStreamTest);
TEST_IO_STREAM(GetFrameCount, "Check that getting stream frame count does not crash the HAL.",
ASSERT_TRUE(stream->getFrameCount().isOk()))
#if MAJOR_VERSION <= 6
TEST_IO_STREAM(GetSampleRate, "Check that the stream sample rate == the one it was opened with",
ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate())))
@ -1075,6 +1057,7 @@ TEST_IO_STREAM(GetChannelMask, "Check that the stream channel mask == the one it
TEST_IO_STREAM(GetFormat, "Check that the stream format == the one it was opened with",
ASSERT_EQ(audioConfig.format, extract(stream->getFormat())))
#endif
// TODO: for now only check that the framesize is not incoherent
TEST_IO_STREAM(GetFrameSize, "Check that the stream frame size == the one it was opened with",
@ -1084,7 +1067,7 @@ TEST_IO_STREAM(GetBufferSize, "Check that the stream buffer size== the one it wa
ASSERT_GE(extract(stream->getBufferSize()), extract(stream->getFrameSize())));
template <class Property, class CapabilityGetter>
static void testCapabilityGetter(const string& name, IStream* stream,
static void testCapabilityGetter(const std::string& name, IStream* stream,
CapabilityGetter capabilityGetter,
Return<Property> (IStream::*getter)(),
Return<Result> (IStream::*setter)(Property),
@ -1120,6 +1103,7 @@ static void testCapabilityGetter(const string& name, IStream* stream,
}
}
#if MAJOR_VERSION <= 6
TEST_IO_STREAM(SupportedSampleRate, "Check that the stream sample rate is declared as supported",
testCapabilityGetter("getSupportedSampleRate", stream.get(),
&GetSupported::sampleRates, &IStream::getSampleRate,
@ -1137,19 +1121,71 @@ TEST_IO_STREAM(SupportedChannelMask, "Check that the stream channel mask is decl
TEST_IO_STREAM(SupportedFormat, "Check that the stream format is declared as supported",
testCapabilityGetter("getSupportedFormat", stream.get(), &GetSupported::formats,
&IStream::getFormat, &IStream::setFormat))
#else
static void testGetSupportedProfiles(IStream* stream) {
Result res;
hidl_vec<AudioProfile> profiles;
auto ret = stream->getSupportedProfiles(returnIn(res, profiles));
EXPECT_TRUE(ret.isOk());
if (res == Result::OK) {
EXPECT_GT(profiles.size(), 0);
} else {
EXPECT_EQ(Result::NOT_SUPPORTED, res);
}
}
TEST_IO_STREAM(GetSupportedProfiles, "Try to call optional method GetSupportedProfiles",
testGetSupportedProfiles(stream.get()))
static void testSetAudioProperties(IStream* stream) {
Result res;
hidl_vec<AudioProfile> profiles;
auto ret = stream->getSupportedProfiles(returnIn(res, profiles));
EXPECT_TRUE(ret.isOk());
if (res == Result::NOT_SUPPORTED) {
GTEST_SKIP() << "Retrieving supported profiles is not implemented";
}
for (const auto& profile : profiles) {
for (const auto& sampleRate : profile.sampleRates) {
for (const auto& channelMask : profile.channelMasks) {
AudioConfigBase config{.format = profile.format,
.sampleRateHz = sampleRate,
.channelMask = channelMask};
auto ret = stream->setAudioProperties(config);
EXPECT_TRUE(ret.isOk());
EXPECT_EQ(Result::OK, ret) << config.format << "; " << config.sampleRateHz << "; "
<< toString(config.channelMask);
}
}
}
}
TEST_IO_STREAM(SetAudioProperties, "Call setAudioProperties for all supported profiles",
testSetAudioProperties(stream.get()))
#endif
static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) {
#if MAJOR_VERSION <= 6
uint32_t sampleRateHz;
auto mask = mkEnumBitfield<AudioChannelMask>({});
AudioFormat format;
stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
auto ret = stream->getAudioProperties(returnIn(sampleRateHz, mask, format));
EXPECT_TRUE(ret.isOk());
// FIXME: the qcom hal it does not currently negotiate the sampleRate &
// channel mask
EXPECT_EQ(expectedConfig.sampleRateHz, sampleRateHz);
EXPECT_EQ(expectedConfig.channelMask, mask);
EXPECT_EQ(expectedConfig.format, format);
#elif MAJOR_VERSION >= 7
AudioConfigBase actualConfig{};
auto ret = stream->getAudioProperties(returnIn(actualConfig));
EXPECT_TRUE(ret.isOk());
EXPECT_EQ(expectedConfig.base.sampleRateHz, actualConfig.sampleRateHz);
EXPECT_EQ(expectedConfig.base.channelMask, actualConfig.channelMask);
EXPECT_EQ(expectedConfig.base.format, actualConfig.format);
#endif
}
TEST_IO_STREAM(GetAudioProperties,
@ -1160,7 +1196,7 @@ TEST_IO_STREAM(SetHwAvSync, "Try to set hardware sync to an invalid value",
ASSERT_RESULT(okOrNotSupportedOrInvalidArgs, stream->setHwAvSync(666)))
static void checkGetNoParameter(IStream* stream, hidl_vec<hidl_string> keys,
initializer_list<Result> expectedResults) {
std::initializer_list<Result> expectedResults) {
hidl_vec<ParameterValue> parameters;
Result res;
ASSERT_OK(Parameters::get(stream, keys, returnIn(res, parameters)));
@ -1271,7 +1307,11 @@ TEST_P(InputStreamTest, GetAudioSource) {
return;
}
ASSERT_OK(res);
#if MAJOR_VERSION <= 6
ASSERT_EQ(AudioSource::DEFAULT, source);
#elif MAJOR_VERSION >= 7
ASSERT_EQ(xsd::AudioSource::AUDIO_SOURCE_DEFAULT, xsd::stringToAudioSource(source));
#endif
}
static void testUnitaryGain(std::function<Return<Result>(float)> setGain) {
@ -1286,7 +1326,7 @@ static void testUnitaryGain(std::function<Return<Result>(float)> setGain) {
}
static void testOptionalUnitaryGain(std::function<Return<Result>(float)> setGain,
string debugName) {
std::string debugName) {
auto result = setGain(1);
ASSERT_IS_OK(result);
if (result == Result::NOT_SUPPORTED) {
@ -1306,7 +1346,7 @@ static void testPrepareForReading(IStreamIn* stream, uint32_t frameSize, uint32_
Result res;
// Ignore output parameters as the call should fail
ASSERT_OK(stream->prepareForReading(frameSize, framesCount,
[&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
[&res](auto r, auto&, auto&, auto&, auto) { res = r; }));
EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
}
@ -1371,7 +1411,7 @@ static void testPrepareForWriting(IStreamOut* stream, uint32_t frameSize, uint32
Result res;
// Ignore output parameters as the call should fail
ASSERT_OK(stream->prepareForWriting(frameSize, framesCount,
[&res](auto r, auto&, auto&, auto&, auto&) { res = r; }));
[&res](auto r, auto&, auto&, auto&, auto) { res = r; }));
EXPECT_RESULT(Result::INVALID_ARGUMENTS, res);
}

View file

@ -14,6 +14,8 @@
* limitations under the License.
*/
#pragma once
// Code in this file uses 'getCachedPolicyConfig'
#ifndef AUDIO_PRIMARY_HIDL_HAL_TEST
#error Must be included from AudioPrimaryHidlTest.h
@ -46,32 +48,32 @@ struct ConfigHelper {
}
// Cache result ?
static const vector<AudioConfig> getRequiredSupportPlaybackAudioConfig() {
static const std::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() {
static const std::vector<AudioConfig> getRecommendedSupportPlaybackAudioConfig() {
return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
{24000, 48000}, {AudioFormat::PCM_16_BIT});
}
static const vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
static const std::vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
if (!primaryHasMic()) return {};
return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100},
{AudioFormat::PCM_16_BIT});
}
static const vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
static const std::vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
if (!primaryHasMic()) return {};
return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000},
{AudioFormat::PCM_16_BIT});
}
static vector<AudioConfig> combineAudioConfig(vector<audio_channel_mask_t> channelMasks,
vector<uint32_t> sampleRates,
audio_format_t format) {
vector<AudioConfig> configs;
static std::vector<AudioConfig> combineAudioConfig(
std::vector<audio_channel_mask_t> channelMasks, std::vector<uint32_t> sampleRates,
audio_format_t format) {
std::vector<AudioConfig> configs;
configs.reserve(channelMasks.size() * sampleRates.size());
for (auto channelMask : channelMasks) {
for (auto sampleRate : sampleRates) {
@ -86,10 +88,10 @@ struct ConfigHelper {
return configs;
}
static vector<AudioConfig> combineAudioConfig(vector<AudioChannelMask> channelMasks,
vector<uint32_t> sampleRates,
vector<AudioFormat> formats) {
vector<AudioConfig> configs;
static std::vector<AudioConfig> combineAudioConfig(std::vector<AudioChannelMask> channelMasks,
std::vector<uint32_t> sampleRates,
std::vector<AudioFormat> formats) {
std::vector<AudioConfig> configs;
configs.reserve(channelMasks.size() * sampleRates.size() * formats.size());
for (auto channelMask : channelMasks) {
for (auto sampleRate : sampleRates) {

View file

@ -14,10 +14,11 @@
* limitations under the License.
*/
// Code in this file uses 'environment'
#ifndef AUDIO_PRIMARY_HIDL_HAL_TEST
#error Must be included from AudioPrimaryHidlTest.h
#endif
#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.
template <class Derived, class Key, class Interface>
class InterfaceManager {

View file

@ -0,0 +1,96 @@
/*
* Copyright (C) 2020 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
// 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 <Serializer.h>
struct PolicyConfigData {
android::HwModuleCollection hwModules;
android::DeviceVector availableOutputDevices;
android::DeviceVector availableInputDevices;
sp<android::DeviceDescriptor> defaultOutputDevice;
};
class PolicyConfig : private PolicyConfigData, public android::AudioPolicyConfig {
public:
explicit PolicyConfig(const std::string& configFileName)
: android::AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices,
defaultOutputDevice),
mConfigFileName{configFileName} {
for (const auto& location : android::audio_get_configuration_paths()) {
std::string path = location + '/' + mConfigFileName;
if (access(path.c_str(), F_OK) == 0) {
mFilePath = path;
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;
}
}
}
}
}
status_t getStatus() const { return mStatus; }
std::string getError() const {
if (mFilePath.empty()) {
return std::string{"Could not find "} + mConfigFileName +
" file in: " + testing::PrintToString(android::audio_get_configuration_paths());
} else {
return "Invalid config file: " + mFilePath;
}
}
const std::string& getFilePath() const { return mFilePath; }
sp<const android::HwModule> getModuleFromName(const std::string& name) const {
return getHwModules().getModuleFromName(name.c_str());
}
sp<const android::HwModule> getPrimaryModule() const { return mPrimaryModule; }
const std::set<std::string>& getModulesWithDevicesNames() const {
return mModulesWithDevicesNames;
}
bool haveInputProfilesInModule(const std::string& name) const {
auto module = getModuleFromName(name);
return module && !module->getInputProfiles().empty();
}
private:
const std::string mConfigFileName;
status_t mStatus = NO_INIT;
std::string mFilePath;
sp<const android::HwModule> mPrimaryModule = nullptr;
std::set<std::string> mModulesWithDevicesNames;
};

View file

@ -118,7 +118,6 @@ cc_test {
}
cc_test {
enabled: false,
name: "VtsHalAudioEffectV7_0TargetTest",
defaults: ["VtsHalAudioEffectTargetTest_default"],
// Use test_config for vts suite.
@ -126,6 +125,7 @@ cc_test {
test_config: "VtsHalAudioEffectV7_0TargetTest.xml",
static_libs: [
"android.hardware.audio.common@7.0",
"android.hardware.audio.common@7.0-enums",
"android.hardware.audio.effect@7.0",
],
data: [

View file

@ -16,7 +16,9 @@
#define LOG_TAG "AudioEffectHidlHalTest"
#include <android-base/logging.h>
#if MAJOR_VERSION <= 6
#include <system/audio.h>
#endif
#include PATH(android/hardware/audio/effect/FILE_VERSION/IEffect.h)
#include PATH(android/hardware/audio/effect/FILE_VERSION/IEffectsFactory.h)
@ -25,6 +27,10 @@
#include PATH(android/hardware/audio/effect/FILE_VERSION/types.h)
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMemory.h>
#if MAJOR_VERSION >= 7
#include <audio_policy_configuration_V7_0-enums.h>
#include <audio_policy_configuration_V7_0.h>
#endif
#include <common/all-versions/VersionUtils.h>
@ -45,6 +51,12 @@ using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::effect::CPP_VERSION;
#if MAJOR_VERSION >= 7
// Make an alias for enumerations generated from the APM config XSD.
namespace xsd {
using namespace ::audio::policy::configuration::CPP_VERSION;
}
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
@ -171,7 +183,7 @@ class AudioEffectHidlTest : public ::testing::TestWithParam<EffectParameter> {
effectsFactory = IEffectsFactory::getService(std::get<PARAM_FACTORY_NAME>(GetParam()));
ASSERT_NE(nullptr, effectsFactory.get());
findAndCreateEffect(getEffectType());
ASSERT_NO_FATAL_FAILURE(findAndCreateEffect(getEffectType()));
ASSERT_NE(nullptr, effect.get());
Return<Result> ret = effect->init();
@ -201,7 +213,7 @@ class AudioEffectHidlTest : public ::testing::TestWithParam<EffectParameter> {
void AudioEffectHidlTest::findAndCreateEffect(const Uuid& type) {
Uuid effectUuid;
findEffectInstance(type, &effectUuid);
ASSERT_NO_FATAL_FAILURE(findEffectInstance(type, &effectUuid));
Return<void> ret = effectsFactory->createEffect(
effectUuid, 1 /*session*/, 1 /*ioHandle*/,
#if MAJOR_VERSION >= 6
@ -244,10 +256,16 @@ void AudioEffectHidlTest::getChannelCount(uint32_t* channelCount) {
});
ASSERT_TRUE(ret.isOk());
ASSERT_EQ(Result::OK, retval);
#if MAJOR_VERSION <= 6
ASSERT_TRUE(audio_channel_mask_is_valid(
static_cast<audio_channel_mask_t>(currentConfig.outputCfg.channels)));
*channelCount = audio_channel_count_from_out_mask(
static_cast<audio_channel_mask_t>(currentConfig.outputCfg.channels));
#else
*channelCount =
audio::policy::configuration::V7_0::getChannelCount(currentConfig.outputCfg.channels);
ASSERT_NE(*channelCount, 0);
#endif
}
TEST_P(AudioEffectHidlTest, Close) {
@ -391,7 +409,12 @@ TEST_P(AudioEffectHidlTest, DisableEnableDisable) {
TEST_P(AudioEffectHidlTest, SetDevice) {
description("Verify that SetDevice works for an output chain effect");
#if MAJOR_VERSION <= 6
Return<Result> ret = effect->setDevice(mkEnumBitfield(AudioDevice::OUT_SPEAKER));
#else
DeviceAddress device{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER)};
Return<Result> ret = effect->setDevice(device);
#endif
EXPECT_TRUE(ret.isOk());
EXPECT_EQ(Result::OK, ret);
}
@ -441,22 +464,28 @@ TEST_P(AudioEffectHidlTest, SetConfigReverse) {
TEST_P(AudioEffectHidlTest, SetInputDevice) {
description("Verify that SetInputDevice does not crash");
#if MAJOR_VERSION <= 6
Return<Result> ret = effect->setInputDevice(mkEnumBitfield(AudioDevice::IN_BUILTIN_MIC));
#else
DeviceAddress device{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC)};
Return<Result> ret = effect->setInputDevice(device);
#endif
EXPECT_TRUE(ret.isOk());
}
TEST_P(AudioEffectHidlTest, SetAudioSource) {
description("Verify that SetAudioSource does not crash");
#if MAJOR_VERSION <= 6
Return<Result> ret = effect->setAudioSource(AudioSource::MIC);
#else
Return<Result> ret = effect->setAudioSource(toString(xsd::AudioSource::AUDIO_SOURCE_MIC));
#endif
EXPECT_TRUE(ret.isOk());
}
TEST_P(AudioEffectHidlTest, Offload) {
description("Verify that calling Offload method does not crash");
EffectOffloadParameter offloadParam;
offloadParam.isOffload = false;
offloadParam.ioHandle = static_cast<int>(AudioHandleConsts::AUDIO_IO_HANDLE_NONE);
Return<Result> ret = effect->offload(offloadParam);
Return<Result> ret = effect->offload(EffectOffloadParameter{});
EXPECT_TRUE(ret.isOk());
}