mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 22:04:26 +00:00
audio: Implement VTS tests for V7.0 am: d72a7c27ab am: c70238a35b
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1507220 Change-Id: If805eb94f5b0fee507186dc303b8e61a38ef2b11
This commit is contained in:
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user