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:
parent
c9e1607de4
commit
343450a074
14 changed files with 856 additions and 185 deletions
|
@ -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",
|
||||
|
|
|
@ -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
|
|
@ -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({}));
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
91
audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
Normal file
91
audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
Normal 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;
|
||||
};
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
96
audio/core/all-versions/vts/functional/PolicyConfig.h
Normal file
96
audio/core/all-versions/vts/functional/PolicyConfig.h
Normal 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;
|
||||
};
|
|
@ -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: [
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue