diff --git a/tv/tuner/1.1/IFilter.hal b/tv/tuner/1.1/IFilter.hal index df736aa86b..1c6c33fe2b 100644 --- a/tv/tuner/1.1/IFilter.hal +++ b/tv/tuner/1.1/IFilter.hal @@ -26,6 +26,8 @@ import @1.0::Result; * To access the v1.1 IFilter APIs, the implementation can cast the IFilter * interface returned from the @1.0::IDemux openFilter into a v1.1 IFiler * using V1_1::IFilter::castFrom(V1_0::IFilter). + * + * Note that reconfiguring Filter must happen after the Filter is stopped. */ interface IFilter extends @1.0::IFilter { /** diff --git a/tv/tuner/1.1/IFilterCallback.hal b/tv/tuner/1.1/IFilterCallback.hal index 9960a23775..23ae844354 100644 --- a/tv/tuner/1.1/IFilterCallback.hal +++ b/tv/tuner/1.1/IFilterCallback.hal @@ -25,7 +25,8 @@ interface IFilterCallback extends @1.0::IFilterCallback { * Notify the client that a new filter event happened. * * @param filterEvent a v1_0 filter event. - * @param filterEventExt a v1_1 extended filter event. + * @param filterEventExt a v1_1 extended filter event. Send an empty filterEvent along with + * startId or scramblingStatus filterEventExt */ oneway onFilterEvent_1_1(DemuxFilterEvent filterEvent, DemuxFilterEventExt filterEventExt); }; diff --git a/tv/tuner/1.1/default/Filter.cpp b/tv/tuner/1.1/default/Filter.cpp index 139e98af99..e766a8af72 100644 --- a/tv/tuner/1.1/default/Filter.cpp +++ b/tv/tuner/1.1/default/Filter.cpp @@ -131,6 +131,7 @@ Return Filter::configure(const DemuxFilterSettings& settings) { break; } + mConfigured = true; return Result::SUCCESS; } @@ -145,8 +146,6 @@ Return Filter::stop() { mFilterThreadRunning = false; - std::lock_guard lock(mFilterThreadLock); - return Result::SUCCESS; } @@ -321,8 +320,17 @@ void Filter::filterThreadLoop() { usleep(1000 * 1000); continue; } + // After successfully write, send a callback and wait for the read to be done if (mCallback_1_1 != nullptr) { + if (mConfigured) { + DemuxFilterEvent emptyEvent; + V1_1::DemuxFilterEventExt startEvent; + startEvent.events.resize(1); + startEvent.events[0].startId(mStartId++); + mCallback_1_1->onFilterEvent_1_1(emptyEvent, startEvent); + mConfigured = false; + } mCallback_1_1->onFilterEvent_1_1(mFilterEvent, mFilterEventExt); mFilterEventExt.events.resize(0); } else if (mCallback != nullptr) { diff --git a/tv/tuner/1.1/default/Filter.h b/tv/tuner/1.1/default/Filter.h index a7b3fd26d7..1ebc1351a0 100644 --- a/tv/tuner/1.1/default/Filter.h +++ b/tv/tuner/1.1/default/Filter.h @@ -235,6 +235,9 @@ class Filter : public V1_1::IFilter { // Scrambling status to be monitored uint32_t mStatuses = 0; + + bool mConfigured = false; + int mStartId = 0; }; } // namespace implementation diff --git a/tv/tuner/1.1/types.hal b/tv/tuner/1.1/types.hal index 006e59749a..09b87f2ac8 100644 --- a/tv/tuner/1.1/types.hal +++ b/tv/tuner/1.1/types.hal @@ -161,6 +161,14 @@ struct DemuxFilterEventExt { DemuxFilterMmtpRecordEventExt mmtpRecord; ScramblingStatus scramblingStatus; + + /** + * An unique ID to mark the start point of receiving the valid filter events after + * reconfiguring the filter. It must be sent at least once in the first event after the + * filter is restarted. 0 is reserved for the newly opened filter's first start, which is + * optional for HAL to send. + */ + uint32_t startId; }; /** diff --git a/tv/tuner/1.1/vts/functional/FilterTests.cpp b/tv/tuner/1.1/vts/functional/FilterTests.cpp index d2535e533b..cdf3b6998b 100644 --- a/tv/tuner/1.1/vts/functional/FilterTests.cpp +++ b/tv/tuner/1.1/vts/functional/FilterTests.cpp @@ -40,6 +40,18 @@ void FilterCallback::testFilterScramblingEvent() { ALOGW("[vts] pass and stop"); } +void FilterCallback::testStartIdAfterReconfigure() { + android::Mutex::Autolock autoLock(mMsgLock); + while (!mStartIdReceived) { + if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) { + EXPECT_TRUE(false) << "does not receive start id within timeout"; + return; + } + } + mStartIdReceived = false; + ALOGW("[vts] pass and stop"); +} + void FilterCallback::readFilterEventData() { ALOGW("[vts] reading filter event"); // todo separate filter handlers @@ -71,6 +83,10 @@ void FilterCallback::readFilterEventData() { case DemuxFilterEventExt::Event::hidl_discriminator::scramblingStatus: mScramblingStatusEvent++; break; + case DemuxFilterEventExt::Event::hidl_discriminator::startId: + ALOGD("[vts] Extended restart filter event, startId=%d", eventExt.startId()); + mStartIdReceived = true; + break; default: break; } @@ -90,8 +106,8 @@ bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) { } int av_fd = handle.getNativeHandle()->data[0]; - uint8_t* buffer = - static_cast(mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0)); + uint8_t* buffer = static_cast( + mmap(NULL, length + offset, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0)); if (buffer == MAP_FAILED) { ALOGE("[vts] fail to allocate av buffer, errno=%d", errno); return false; @@ -271,3 +287,9 @@ AssertionResult FilterTests::configureScramblingEvent(uint64_t filterId, uint32_ } return AssertionResult(status == Result::SUCCESS); } + +AssertionResult FilterTests::startIdTest(uint64_t filterId) { + EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first."; + mFilterCallbacks[filterId]->testStartIdAfterReconfigure(); + return AssertionResult(true); +} diff --git a/tv/tuner/1.1/vts/functional/FilterTests.h b/tv/tuner/1.1/vts/functional/FilterTests.h index d88f171e10..ae57659a38 100644 --- a/tv/tuner/1.1/vts/functional/FilterTests.h +++ b/tv/tuner/1.1/vts/functional/FilterTests.h @@ -118,6 +118,7 @@ class FilterCallback : public IFilterCallback { void testFilterDataOutput(); void testFilterScramblingEvent(); + void testStartIdAfterReconfigure(); void readFilterEventData(); bool dumpAvData(DemuxFilterMediaEvent event); @@ -138,6 +139,7 @@ class FilterCallback : public IFilterCallback { int mPidFilterOutputCount = 0; int mScramblingStatusEvent = 0; + bool mStartIdReceived = false; }; class FilterTests { @@ -160,6 +162,7 @@ class FilterTests { AssertionResult startFilter(uint64_t filterId); AssertionResult stopFilter(uint64_t filterId); AssertionResult closeFilter(uint64_t filterId); + AssertionResult startIdTest(uint64_t filterId); FilterEventType getFilterEventType(DemuxFilterType type) { FilterEventType eventType = FilterEventType::UNDEFINED; diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp index 17abf49842..dda8b60087 100644 --- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp +++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp @@ -57,6 +57,39 @@ void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig filterConf, ASSERT_TRUE(mFrontendTests.closeFrontend()); } +void TunerFilterHidlTest::reconfigSingleFilterInDemuxTest(FilterConfig filterConf, + FilterConfig filterReconf, + FrontendConfig frontendConf) { + uint32_t feId; + uint32_t demuxId; + sp demux; + uint64_t filterId; + + mFrontendTests.getFrontendIdByType(frontendConf.type, feId); + ASSERT_TRUE(feId != INVALID_ID); + ASSERT_TRUE(mFrontendTests.openFrontendById(feId)); + ASSERT_TRUE(mFrontendTests.setFrontendCallback()); + ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId)); + ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId)); + mFrontendTests.setDemux(demux); + mFilterTests.setDemux(demux); + ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize)); + ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId)); + ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId)); + ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId)); + ASSERT_TRUE(mFilterTests.startFilter(filterId)); + ASSERT_TRUE(mFilterTests.stopFilter(filterId)); + ASSERT_TRUE(mFilterTests.configFilter(filterReconf.settings, filterId)); + ASSERT_TRUE(mFilterTests.startFilter(filterId)); + ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/)); + ASSERT_TRUE(mFilterTests.startIdTest(filterId)); + ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/)); + ASSERT_TRUE(mFilterTests.stopFilter(filterId)); + ASSERT_TRUE(mFilterTests.closeFilter(filterId)); + ASSERT_TRUE(mDemuxTests.closeDemux()); + ASSERT_TRUE(mFrontendTests.closeFrontend()); +} + void TunerBroadcastHidlTest::mediaFilterUsingSharedMemoryTest(FilterConfig filterConf, FrontendConfig frontendConf) { uint32_t feId; @@ -146,6 +179,13 @@ TEST_P(TunerFilterHidlTest, ConfigIpFilterInDemuxWithCid) { configSingleFilterInDemuxTest(filterArray[IP_IP0], frontendArray[DVBT]); } +TEST_P(TunerFilterHidlTest, ReonfigFilterToReceiveStartId) { + description("Recofigure and restart a filter to test start id."); + // TODO use parameterized tests + reconfigSingleFilterInDemuxTest(filterArray[TS_VIDEO0], filterArray[TS_VIDEO1], + frontendArray[DVBT]); +} + 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]); diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h index 773224e882..d14a2e8779 100644 --- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h +++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h @@ -58,7 +58,8 @@ class TunerFilterHidlTest : public testing::TestWithParam { } void configSingleFilterInDemuxTest(FilterConfig filterConf, FrontendConfig frontendConf); - + void reconfigSingleFilterInDemuxTest(FilterConfig filterConf, FilterConfig filterReconf, + FrontendConfig frontendConf); sp mService; FrontendTests mFrontendTests; DemuxTests mDemuxTests;