Merge changes I7d42f8a7,I0482376e

* changes:
  audio VTS: add CompressedOffloadOutputStream test
  audio VTS: Refactor test parameter generation for I/O streams
This commit is contained in:
TreeHugger Robot
2022-06-29 18:52:56 +00:00
committed by Android (Google) Code Review
9 changed files with 209 additions and 106 deletions

View File

@@ -14,6 +14,9 @@
* limitations under the License.
*/
#include <fstream>
#include <numeric>
#include <android-base/chrono_utils.h>
#include "Generators.h"
@@ -517,20 +520,10 @@ class PcmOnlyConfigOutputStreamTest : public OutputStreamTest {
}
bool canQueryPresentationPosition() const {
auto maybeSinkAddress =
getCachedPolicyConfig().getSinkDeviceForMixPort(getDeviceName(), getMixPortName());
// Returning 'true' when no sink is found so the test can fail later with a more clear
// problem description.
return !maybeSinkAddress.has_value() ||
!xsd::isTelephonyDevice(maybeSinkAddress.value().deviceType);
return !xsd::isTelephonyDevice(address.deviceType);
}
void createPatchIfNeeded() {
auto maybeSinkAddress =
getCachedPolicyConfig().getSinkDeviceForMixPort(getDeviceName(), getMixPortName());
ASSERT_TRUE(maybeSinkAddress.has_value())
<< "No sink device found for mix port " << getMixPortName() << " (module "
<< getDeviceName() << ")";
if (areAudioPatchesSupported()) {
AudioPortConfig source;
source.base.format.value(getConfig().base.format);
@@ -540,13 +533,13 @@ class PcmOnlyConfigOutputStreamTest : public OutputStreamTest {
source.ext.mix().ioHandle = helper.getIoHandle();
source.ext.mix().useCase.stream({});
AudioPortConfig sink;
sink.ext.device(maybeSinkAddress.value());
sink.ext.device(address);
EXPECT_OK(getDevice()->createAudioPatch(hidl_vec<AudioPortConfig>{source},
hidl_vec<AudioPortConfig>{sink},
returnIn(res, mPatchHandle)));
mHasPatch = res == Result::OK;
} else {
EXPECT_OK(stream->setDevices({maybeSinkAddress.value()}));
EXPECT_OK(stream->setDevices({address}));
}
}
@@ -556,10 +549,6 @@ class PcmOnlyConfigOutputStreamTest : public OutputStreamTest {
EXPECT_OK(getDevice()->releaseAudioPatch(mPatchHandle));
mHasPatch = false;
}
} else {
if (stream) {
EXPECT_OK(stream->setDevices({address}));
}
}
}
@@ -575,16 +564,22 @@ class PcmOnlyConfigOutputStreamTest : public OutputStreamTest {
// Sometimes HAL doesn't have enough information until the audio data actually gets
// consumed by the hardware.
bool timedOut = false;
res = Result::INVALID_STATE;
for (android::base::Timer elapsed;
res != Result::OK && !writer.hasError() &&
!(timedOut = (elapsed.duration() >= kPositionChangeTimeout));) {
usleep(kWriteDurationUs);
ASSERT_OK(stream->getPresentationPosition(returnIn(res, framesInitial, ts)));
ASSERT_RESULT(okOrInvalidState, res);
if (!firstPosition || *firstPosition == std::numeric_limits<uint64_t>::max()) {
res = Result::INVALID_STATE;
for (android::base::Timer elapsed;
res != Result::OK && !writer.hasError() &&
!(timedOut = (elapsed.duration() >= kPositionChangeTimeout));) {
usleep(kWriteDurationUs);
ASSERT_OK(stream->getPresentationPosition(returnIn(res, framesInitial, ts)));
ASSERT_RESULT(okOrInvalidState, res);
}
ASSERT_FALSE(writer.hasError());
ASSERT_FALSE(timedOut);
} else {
// Use `firstPosition` instead of querying it from the HAL. This is used when
// `waitForPresentationPositionAdvance` is called in a loop.
framesInitial = *firstPosition;
}
ASSERT_FALSE(writer.hasError());
ASSERT_FALSE(timedOut);
uint64_t frames = framesInitial;
for (android::base::Timer elapsed;
@@ -646,7 +641,7 @@ TEST_P(PcmOnlyConfigOutputStreamTest, PresentationPositionPreservedOnStandby) {
ASSERT_OK(stream->standby());
writer.resume();
uint64_t frames;
uint64_t frames = std::numeric_limits<uint64_t>::max();
ASSERT_NO_FATAL_FAILURE(waitForPresentationPositionAdvance(writer, &frames));
EXPECT_GT(frames, framesInitial);
@@ -691,24 +686,12 @@ class PcmOnlyConfigInputStreamTest : public InputStreamTest {
InputStreamTest::TearDown();
}
bool canQueryCapturePosition() const {
auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
getDeviceName(), getMixPortName());
// Returning 'true' when no source is found so the test can fail later with a more clear
// problem description.
return !maybeSourceAddress.has_value() ||
!xsd::isTelephonyDevice(maybeSourceAddress.value().deviceType);
}
bool canQueryCapturePosition() const { return !xsd::isTelephonyDevice(address.deviceType); }
void createPatchIfNeeded() {
auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
getDeviceName(), getMixPortName());
ASSERT_TRUE(maybeSourceAddress.has_value())
<< "No source device found for mix port " << getMixPortName() << " (module "
<< getDeviceName() << ")";
if (areAudioPatchesSupported()) {
AudioPortConfig source;
source.ext.device(maybeSourceAddress.value());
source.ext.device(address);
AudioPortConfig sink;
sink.base.format.value(getConfig().base.format);
sink.base.sampleRateHz.value(getConfig().base.sampleRateHz);
@@ -721,20 +704,14 @@ class PcmOnlyConfigInputStreamTest : public InputStreamTest {
returnIn(res, mPatchHandle)));
mHasPatch = res == Result::OK;
} else {
EXPECT_OK(stream->setDevices({maybeSourceAddress.value()}));
EXPECT_OK(stream->setDevices({address}));
}
}
void releasePatchIfNeeded() {
if (getDevice()) {
if (areAudioPatchesSupported() && mHasPatch) {
EXPECT_OK(getDevice()->releaseAudioPatch(mPatchHandle));
mHasPatch = false;
}
} else {
if (stream) {
EXPECT_OK(stream->setDevices({address}));
}
if (getDevice() && areAudioPatchesSupported() && mHasPatch) {
EXPECT_OK(getDevice()->releaseAudioPatch(mPatchHandle));
mHasPatch = false;
}
}
@@ -864,14 +841,8 @@ TEST_P(MicrophoneInfoInputStreamTest, GetActiveMicrophones) {
}
ASSERT_OK(res);
auto maybeSourceAddress =
getCachedPolicyConfig().getSourceDeviceForMixPort(getDeviceName(), getMixPortName());
ASSERT_TRUE(maybeSourceAddress.has_value())
<< "No source device found for mix port " << getMixPortName() << " (module "
<< getDeviceName() << ")";
for (auto microphone : microphones) {
if (microphone.deviceAddress == maybeSourceAddress.value()) {
if (microphone.deviceAddress == address) {
StreamReader reader(stream.get(), stream->getBufferSize());
ASSERT_TRUE(reader.start());
reader.pause(); // This ensures that at least one read has happened.
@@ -889,3 +860,100 @@ INSTANTIATE_TEST_CASE_P(MicrophoneInfoInputStream, MicrophoneInfoInputStreamTest
::testing::ValuesIn(getBuiltinMicConfigParameters()),
&DeviceConfigParameterToString);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MicrophoneInfoInputStreamTest);
static const std::vector<DeviceConfigParameter>& getOutputDeviceCompressedConfigParameters(
const AudioConfigBase& configToMatch) {
static const std::vector<DeviceConfigParameter> parameters = [&] {
auto allParams = getOutputDeviceConfigParameters();
std::vector<DeviceConfigParameter> compressedParams;
std::copy_if(allParams.begin(), allParams.end(), std::back_inserter(compressedParams),
[&](auto cfg) {
if (std::get<PARAM_CONFIG>(cfg).base != configToMatch) return false;
const auto& flags = std::get<PARAM_FLAGS>(cfg);
return std::find_if(flags.begin(), flags.end(), [](const auto& flag) {
return flag ==
toString(xsd::AudioInOutFlag::
AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
}) != flags.end();
});
return compressedParams;
}();
return parameters;
}
class CompressedOffloadOutputStreamTest : public PcmOnlyConfigOutputStreamTest {
public:
void loadData(const std::string& fileName, std::vector<uint8_t>* data) {
std::ifstream is(fileName, std::ios::in | std::ios::binary);
ASSERT_TRUE(is.good()) << "Failed to open file " << fileName;
is.seekg(0, is.end);
data->reserve(data->size() + is.tellg());
is.seekg(0, is.beg);
data->insert(data->end(), std::istreambuf_iterator<char>(is),
std::istreambuf_iterator<char>());
ASSERT_TRUE(!is.fail()) << "Failed to read from file " << fileName;
}
};
TEST_P(CompressedOffloadOutputStreamTest, Mp3FormatGaplessOffload) {
doc::test("Check that compressed offload mix ports for MP3 implement gapless offload");
const auto& flags = getOutputFlags();
if (std::find_if(flags.begin(), flags.end(), [](const auto& flag) {
return flag == toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD);
}) == flags.end()) {
GTEST_SKIP() << "Compressed offload mix port does not support gapless offload";
}
// FIXME: The presentation position is not updated if there is no zero padding in data.
std::vector<uint8_t> offloadData(stream->getBufferSize());
ASSERT_NO_FATAL_FAILURE(loadData("/data/local/tmp/sine882hz3s.mp3", &offloadData));
ASSERT_FALSE(offloadData.empty());
ASSERT_NO_FATAL_FAILURE(createPatchIfNeeded());
const int presentationeEndPrecisionMs = 1000;
const int sampleRate = 44100;
const int significantSampleNumber = (presentationeEndPrecisionMs * sampleRate) / 1000;
const int delay = 576 + 1000;
const int padding = 756 + 1000;
const int durationMs = 3000 - 44;
// StreamWriter plays 'offloadData' in a loop, possibly using multiple calls to 'write',
// this depends on the relative sizes of 'offloadData' and the HAL buffer. Writer calls
// 'onDataWrap' callback each time it wraps around the buffer.
StreamWriter writer(
stream.get(), stream->getBufferSize(), std::move(offloadData), [&]() /* onDataWrap */ {
Parameters::set(stream,
{{AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, std::to_string(delay)},
{AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, std::to_string(padding)}});
stream->drain(AudioDrain::EARLY_NOTIFY);
});
ASSERT_TRUE(writer.start());
ASSERT_TRUE(writer.waitForAtLeastOneCycle());
// Decrease the volume since the test plays a loud sine wave.
ASSERT_OK(stream->setVolume(0.1, 0.1));
// How many times to loop the track so that the sum of gapless delay and padding from
// the first presentation end to the last is at least 'presentationeEndPrecisionMs'.
const int playbackNumber = (int)(significantSampleNumber / ((float)delay + padding) + 1);
std::vector<float> presentationEndTimes;
uint64_t previousPosition = std::numeric_limits<uint64_t>::max();
for (int i = 0; i < playbackNumber; ++i) {
const auto start = std::chrono::steady_clock::now();
ASSERT_NO_FATAL_FAILURE(
waitForPresentationPositionAdvance(writer, &previousPosition, &previousPosition));
presentationEndTimes.push_back(std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - start)
.count());
}
const float avgDuration =
std::accumulate(presentationEndTimes.begin(), presentationEndTimes.end(), 0.0) /
presentationEndTimes.size();
EXPECT_NEAR(durationMs, avgDuration, presentationeEndPrecisionMs * 0.1);
writer.stop();
releasePatchIfNeeded();
}
INSTANTIATE_TEST_CASE_P(
CompressedOffloadOutputStream, CompressedOffloadOutputStreamTest,
::testing::ValuesIn(getOutputDeviceCompressedConfigParameters(AudioConfigBase{
.format = xsd::toString(xsd::AudioFormat::AUDIO_FORMAT_MP3),
.sampleRateHz = 44100,
.channelMask = xsd::toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO)})),
&DeviceConfigParameterToString);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CompressedOffloadOutputStreamTest);

View File

@@ -57,9 +57,6 @@ static std::vector<AudioConfig> combineAudioConfig(std::vector<xsd::AudioChannel
static std::tuple<std::vector<AudioInOutFlag>, bool> generateOutFlags(
const xsd::MixPorts::MixPort& mixPort) {
static const std::vector<AudioInOutFlag> offloadFlags = {
toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_DIRECT)};
std::vector<AudioInOutFlag> flags;
bool isOffload = false;
if (mixPort.hasFlags()) {
@@ -67,14 +64,10 @@ static std::tuple<std::vector<AudioInOutFlag>, bool> generateOutFlags(
isOffload = std::find(xsdFlags.begin(), xsdFlags.end(),
xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) !=
xsdFlags.end();
if (!isOffload) {
for (auto flag : xsdFlags) {
if (flag != xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_PRIMARY) {
flags.push_back(toString(flag));
}
for (auto flag : xsdFlags) {
if (flag != xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_PRIMARY) {
flags.push_back(toString(flag));
}
} else {
flags = offloadFlags;
}
}
return {flags, isOffload};
@@ -85,10 +78,10 @@ static AudioOffloadInfo generateOffloadInfo(const AudioConfigBase& base) {
.base = base,
.streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC),
.usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
.bitRatePerSecond = 320,
.bitRatePerSecond = 192, // as in sine882hz3s.mp3
.durationMicroseconds = -1,
.bitWidth = 16,
.bufferSize = 256 // arbitrary value
.bufferSize = 72000 // 3 seconds at 192 kbps, as in sine882hz3s.mp3
};
}
@@ -100,11 +93,10 @@ std::vector<DeviceConfigParameter> generateOutputDeviceConfigParameters(bool one
if (!module || !module->getFirstMixPorts()) break;
for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
if (mixPort.getRole() != xsd::Role::source) continue; // not an output profile
if (getCachedPolicyConfig()
.getAttachedSinkDeviceForMixPort(moduleName, mixPort.getName())
.empty()) {
continue; // no attached device
}
const auto attachedDeviceAddress =
getCachedPolicyConfig().getDeviceAddressOfSinkDeviceAttachedToMixPort(
moduleName, mixPort.getName());
if (!attachedDeviceAddress.has_value()) continue;
auto [flags, isOffload] = generateOutFlags(mixPort);
for (const auto& profile : mixPort.getProfile()) {
if (!profile.hasFormat() || !profile.hasSamplingRates() ||
@@ -118,7 +110,8 @@ std::vector<DeviceConfigParameter> generateOutputDeviceConfigParameters(bool one
if (isOffload) {
config.offloadInfo.info(generateOffloadInfo(config.base));
}
result.emplace_back(device, mixPort.getName(), config, flags);
result.emplace_back(device, mixPort.getName(), attachedDeviceAddress.value(),
config, flags);
if (oneProfilePerDevice) break;
}
if (oneProfilePerDevice) break;
@@ -162,13 +155,16 @@ const std::vector<DeviceConfigParameter>& getOutputDeviceInvalidConfigParameters
profile.getFormat(),
static_cast<uint32_t>(profile.getSamplingRates()[0]),
toString(profile.getChannelMasks()[0])};
DeviceAddress defaultDevice = {
toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT), {}};
{
AudioConfig config{.base = validBase};
config.base.channelMask = "random_string";
if (isOffload) {
config.offloadInfo.info(generateOffloadInfo(validBase));
}
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
{
AudioConfig config{.base = validBase};
@@ -176,7 +172,8 @@ const std::vector<DeviceConfigParameter>& getOutputDeviceInvalidConfigParameters
if (isOffload) {
config.offloadInfo.info(generateOffloadInfo(validBase));
}
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
if (generateInvalidFlags) {
AudioConfig config{.base = validBase};
@@ -184,32 +181,37 @@ const std::vector<DeviceConfigParameter>& getOutputDeviceInvalidConfigParameters
config.offloadInfo.info(generateOffloadInfo(validBase));
}
std::vector<AudioInOutFlag> flags = {"random_string", ""};
result.emplace_back(device, mixPort.getName(), config, flags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
flags);
}
if (isOffload) {
{
AudioConfig config{.base = validBase};
config.offloadInfo.info(generateOffloadInfo(validBase));
config.offloadInfo.info().base.channelMask = "random_string";
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
{
AudioConfig config{.base = validBase};
config.offloadInfo.info(generateOffloadInfo(validBase));
config.offloadInfo.info().base.format = "random_string";
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
{
AudioConfig config{.base = validBase};
config.offloadInfo.info(generateOffloadInfo(validBase));
config.offloadInfo.info().streamType = "random_string";
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
{
AudioConfig config{.base = validBase};
config.offloadInfo.info(generateOffloadInfo(validBase));
config.offloadInfo.info().usage = "random_string";
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
hasOffloadConfig = true;
} else {
@@ -233,11 +235,10 @@ std::vector<DeviceConfigParameter> generateInputDeviceConfigParameters(bool oneP
if (!module || !module->getFirstMixPorts()) break;
for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
if (mixPort.getRole() != xsd::Role::sink) continue; // not an input profile
if (getCachedPolicyConfig()
.getAttachedSourceDeviceForMixPort(moduleName, mixPort.getName())
.empty()) {
continue; // no attached device
}
const auto attachedDeviceAddress =
getCachedPolicyConfig().getDeviceAddressOfSourceDeviceAttachedToMixPort(
moduleName, mixPort.getName());
if (!attachedDeviceAddress.has_value()) continue;
std::vector<AudioInOutFlag> flags;
if (mixPort.hasFlags()) {
std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(),
@@ -250,7 +251,8 @@ std::vector<DeviceConfigParameter> generateInputDeviceConfigParameters(bool oneP
auto configs = combineAudioConfig(profile.getChannelMasks(),
profile.getSamplingRates(), profile.getFormat());
for (const auto& config : configs) {
result.emplace_back(device, mixPort.getName(), config, flags);
result.emplace_back(device, mixPort.getName(), attachedDeviceAddress.value(),
config, flags);
if (oneProfilePerDevice) break;
}
if (oneProfilePerDevice) break;
@@ -298,20 +300,25 @@ const std::vector<DeviceConfigParameter>& getInputDeviceInvalidConfigParameters(
profile.getFormat(),
static_cast<uint32_t>(profile.getSamplingRates()[0]),
toString(profile.getChannelMasks()[0])};
DeviceAddress defaultDevice = {
toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT), {}};
{
AudioConfig config{.base = validBase};
config.base.channelMask = "random_string";
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
{
AudioConfig config{.base = validBase};
config.base.format = "random_string";
result.emplace_back(device, mixPort.getName(), config, validFlags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
validFlags);
}
if (generateInvalidFlags) {
AudioConfig config{.base = validBase};
std::vector<AudioInOutFlag> flags = {"random_string", ""};
result.emplace_back(device, mixPort.getName(), config, flags);
result.emplace_back(device, mixPort.getName(), defaultDevice, config,
flags);
}
hasConfig = true;
break;

View File

@@ -61,6 +61,18 @@ class PolicyConfig {
const std::set<std::string>& getModulesWithDevicesNames() const {
return mModulesWithDevicesNames;
}
std::optional<DeviceAddress> getDeviceAddressOfSinkDeviceAttachedToMixPort(
const std::string& moduleName, const std::string& mixPortName) const {
const auto attachedDevicePort = getAttachedSinkDeviceForMixPort(moduleName, mixPortName);
if (attachedDevicePort.empty()) return {};
return getDeviceAddressOfDevicePort(moduleName, attachedDevicePort);
}
std::optional<DeviceAddress> getDeviceAddressOfSourceDeviceAttachedToMixPort(
const std::string& moduleName, const std::string& mixPortName) const {
const auto attachedDevicePort = getAttachedSourceDeviceForMixPort(moduleName, mixPortName);
if (attachedDevicePort.empty()) return {};
return getDeviceAddressOfDevicePort(moduleName, attachedDevicePort);
}
std::string getAttachedSinkDeviceForMixPort(const std::string& moduleName,
const std::string& mixPortName) const {
return findAttachedDevice(getAttachedDevices(moduleName),
@@ -84,8 +96,6 @@ class PolicyConfig {
const std::vector<std::string>& getAttachedDevices(const std::string& moduleName) const;
std::optional<DeviceAddress> getDeviceAddressOfDevicePort(
const std::string& moduleName, const std::string& devicePortName) const;
std::string getDevicePortTagNameFromType(const std::string& moduleName,
const AudioDevice& deviceType) const;
std::set<std::string> getSinkDevicesForMixPort(const std::string& moduleName,
const std::string& mixPortName) const;
std::set<std::string> getSourceDevicesForMixPort(const std::string& moduleName,

View File

@@ -190,6 +190,7 @@ cc_test {
],
data: [
":audio_policy_configuration_V7_0",
"data/sine882hz3s.mp3",
],
// Use test_config for vts suite.
// TODO(b/146104851): Add auto-gen rules and remove it.
@@ -223,6 +224,7 @@ cc_test {
],
data: [
":audio_policy_configuration_V7_1",
"data/sine882hz3s.mp3",
],
// Use test_config for vts suite.
// TODO(b/146104851): Add auto-gen rules and remove it.

View File

@@ -617,7 +617,8 @@ static std::string DeviceConfigParameterToString(
std::get<PARAM_FLAGS>(info.param)));
#elif MAJOR_VERSION >= 7
const auto configPart =
std::to_string(config.base.sampleRateHz) + "_" +
::testing::PrintToString(std::get<PARAM_ATTACHED_DEV_ADDR>(info.param).deviceType) +
"_" + 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)));
@@ -658,6 +659,9 @@ class AudioHidlTestWithDeviceConfigParameter
std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam())));
}
#elif MAJOR_VERSION >= 7
DeviceAddress getAttachedDeviceAddress() const {
return std::get<PARAM_ATTACHED_DEV_ADDR>(GetParam());
}
hidl_vec<AudioInOutFlag> getInputFlags() const { return std::get<PARAM_FLAGS>(GetParam()); }
hidl_vec<AudioInOutFlag> getOutputFlags() const { return std::get<PARAM_FLAGS>(GetParam()); }
#endif
@@ -933,6 +937,14 @@ class StreamWriter : public StreamWorker<StreamWriter> {
StreamWriter(IStreamOut* stream, size_t bufferSize)
: mStream(stream), mBufferSize(bufferSize), mData(mBufferSize) {}
StreamWriter(IStreamOut* stream, size_t bufferSize, std::vector<uint8_t>&& data,
std::function<void()> onDataWrap)
: mStream(stream),
mBufferSize(bufferSize),
mData(std::move(data)),
mOnDataWrap(onDataWrap) {
ALOGW("StreamWriter data size: %d", (int)mData.size());
}
~StreamWriter() {
stop();
if (mEfGroup) {
@@ -998,9 +1010,11 @@ class StreamWriter : public StreamWorker<StreamWriter> {
ALOGE("command message queue write failed");
return false;
}
const size_t dataSize = std::min(mData.size(), mDataMQ->availableToWrite());
bool success = mDataMQ->write(mData.data(), dataSize);
const size_t dataSize = std::min(mData.size() - mDataPosition, mDataMQ->availableToWrite());
bool success = mDataMQ->write(mData.data() + mDataPosition, dataSize);
ALOGE_IF(!success, "data message queue write failed");
mDataPosition += dataSize;
if (mDataPosition >= mData.size()) mDataPosition = 0;
mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
uint32_t efState = 0;
@@ -1026,6 +1040,7 @@ class StreamWriter : public StreamWorker<StreamWriter> {
ALOGE("bad wait status: %d", ret);
success = false;
}
if (success && mDataPosition == 0) mOnDataWrap();
return success;
}
@@ -1033,6 +1048,8 @@ class StreamWriter : public StreamWorker<StreamWriter> {
IStreamOut* const mStream;
const size_t mBufferSize;
std::vector<uint8_t> mData;
std::function<void()> mOnDataWrap = []() {};
size_t mDataPosition = 0;
std::unique_ptr<CommandMQ> mCommandMQ;
std::unique_ptr<DataMQ> mDataMQ;
std::unique_ptr<StatusMQ> mStatusMQ;
@@ -1047,7 +1064,7 @@ class OutputStreamTest
#if MAJOR_VERSION <= 6
address.device = AudioDevice::OUT_DEFAULT;
#elif MAJOR_VERSION >= 7
address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT);
address = getAttachedDeviceAddress();
#endif
const AudioConfig& config = getConfig();
auto flags = getOutputFlags();
@@ -1243,16 +1260,11 @@ class InputStreamTest
#if MAJOR_VERSION <= 6
address.device = AudioDevice::IN_DEFAULT;
#elif MAJOR_VERSION >= 7
auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
getDeviceName(), getMixPortName());
address = getAttachedDeviceAddress();
auto& metadata = initMetadata.tracks[0];
if (maybeSourceAddress.has_value() &&
!xsd::isTelephonyDevice(maybeSourceAddress.value().deviceType)) {
address = maybeSourceAddress.value();
if (!xsd::isTelephonyDevice(address.deviceType)) {
metadata.source = toString(xsd::AudioSource::AUDIO_SOURCE_UNPROCESSED);
metadata.channelMask = getConfig().base.channelMask;
} else {
address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT);
}
#if MAJOR_VERSION == 7 && MINOR_VERSION >= 1
auto flagsIt = std::find(flags.begin(), flags.end(),

View File

@@ -39,9 +39,10 @@ using DeviceConfigParameter = std::tuple<
std::variant<android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioInputFlag,
android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioOutputFlag>>;
#elif MAJOR_VERSION >= 7
enum { PARAM_DEVICE, PARAM_PORT_NAME, PARAM_CONFIG, PARAM_FLAGS };
enum { PARAM_DEVICE, PARAM_PORT_NAME, PARAM_ATTACHED_DEV_ADDR, PARAM_CONFIG, PARAM_FLAGS };
using DeviceConfigParameter =
std::tuple<DeviceParameter, std::string,
android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::DeviceAddress,
android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioConfig,
std::vector<android::hardware::audio::CORE_TYPES_CPP_VERSION::AudioInOutFlag>>;
#endif

View File

@@ -29,6 +29,7 @@
<option name="cleanup" value="true" />
<option name="push" value="VtsHalAudioV7_0TargetTest->/data/local/tmp/VtsHalAudioV7_0TargetTest" />
<option name="push" value="audio_policy_configuration_V7_0.xsd->/data/local/tmp/audio_policy_configuration_V7_0.xsd" />
<option name="push" value="sine882hz3s.mp3->/data/local/tmp/sine882hz3s.mp3" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >

View File

@@ -29,6 +29,8 @@
<option name="cleanup" value="true" />
<option name="push" value="VtsHalAudioV7_1TargetTest->/data/local/tmp/VtsHalAudioV7_1TargetTest" />
<option name="push" value="audio_policy_configuration_V7_1.xsd->/data/local/tmp/audio_policy_configuration_V7_1.xsd" />
<option name="push" value="sine882hz3s.mp3->/data/local/tmp/sine882hz3s.mp3" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >