Add startId in Filter Event to work with filter reconfiguration
Test: atest VtsHalTvTunerV1_1TargetTest
Bug: 172593389
Change-Id: I77e45366b737068aa0aa20c2b384f2e3160c7398
diff --git a/tv/tuner/1.1/IFilter.hal b/tv/tuner/1.1/IFilter.hal
index df736aa..1c6c33f 100644
--- a/tv/tuner/1.1/IFilter.hal
+++ b/tv/tuner/1.1/IFilter.hal
@@ -26,6 +26,8 @@
* 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 9960a23..23ae844 100644
--- a/tv/tuner/1.1/IFilterCallback.hal
+++ b/tv/tuner/1.1/IFilterCallback.hal
@@ -25,7 +25,8 @@
* 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 139e98a..e766a8a 100644
--- a/tv/tuner/1.1/default/Filter.cpp
+++ b/tv/tuner/1.1/default/Filter.cpp
@@ -131,6 +131,7 @@
break;
}
+ mConfigured = true;
return Result::SUCCESS;
}
@@ -145,8 +146,6 @@
mFilterThreadRunning = false;
- std::lock_guard<std::mutex> lock(mFilterThreadLock);
-
return Result::SUCCESS;
}
@@ -321,8 +320,17 @@
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 a7b3fd2..1ebc135 100644
--- a/tv/tuner/1.1/default/Filter.h
+++ b/tv/tuner/1.1/default/Filter.h
@@ -235,6 +235,9 @@
// 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 006e597..09b87f2 100644
--- a/tv/tuner/1.1/types.hal
+++ b/tv/tuner/1.1/types.hal
@@ -161,6 +161,14 @@
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 d2535e5..cdf3b69 100644
--- a/tv/tuner/1.1/vts/functional/FilterTests.cpp
+++ b/tv/tuner/1.1/vts/functional/FilterTests.cpp
@@ -40,6 +40,18 @@
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 @@
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 @@
}
int av_fd = handle.getNativeHandle()->data[0];
- uint8_t* buffer =
- static_cast<uint8_t*>(mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0));
+ uint8_t* buffer = static_cast<uint8_t*>(
+ 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 @@
}
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 d88f171..ae57659 100644
--- a/tv/tuner/1.1/vts/functional/FilterTests.h
+++ b/tv/tuner/1.1/vts/functional/FilterTests.h
@@ -118,6 +118,7 @@
void testFilterDataOutput();
void testFilterScramblingEvent();
+ void testStartIdAfterReconfigure();
void readFilterEventData();
bool dumpAvData(DemuxFilterMediaEvent event);
@@ -138,6 +139,7 @@
int mPidFilterOutputCount = 0;
int mScramblingStatusEvent = 0;
+ bool mStartIdReceived = false;
};
class FilterTests {
@@ -160,6 +162,7 @@
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 17abf49..dda8b60 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 @@
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
+void TunerFilterHidlTest::reconfigSingleFilterInDemuxTest(FilterConfig filterConf,
+ FilterConfig filterReconf,
+ FrontendConfig frontendConf) {
+ uint32_t feId;
+ uint32_t demuxId;
+ sp<IDemux> 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 @@
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 773224e..d14a2e8 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 @@
}
void configSingleFilterInDemuxTest(FilterConfig filterConf, FrontendConfig frontendConf);
-
+ void reconfigSingleFilterInDemuxTest(FilterConfig filterConf, FilterConfig filterReconf,
+ FrontendConfig frontendConf);
sp<ITuner> mService;
FrontendTests mFrontendTests;
DemuxTests mDemuxTests;