mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
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:
@@ -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();
|
||||
|
||||
@@ -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 = {},
|
||||
|
||||
Reference in New Issue
Block a user