Enhance Tuner 1.0 VTS testing and configurations

Broadcom shared a valuable patch to enhance Tuner 1.0 VTS per their
testing experience on the real devices.

We evaluated the suggestions and fix the following issues:
1. Allow testers to set a default frontend
2. Allow testers to enable/disable frontend
3. Skip FMQ creation on filters that do not need FMQ
4. Don't fail if the vendor impl rejects a foreign keytoken
5. Better logs
6. Clean up filter and its callback on close regardless of the closing
result
7. More filter size constants options

Suggestions from: Gareth Fenn <gfenn@broadcom.com>
Test: atest VtsHalTvTunerV1_0TargetTest
Bug: 177960135

Change-Id: Ie4dcc6cb284b2b57879f286c436f5bd9adf43201
This commit is contained in:
Amy Zhang 2021-01-19 19:39:01 -08:00
parent 609874e6ac
commit 37719f3879
5 changed files with 62 additions and 35 deletions

View file

@ -55,6 +55,7 @@ void DvrCallback::playbackThreadLoop() {
uint8_t* buffer;
ALOGW("[vts] playback thread loop start %s", mInputDataFile.c_str());
if (fd < 0) {
EXPECT_TRUE(fd >= 0) << "Failed to open: " + mInputDataFile;
mPlaybackThreadRunning = false;
ALOGW("[vts] Error %s", strerror(errno));
}
@ -178,7 +179,7 @@ void DvrCallback::recordThreadLoop(RecordSettings* /*recordSettings*/, bool* kee
// Our current implementation filter the data and write it into the filter FMQ
// immediately after the DATA_READY from the VTS/framework
if (!readRecordFMQ()) {
ALOGD("[vts] record data failed to be filtered. Ending thread");
ALOGW("[vts] record data failed to be filtered. Ending thread");
mRecordThreadRunning = false;
break;
}

View file

@ -70,6 +70,10 @@ void FilterCallback::filterThreadLoop(DemuxFilterEvent& /* event */) {
}
bool FilterCallback::readFilterEventData() {
if (mFilterMQ == NULL) {
ALOGW("[vts] FMQ is not configured and does not need to be tested.");
return true;
}
bool result = false;
DemuxFilterEvent filterEvent = mFilterEvent;
ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
@ -223,7 +227,11 @@ AssertionResult FilterTests::configFilter(DemuxFilterSettings setting, uint32_t
return AssertionResult(status == Result::SUCCESS);
}
AssertionResult FilterTests::getFilterMQDescriptor(uint32_t filterId) {
AssertionResult FilterTests::getFilterMQDescriptor(uint32_t filterId, bool getMqDesc) {
if (!getMqDesc) {
ALOGE("[vts] Filter does not need FMQ.");
return success();
}
Result status;
EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
@ -284,16 +292,14 @@ AssertionResult FilterTests::clearTimeStamp() {
AssertionResult FilterTests::closeFilter(uint32_t filterId) {
EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
Result status = mFilters[filterId]->close();
if (status == Result::SUCCESS) {
for (int i = 0; i < mUsedFilterIds.size(); i++) {
if (mUsedFilterIds[i] == filterId) {
mUsedFilterIds.erase(mUsedFilterIds.begin() + i);
break;
}
for (int i = 0; i < mUsedFilterIds.size(); i++) {
if (mUsedFilterIds[i] == filterId) {
mUsedFilterIds.erase(mUsedFilterIds.begin() + i);
break;
}
mFilterCallbacks.erase(filterId);
mFilters.erase(filterId);
}
mFilterCallbacks.erase(filterId);
mFilters.erase(filterId);
return AssertionResult(status == Result::SUCCESS);
}

View file

@ -159,7 +159,7 @@ class FilterTests {
AssertionResult getTimeStamp();
AssertionResult getNewlyOpenedFilterId(uint32_t& filterId);
AssertionResult configFilter(DemuxFilterSettings setting, uint32_t filterId);
AssertionResult getFilterMQDescriptor(uint32_t filterId);
AssertionResult getFilterMQDescriptor(uint32_t filterId, bool getMqDesc);
AssertionResult setFilterDataSource(uint32_t sourceFilterId, uint32_t sinkFilterId);
AssertionResult setFilterDataSourceToDemux(uint32_t filterId);
AssertionResult startFilter(uint32_t filterId);

View file

@ -48,7 +48,7 @@ void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig filterConf,
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
@ -75,6 +75,9 @@ void TunerFilterHidlTest::testTimeFilter(TimeFilterConfig filterConf) {
void TunerBroadcastHidlTest::broadcastSingleFilterTest(FilterConfig filterConf,
FrontendConfig frontendConf) {
if (!frontendConf.enable) {
return;
}
uint32_t feId;
uint32_t demuxId;
sp<IDemux> demux;
@ -99,7 +102,7 @@ void TunerBroadcastHidlTest::broadcastSingleFilterTest(FilterConfig filterConf,
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
// tune test
ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
@ -145,7 +148,7 @@ void TunerPlaybackHidlTest::playbackSingleFilterTest(FilterConfig filterConf, Dv
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
mDvrTests.startPlaybackInputThread(dvrConf.playbackInputFile, dvrConf.settings.playback());
ASSERT_TRUE(mDvrTests.startDvrPlayback());
ASSERT_TRUE(mFilterTests.startFilter(filterId));
@ -160,6 +163,9 @@ void TunerPlaybackHidlTest::playbackSingleFilterTest(FilterConfig filterConf, Dv
void TunerRecordHidlTest::recordSingleFilterTest(FilterConfig filterConf,
FrontendConfig frontendConf, DvrConfig dvrConf) {
if (!frontendConf.enable) {
return;
}
uint32_t feId;
uint32_t demuxId;
sp<IDemux> demux;
@ -184,7 +190,7 @@ void TunerRecordHidlTest::recordSingleFilterTest(FilterConfig filterConf,
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
filter = mFilterTests.getFilterById(filterId);
ASSERT_TRUE(filter != nullptr);
mDvrTests.startRecordOutputThread(dvrConf.settings.record());
@ -247,7 +253,7 @@ void TunerRecordHidlTest::attachSingleFilterToRecordDvrTest(FilterConfig filterC
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
filter = mFilterTests.getFilterById(filterId);
ASSERT_TRUE(filter != nullptr);
ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
@ -265,6 +271,9 @@ void TunerRecordHidlTest::attachSingleFilterToRecordDvrTest(FilterConfig filterC
void TunerDescramblerHidlTest::scrambledBroadcastTest(set<struct FilterConfig> mediaFilterConfs,
FrontendConfig frontendConf,
DescramblerConfig descConfig) {
if (!frontendConf.enable) {
return;
}
uint32_t feId;
uint32_t demuxId;
sp<IDemux> demux;
@ -328,17 +337,17 @@ void TunerDescramblerHidlTest::scrambledBroadcastTest(set<struct FilterConfig> m
TEST_P(TunerFrontendHidlTest, TuneFrontend) {
description("Tune one Frontend with specific setting and check Lock event");
mFrontendTests.tuneTest(frontendArray[DVBT]);
mFrontendTests.tuneTest(frontendArray[defaultFrontend]);
}
TEST_P(TunerFrontendHidlTest, AutoScanFrontend) {
description("Run an auto frontend scan with specific setting and check lock scanMessage");
mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_AUTO);
mFrontendTests.scanTest(frontendScanArray[defaultScanFrontend], FrontendScanType::SCAN_AUTO);
}
TEST_P(TunerFrontendHidlTest, BlindScanFrontend) {
description("Run an blind frontend scan with specific setting and check lock scanMessage");
mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_BLIND);
mFrontendTests.scanTest(frontendScanArray[defaultScanFrontend], FrontendScanType::SCAN_BLIND);
}
TEST_P(TunerLnbHidlTest, OpenLnbByName) {
@ -374,7 +383,7 @@ TEST_P(TunerDemuxHidlTest, openDemux) {
uint32_t feId;
uint32_t demuxId;
sp<IDemux> demux;
mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
mFrontendTests.getFrontendIdByType(frontendArray[defaultFrontend].type, feId);
ASSERT_TRUE(feId != INVALID_ID);
ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
@ -394,7 +403,7 @@ TEST_P(TunerDemuxHidlTest, getAvSyncTime) {
uint32_t avSyncHwId;
sp<IFilter> mediaFilter;
mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
mFrontendTests.getFrontendIdByType(frontendArray[defaultFrontend].type, feId);
ASSERT_TRUE(feId != INVALID_ID);
ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
@ -422,7 +431,7 @@ TEST_P(TunerDemuxHidlTest, getAvSyncTime) {
TEST_P(TunerFilterHidlTest, StartFilterInDemux) {
description("Open and start a filter in Demux.");
// TODO use paramterized tests
configSingleFilterInDemuxTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
configSingleFilterInDemuxTest(filterArray[TS_VIDEO0], frontendArray[defaultFrontend]);
}
TEST_P(TunerFilterHidlTest, SetFilterLinkage) {
@ -463,22 +472,22 @@ TEST_P(TunerFilterHidlTest, testTimeFilter) {
TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowVideoFilterTest) {
description("Test Video Filter functionality in Broadcast use case.");
broadcastSingleFilterTest(filterArray[TS_VIDEO1], frontendArray[DVBT]);
broadcastSingleFilterTest(filterArray[TS_VIDEO1], frontendArray[defaultFrontend]);
}
TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowAudioFilterTest) {
description("Test Audio Filter functionality in Broadcast use case.");
broadcastSingleFilterTest(filterArray[TS_AUDIO0], frontendArray[DVBT]);
broadcastSingleFilterTest(filterArray[TS_AUDIO0], frontendArray[defaultFrontend]);
}
TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowSectionFilterTest) {
description("Test Section Filter functionality in Broadcast use case.");
broadcastSingleFilterTest(filterArray[TS_SECTION0], frontendArray[DVBT]);
broadcastSingleFilterTest(filterArray[TS_SECTION0], frontendArray[defaultFrontend]);
}
TEST_P(TunerBroadcastHidlTest, IonBufferTest) {
description("Test the av filter data bufferring.");
broadcastSingleFilterTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
broadcastSingleFilterTest(filterArray[TS_VIDEO0], frontendArray[defaultFrontend]);
}
TEST_P(TunerBroadcastHidlTest, LnbBroadcastDataFlowVideoFilterTest) {
@ -493,11 +502,11 @@ TEST_P(TunerBroadcastHidlTest, BroadcastEsDataFlowMediaFiltersTest) {
sp<IDemux> demux;
uint32_t filterId;
mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
mFrontendTests.getFrontendIdByType(frontendArray[defaultFrontend].type, feId);
if (feId == INVALID_ID) {
// TODO broadcast test on Cuttlefish needs licensed ts input,
// these tests are runnable on vendor device with real frontend module
// or with manual ts installing and use DVBT frontend.
// or with manual ts installing and use defaultFrontend frontend.
return;
}
ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
@ -510,13 +519,13 @@ TEST_P(TunerBroadcastHidlTest, BroadcastEsDataFlowMediaFiltersTest) {
filterArray[TS_AUDIO1].bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_AUDIO1].settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterArray[TS_AUDIO1].getMqDesc));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_VIDEO1].type,
filterArray[TS_VIDEO1].bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_VIDEO1].settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterArray[TS_VIDEO1].getMqDesc));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
// tune test
PlaybackSettings playbackSettings{
@ -533,7 +542,8 @@ TEST_P(TunerBroadcastHidlTest, BroadcastEsDataFlowMediaFiltersTest) {
};
dvrConfig.settings.playback(playbackSettings);
mFrontendTests.setSoftwareFrontendDvrConfig(dvrConfig);
ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendArray[DVBT], true /*testWithDemux*/));
ASSERT_TRUE(
mFrontendTests.tuneFrontend(frontendArray[defaultFrontend], true /*testWithDemux*/));
ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
@ -550,13 +560,14 @@ TEST_P(TunerPlaybackHidlTest, PlaybackDataFlowWithTsSectionFilterTest) {
TEST_P(TunerRecordHidlTest, AttachFiltersToRecordTest) {
description("Attach a single filter to the record dvr test.");
// TODO use paramterized tests
attachSingleFilterToRecordDvrTest(filterArray[TS_RECORD0], frontendArray[DVBT],
attachSingleFilterToRecordDvrTest(filterArray[TS_RECORD0], frontendArray[defaultFrontend],
dvrArray[DVR_RECORD0]);
}
TEST_P(TunerRecordHidlTest, RecordDataFlowWithTsRecordFilterTest) {
description("Feed ts data from frontend to recording and test with ts record filter");
recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[DVBT], dvrArray[DVR_RECORD0]);
recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[defaultFrontend],
dvrArray[DVR_RECORD0]);
}
TEST_P(TunerRecordHidlTest, LnbRecordDataFlowWithTsRecordFilterTest) {
@ -569,7 +580,7 @@ TEST_P(TunerDescramblerHidlTest, CreateDescrambler) {
uint32_t feId;
uint32_t demuxId;
sp<IDemux> demux;
mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
mFrontendTests.getFrontendIdByType(frontendArray[defaultFrontend].type, feId);
ASSERT_TRUE(feId != INVALID_ID);
ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
@ -586,7 +597,7 @@ TEST_P(TunerDescramblerHidlTest, ScrambledBroadcastDataFlowMediaFiltersTest) {
set<FilterConfig> filterConfs;
filterConfs.insert(filterArray[TS_AUDIO0]);
filterConfs.insert(filterArray[TS_VIDEO1]);
scrambledBroadcastTest(filterConfs, frontendArray[DVBT], descramblerArray[DESC_0]);
scrambledBroadcastTest(filterConfs, frontendArray[defaultFrontend], descramblerArray[DESC_0]);
}
INSTANTIATE_TEST_SUITE_P(

View file

@ -55,6 +55,7 @@ using android::hardware::tv::tuner::V1_0::RecordSettings;
using namespace std;
const uint32_t FMQ_SIZE_512K = 0x80000;
const uint32_t FMQ_SIZE_1M = 0x100000;
const uint32_t FMQ_SIZE_4M = 0x400000;
const uint32_t FMQ_SIZE_16M = 0x1000000;
@ -134,6 +135,7 @@ struct FilterConfig {
uint32_t bufferSize;
DemuxFilterType type;
DemuxFilterSettings settings;
bool getMqDesc;
bool operator<(const FilterConfig& /*c*/) const { return false; }
};
@ -144,6 +146,7 @@ struct TimeFilterConfig {
};
struct FrontendConfig {
bool enable;
bool isSoftwareFe;
FrontendType type;
FrontendSettings settings;
@ -191,6 +194,8 @@ static DemuxFilterType filterLinkageTypes[LINKAGE_DIR][FILTER_MAIN_TYPE_BIT_COUN
static DvrConfig dvrArray[DVR_MAX];
static DescramblerConfig descramblerArray[DESC_MAX];
static vector<string> goldenOutputFiles;
static int defaultFrontend = DVBT;
static int defaultScanFrontend = SCAN_DVBT;
/** Configuration array for the frontend tune test */
inline void initFrontendConfig() {
@ -216,7 +221,9 @@ inline void initFrontendConfig() {
frontendArray[DVBT].tuneStatusTypes = types;
frontendArray[DVBT].expectTuneStatuses = statuses;
frontendArray[DVBT].isSoftwareFe = true;
frontendArray[DVBS].enable = true;
frontendArray[DVBS].type = FrontendType::DVBS;
frontendArray[DVBS].enable = true;
frontendArray[DVBS].isSoftwareFe = true;
};
@ -288,6 +295,7 @@ inline void initFilterConfig() {
.isRaw = false,
.streamId = 0xbd,
});
filterArray[TS_PES0].getMqDesc = true;
// TS PCR filter setting
filterArray[TS_PCR0].type.mainType = DemuxFilterMainType::TS;
filterArray[TS_PCR0].type.subType.tsFilterType(DemuxTsFilterType::PCR);
@ -308,6 +316,7 @@ inline void initFilterConfig() {
filterArray[TS_SECTION0].settings.ts().filterSettings.section({
.isRaw = false,
});
filterArray[TS_SECTION0].getMqDesc = true;
// TS RECORD filter setting
filterArray[TS_RECORD0].type.mainType = DemuxFilterMainType::TS;
filterArray[TS_RECORD0].type.subType.tsFilterType(DemuxTsFilterType::RECORD);