audio: Fix VTS PCM Input tests for certain h/w platforms am: a620ab760b

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1652995

Change-Id: Ibea87b4aa4a842e9a396a6581ac1409d2f3ecfde
This commit is contained in:
Mikhail Naganov
2021-03-29 20:43:25 +00:00
committed by Automerger Merge Worker
2 changed files with 90 additions and 31 deletions

View File

@@ -580,12 +580,19 @@ class PcmOnlyConfigOutputStreamTest : public OutputStreamTest {
// Starting / resuming of streams is asynchronous at HAL level.
// Sometimes HAL doesn't have enough information until the audio data actually gets
// consumed by the hardware.
do {
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);
} while (res != Result::OK);
}
ASSERT_FALSE(writer.hasError());
ASSERT_FALSE(timedOut);
uint64_t frames = framesInitial;
bool timedOut = false;
for (android::base::Timer elapsed;
frames <= framesInitial && !writer.hasError() &&
!(timedOut = (elapsed.duration() >= kPositionChangeTimeout));) {
@@ -666,11 +673,18 @@ static const std::vector<DeviceConfigParameter>& getInputDevicePcmOnlyConfigPara
allParams.begin(), allParams.end(), std::back_inserter(pcmParams), [](auto cfg) {
const auto& flags = std::get<PARAM_FLAGS>(cfg);
return xsd::isLinearPcm(std::get<PARAM_CONFIG>(cfg).base.format)
// MMAP NOIRQ profiles use different reading protocol.
// MMAP NOIRQ profiles use different reading protocol,
// reading h/w hotword might require Soundtrigger to be active.
&&
std::find(flags.begin(), flags.end(),
toString(xsd::AudioInOutFlag::AUDIO_INPUT_FLAG_MMAP_NOIRQ)) ==
flags.end() &&
std::find_if(
flags.begin(), flags.end(),
[](const auto& flag) {
return flag == toString(
xsd::AudioInOutFlag::
AUDIO_INPUT_FLAG_MMAP_NOIRQ) ||
flag == toString(xsd::AudioInOutFlag::
AUDIO_INPUT_FLAG_HW_HOTWORD);
}) == flags.end() &&
!getCachedPolicyConfig()
.getAttachedSourceDeviceForMixPort(
std::get<PARAM_DEVICE_NAME>(
@@ -690,6 +704,15 @@ 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);
}
void createPatchIfNeeded() {
auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
getDeviceName(), getMixPortName());
@@ -714,6 +737,7 @@ class PcmOnlyConfigInputStreamTest : public InputStreamTest {
EXPECT_OK(stream->setDevices({maybeSourceAddress.value()}));
}
}
void releasePatchIfNeeded() {
if (areAudioPatchesSupported()) {
if (mHasPatch) {
@@ -724,7 +748,42 @@ class PcmOnlyConfigInputStreamTest : public InputStreamTest {
EXPECT_OK(stream->setDevices({address}));
}
}
const std::string& getMixPortName() const { return std::get<PARAM_PORT_NAME>(GetParam()); }
void waitForCapturePositionAdvance(StreamReader& reader, uint64_t* firstPosition = nullptr,
uint64_t* lastPosition = nullptr) {
static constexpr int kReadDurationUs = 50 * 1000;
static constexpr std::chrono::milliseconds kPositionChangeTimeout{10000};
uint64_t framesInitial, ts;
// Starting / resuming of streams is asynchronous at HAL level.
// Sometimes HAL doesn't have enough information until the audio data actually has been
// produced by the hardware. Legacy HALs might return NOT_SUPPORTED when they actually
// mean INVALID_STATE.
bool timedOut = false;
res = Result::INVALID_STATE;
for (android::base::Timer elapsed;
res != Result::OK && !reader.hasError() &&
!(timedOut = (elapsed.duration() >= kPositionChangeTimeout));) {
usleep(kReadDurationUs);
ASSERT_OK(stream->getCapturePosition(returnIn(res, framesInitial, ts)));
ASSERT_RESULT(okOrInvalidStateOrNotSupported, res);
}
ASSERT_FALSE(reader.hasError());
ASSERT_FALSE(timedOut);
uint64_t frames = framesInitial;
for (android::base::Timer elapsed;
frames <= framesInitial && !reader.hasError() &&
!(timedOut = (elapsed.duration() >= kPositionChangeTimeout));) {
usleep(kReadDurationUs);
ASSERT_OK(stream->getCapturePosition(returnIn(res, frames, ts)));
ASSERT_RESULT(Result::OK, res);
}
EXPECT_FALSE(timedOut);
EXPECT_FALSE(reader.hasError());
EXPECT_GT(frames, framesInitial);
if (firstPosition) *firstPosition = framesInitial;
if (lastPosition) *lastPosition = frames;
}
private:
AudioPatchHandle mPatchHandle = {};
@@ -740,47 +799,36 @@ TEST_P(PcmOnlyConfigInputStreamTest, Read) {
TEST_P(PcmOnlyConfigInputStreamTest, CapturePositionAdvancesWithReads) {
doc::test("Check that the capture position advances with reads");
if (!canQueryCapturePosition()) {
GTEST_SKIP() << "Capture position retrieval is not possible";
}
ASSERT_NO_FATAL_FAILURE(createPatchIfNeeded());
StreamReader reader(stream.get(), stream->getBufferSize());
ASSERT_TRUE(reader.start());
EXPECT_TRUE(reader.waitForAtLeastOneCycle());
uint64_t framesInitial, ts;
ASSERT_OK(stream->getCapturePosition(returnIn(res, framesInitial, ts)));
ASSERT_RESULT(Result::OK, res);
EXPECT_TRUE(reader.waitForAtLeastOneCycle());
uint64_t frames;
ASSERT_OK(stream->getCapturePosition(returnIn(res, frames, ts)));
ASSERT_RESULT(Result::OK, res);
EXPECT_GT(frames, framesInitial);
reader.stop();
releasePatchIfNeeded();
ASSERT_NO_FATAL_FAILURE(waitForCapturePositionAdvance(reader));
}
TEST_P(PcmOnlyConfigInputStreamTest, CapturePositionPreservedOnStandby) {
doc::test("Check that the capture position does not reset on standby");
if (!canQueryCapturePosition()) {
GTEST_SKIP() << "Capture position retrieval is not possible";
}
ASSERT_NO_FATAL_FAILURE(createPatchIfNeeded());
StreamReader reader(stream.get(), stream->getBufferSize());
ASSERT_TRUE(reader.start());
EXPECT_TRUE(reader.waitForAtLeastOneCycle());
uint64_t framesInitial, ts;
ASSERT_OK(stream->getCapturePosition(returnIn(res, framesInitial, ts)));
ASSERT_RESULT(Result::OK, res);
uint64_t framesInitial;
ASSERT_NO_FATAL_FAILURE(waitForCapturePositionAdvance(reader, nullptr, &framesInitial));
reader.pause();
ASSERT_OK(stream->standby());
reader.resume();
EXPECT_FALSE(reader.hasError());
uint64_t frames;
ASSERT_OK(stream->getCapturePosition(returnIn(res, frames, ts)));
ASSERT_RESULT(Result::OK, res);
ASSERT_NO_FATAL_FAILURE(waitForCapturePositionAdvance(reader, &frames, nullptr));
EXPECT_GT(frames, framesInitial);
reader.stop();

View File

@@ -1194,7 +1194,17 @@ class InputStreamTest : public OpenStreamTest<IStreamIn> {
#if MAJOR_VERSION <= 6
address.device = AudioDevice::IN_DEFAULT;
#elif MAJOR_VERSION >= 7
address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT);
auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
getDeviceName(), getMixPortName());
if (maybeSourceAddress.has_value() &&
!xsd::isTelephonyDevice(maybeSourceAddress.value().deviceType)) {
address = maybeSourceAddress.value();
auto& metadata = initMetadata.tracks[0];
metadata.source = toString(xsd::AudioSource::AUDIO_SOURCE_UNPROCESSED);
metadata.channelMask = getConfig().base.channelMask;
} else {
address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT);
}
#endif
const AudioConfig& config = getConfig();
auto flags = getInputFlags();
@@ -1212,7 +1222,8 @@ class InputStreamTest : public OpenStreamTest<IStreamIn> {
#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
const SinkMetadata initMetadata = {{ {.source = AudioSource::DEFAULT, .gain = 1 } }};
#elif MAJOR_VERSION >= 7
const SinkMetadata initMetadata = {
const std::string& getMixPortName() const { return std::get<PARAM_PORT_NAME>(GetParam()); }
SinkMetadata initMetadata = {
{{.source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT),
.gain = 1,
.tags = {},