diff options
author | Amy <amyjojo@google.com> | 2019-09-06 10:30:53 -0700 |
---|---|---|
committer | Amy <amyjojo@google.com> | 2019-09-18 15:34:54 -0700 |
commit | 9db58dfa486b47e5b4974d28da31d74b75f73b11 (patch) | |
tree | 93d722deb453e3ca2b06cee310815f26ec916425 | |
parent | a4885299c2001001338ec535061b73e741c0e813 (diff) |
Tuner HAL Demux Playback interface VTS
Test: manual
Bug: 135708935
Change-Id: Ifb93bbd5920f7998d9716a55cba983f8a5ace425
-rw-r--r-- | tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp | 492 |
1 files changed, 329 insertions, 163 deletions
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp index 66adb2a698..d272d710f3 100644 --- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp +++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp @@ -34,6 +34,8 @@ #include <hidlmemory/FrameworkUtils.h> #include <utils/Condition.h> #include <utils/Mutex.h> +#include <fstream> +#include <iostream> #define WAIT_TIMEOUT 3000000000 @@ -53,11 +55,16 @@ using android::hardware::MessageQueue; using android::hardware::MQDescriptorSync; using android::hardware::Return; using android::hardware::Void; +using android::hardware::tv::tuner::V1_0::DemuxDataFormat; using android::hardware::tv::tuner::V1_0::DemuxFilterEvent; using android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent; using android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent; +using android::hardware::tv::tuner::V1_0::DemuxFilterSettings; using android::hardware::tv::tuner::V1_0::DemuxFilterStatus; using android::hardware::tv::tuner::V1_0::DemuxFilterType; +using android::hardware::tv::tuner::V1_0::DemuxInputSettings; +using android::hardware::tv::tuner::V1_0::DemuxInputStatus; +using android::hardware::tv::tuner::V1_0::DemuxOutputStatus; using android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits; using android::hardware::tv::tuner::V1_0::FrontendAtscModulation; using android::hardware::tv::tuner::V1_0::FrontendAtscSettings; @@ -77,9 +84,9 @@ using android::hardware::tv::tuner::V1_0::Result; namespace { using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>; -using FilterMQDesc = MQDescriptorSync<uint8_t>; +using MQDesc = MQDescriptorSync<uint8_t>; -const std::vector<uint8_t> goldenDataInputBuffer{ +const std::vector<uint8_t> goldenDataOutputBuffer{ 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb, 0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03, 0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06, @@ -119,10 +126,21 @@ const std::vector<uint8_t> goldenDataInputBuffer{ }; const uint16_t FMQ_SIZE_4K = 0x1000; +const uint32_t FMQ_SIZE_1M = 0x100000; // Equal to SECTION_WRITE_COUNT on the HAL impl side // The HAL impl will repeatedly write to the FMQ the count times const uint16_t SECTION_READ_COUNT = 10; +struct FilterConf { + DemuxFilterType type; + DemuxFilterSettings setting; +}; + +struct InputConf { + string inputDataFile; + DemuxInputSettings setting; +}; + class FrontendCallback : public IFrontendCallback { public: virtual Return<void> onEvent(FrontendEventType frontendEventType) override { @@ -184,8 +202,10 @@ void FrontendCallback::testOnDiseqcMessage(sp<IFrontend>& frontend, FrontendSett class DemuxCallback : public IDemuxCallback { public: virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent) override { + ALOGW("[VTS] FILTER EVENT %d", filterEvent.filterId); android::Mutex::Autolock autoLock(mMsgLock); mFilterEventReceived = true; + // maybe assemble here?? mFilterEvent = filterEvent; mMsgCondition.signal(); return Void(); @@ -196,24 +216,53 @@ class DemuxCallback : public IDemuxCallback { return Void(); } + virtual Return<void> onOutputStatus(DemuxOutputStatus /*status*/) override { return Void(); } + + virtual Return<void> onInputStatus(DemuxInputStatus status) override { + // android::Mutex::Autolock autoLock(mMsgLock); + switch (status) { + case DemuxInputStatus::SPACE_EMPTY: + case DemuxInputStatus::SPACE_ALMOST_EMPTY: + mKeepWritingInputFMQ = true; + break; + case DemuxInputStatus::SPACE_ALMOST_FULL: + case DemuxInputStatus::SPACE_FULL: + mKeepWritingInputFMQ = false; + break; + } + return Void(); + } + void testOnFilterEvent(uint32_t filterId); - void testOnSectionFilterEvent(sp<IDemux>& demux, uint32_t filterId, - FilterMQDesc& filterMQDescriptor); - void testOnPesFilterEvent(sp<IDemux>& demux, uint32_t filterId, - FilterMQDesc& filterMQDescriptor); - void readAndCompareSectionEventData(); - void readAndComparePesEventData(); + void testOnSectionFilterEvent(sp<IDemux>& demux, uint32_t filterId, MQDesc& filterMQDescriptor, + MQDesc& inputMQDescriptor); + void startPlaybackInputThread(InputConf inputConf, MQDesc& inputMQDescriptor); + bool readAndCompareSectionEventData(); + + static void* __threadLoopInput(void* threadArgs); + void inputThreadLoop(InputConf inputConf, bool* keepWritingInputFMQ, MQDesc& inputMQDescriptor); private: + struct InputThreadArgs { + DemuxCallback* user; + InputConf inputConf; + bool* keepWritingInputFMQ; + MQDesc& inputMQDesc; + }; bool mFilterEventReceived = false; std::vector<uint8_t> mDataOutputBuffer; std::unique_ptr<FilterMQ> mFilterMQ; + std::unique_ptr<FilterMQ> mInputMQ; uint16_t mDataLength = 0; DemuxFilterEvent mFilterEvent; android::Mutex mMsgLock; android::Mutex mReadLock; android::Condition mMsgCondition; EventFlag* mFilterMQEventFlag; + EventFlag* mInputMQEventFlag; + bool mKeepWritingInputFMQ; + bool mInputThreadRunning; + pthread_t mInputThread; }; void DemuxCallback::testOnFilterEvent(uint32_t filterId) { @@ -230,83 +279,138 @@ void DemuxCallback::testOnFilterEvent(uint32_t filterId) { EXPECT_TRUE(filterId == mFilterEvent.filterId) << "filter id match"; } +void DemuxCallback::startPlaybackInputThread(InputConf inputConf, MQDesc& inputMQDescriptor) { + struct InputThreadArgs* threadArgs = + (struct InputThreadArgs*)malloc(sizeof(struct InputThreadArgs)); + threadArgs->user = this; + threadArgs->inputConf = inputConf; + threadArgs->keepWritingInputFMQ = &mKeepWritingInputFMQ; + threadArgs->inputMQDesc = inputMQDescriptor; + + pthread_create(&mInputThread, NULL, __threadLoopInput, (void*)threadArgs); + pthread_setname_np(mInputThread, "test_playback_input_loop"); +} + +/*void DemuxCallback::testPlaybackDataFlow(bool* keepWritingInputFMQ) { + // timeout logic here + + // assemble logic here + + +}*/ + void DemuxCallback::testOnSectionFilterEvent(sp<IDemux>& demux, uint32_t filterId, - FilterMQDesc& filterMQDescriptor) { + MQDesc& filterMQDescriptor, + MQDesc& inputMQDescriptor) { Result status; // Create MQ to read the output into the local buffer mFilterMQ = std::make_unique<FilterMQ>(filterMQDescriptor, true /* resetPointers */); EXPECT_TRUE(mFilterMQ); + // Get the MQ to write the input to the HAL + mInputMQ = std::make_unique<FilterMQ>(inputMQDescriptor, true /* resetPointers */); + EXPECT_TRUE(mInputMQ); // Create the EventFlag that is used to signal the HAL impl that data have been // read the Filter FMQ EXPECT_TRUE(EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterMQEventFlag) == android::OK); + // Create the EventFlag that is used to signal the HAL impl that data have been + // written into the Input FMQ + EXPECT_TRUE(EventFlag::createEventFlag(mInputMQ->getEventFlagWord(), &mInputMQEventFlag) == + android::OK); // Start filter status = demux->startFilter(filterId); + status = demux->startInput(); + EXPECT_EQ(status, Result::SUCCESS); // Test start filter and receive callback event for (int i = 0; i < SECTION_READ_COUNT; i++) { + // Write input FMQ and notify the Tuner Implementation + EXPECT_TRUE(mInputMQ->write(goldenDataOutputBuffer.data(), goldenDataOutputBuffer.size())); + mInputMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY)); testOnFilterEvent(filterId); // checksum of mDataOutputBuffer and Input golden input - readAndCompareSectionEventData(); + if (readAndCompareSectionEventData() && i < SECTION_READ_COUNT - 1) { + mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED)); + } } } -void DemuxCallback::testOnPesFilterEvent(sp<IDemux>& demux, uint32_t filterId, - FilterMQDesc& filterMQDescriptor) { - Result status; - // Create MQ to read the output into the local buffer - mFilterMQ = std::make_unique<FilterMQ>(filterMQDescriptor, true /* resetPointers */); - EXPECT_TRUE(mFilterMQ); - // Create the EventFlag that is used to signal the HAL impl that data have been - // read the Filter FMQ - EXPECT_TRUE(EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterMQEventFlag) == - android::OK); - // Start filter - status = demux->startFilter(filterId); - EXPECT_EQ(status, Result::SUCCESS); - // Test start filter and receive callback event - testOnFilterEvent(filterId); - // checksum of mDataOutputBuffer and Input golden input - readAndComparePesEventData(); -} - -void DemuxCallback::readAndCompareSectionEventData() { +bool DemuxCallback::readAndCompareSectionEventData() { bool result = false; for (int i = 0; i < mFilterEvent.events.size(); i++) { DemuxFilterSectionEvent event = mFilterEvent.events[i].section(); mDataLength = event.dataLength; - EXPECT_TRUE(mDataLength == goldenDataInputBuffer.size()) << "buffer size does not match"; + EXPECT_TRUE(mDataLength == goldenDataOutputBuffer.size()) << "buffer size does not match"; mDataOutputBuffer.resize(mDataLength); result = mFilterMQ->read(mDataOutputBuffer.data(), mDataLength); EXPECT_TRUE(result) << "can't read from Filter MQ"; for (int i = 0; i < mDataLength; i++) { - EXPECT_TRUE(goldenDataInputBuffer[i] == mDataOutputBuffer[i]) << "data does not match"; + EXPECT_TRUE(goldenDataOutputBuffer[i] == mDataOutputBuffer[i]) << "data does not match"; } } - if (result) { - mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED)); - } + return result; } -void DemuxCallback::readAndComparePesEventData() { - // TODO handle multiple events in one filter callback event - DemuxFilterPesEvent event = mFilterEvent.events[0].pes(); - mDataLength = event.dataLength; - EXPECT_TRUE(mDataLength == goldenDataInputBuffer.size()) << "buffer size does not match"; +void* DemuxCallback::__threadLoopInput(void* threadArgs) { + DemuxCallback* const self = + static_cast<DemuxCallback*>(((struct InputThreadArgs*)threadArgs)->user); + self->inputThreadLoop(((struct InputThreadArgs*)threadArgs)->inputConf, + ((struct InputThreadArgs*)threadArgs)->keepWritingInputFMQ, + ((struct InputThreadArgs*)threadArgs)->inputMQDesc); + return 0; +} - mDataOutputBuffer.resize(mDataLength); - bool result = mFilterMQ->read(mDataOutputBuffer.data(), mDataLength); - EXPECT_TRUE(result) << "can't read from Filter MQ"; +void DemuxCallback::inputThreadLoop(InputConf inputConf, bool* keepWritingInputFMQ, + MQDesc& inputMQDescriptor) { + mInputThreadRunning = true; - if (result) { - mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED)); - } + std::unique_ptr inputMQ = + std::make_unique<FilterMQ>(inputMQDescriptor, true /* resetPointers */); + EXPECT_TRUE(inputMQ); - for (int i = 0; i < mDataLength; i++) { - EXPECT_TRUE(goldenDataInputBuffer[i] == mDataOutputBuffer[i]) << "data does not match"; + // Create the EventFlag that is used to signal the HAL impl that data have been + // written into the Input FMQ + EventFlag* inputMQEventFlag; + EXPECT_TRUE(EventFlag::createEventFlag(inputMQ->getEventFlagWord(), &inputMQEventFlag) == + android::OK); + + // open the stream and get its length + std::ifstream inputData(inputConf.inputDataFile /*"ts/test1.ts"*/, std::ifstream::binary); + int writeSize = inputConf.setting.packetSize * 6; + char* buffer = new char[writeSize]; + if (!inputData) { + // log + mInputThreadRunning = false; + } + + while (mInputThreadRunning) { + // move the stream pointer for packet size * 2k? every read until end + while (*keepWritingInputFMQ) { + inputData.read(buffer, writeSize); + if (!inputData) { + int leftSize = inputData.gcount(); + inputData.clear(); + inputData.read(buffer, leftSize); + // Write the left over of the input data and quit the thread + if (leftSize > 0) { + EXPECT_TRUE(inputMQ->write((unsigned char*)&buffer[0], + leftSize / inputConf.setting.packetSize)); + inputMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY)); + } + mInputThreadRunning = false; + break; + } + // Write input FMQ and notify the Tuner Implementation + EXPECT_TRUE(inputMQ->write((unsigned char*)&buffer[0], 6)); + inputMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY)); + inputData.seekg(writeSize, inputData.cur); + } } + + delete[] buffer; + inputData.close(); } // Test environment for Tuner HIDL HAL. @@ -341,24 +445,33 @@ class TunerHidlTest : public ::testing::VtsHalHidlTargetTestBase { sp<IDescrambler> mDescrambler; sp<IDemux> mDemux; sp<DemuxCallback> mDemuxCallback; - FilterMQDesc mFilterMQDescriptor; + MQDesc mFilterMQDescriptor; + MQDesc mInputMQDescriptor; + uint32_t mDemuxId; uint32_t mFilterId; + pthread_t mInputThread; + bool mInputThreadRunning; + ::testing::AssertionResult createFrontend(int32_t frontendId); ::testing::AssertionResult tuneFrontend(int32_t frontendId); ::testing::AssertionResult stopTuneFrontend(int32_t frontendId); ::testing::AssertionResult closeFrontend(int32_t frontendId); ::testing::AssertionResult createDemux(); ::testing::AssertionResult createDemuxWithFrontend(int32_t frontendId); + ::testing::AssertionResult getInputMQDescriptor(); + ::testing::AssertionResult addInputToDemux(DemuxInputSettings setting); ::testing::AssertionResult addSectionFilterToDemux(); - ::testing::AssertionResult addPesFilterToDemux(); - ::testing::AssertionResult getFilterMQDescriptor(sp<IDemux>& demux, const uint32_t filterId); - ::testing::AssertionResult readSectionFilterDataOutput(); - ::testing::AssertionResult readPesFilterDataOutput(); + ::testing::AssertionResult addFilterToDemux(DemuxFilterType type, DemuxFilterSettings setting); + ::testing::AssertionResult getFilterMQDescriptor(const uint32_t filterId); ::testing::AssertionResult closeDemux(); ::testing::AssertionResult createDescrambler(); ::testing::AssertionResult closeDescrambler(); + + ::testing::AssertionResult readSectionFilterDataOutput(); + ::testing::AssertionResult playbackDataFlowTest(vector<FilterConf> filterConf, + InputConf inputConf, string goldenOutput); }; ::testing::AssertionResult TunerHidlTest::createFrontend(int32_t frontendId) { @@ -405,7 +518,7 @@ class TunerHidlTest : public ::testing::VtsHalHidlTargetTestBase { ::testing::AssertionResult TunerHidlTest::stopTuneFrontend(int32_t frontendId) { Result status; - if (createFrontend(frontendId) == ::testing::AssertionFailure()) { + if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) { return ::testing::AssertionFailure(); } @@ -415,11 +528,12 @@ class TunerHidlTest : public ::testing::VtsHalHidlTargetTestBase { ::testing::AssertionResult TunerHidlTest::closeFrontend(int32_t frontendId) { Result status; - if (createFrontend(frontendId) == ::testing::AssertionFailure()) { + if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) { return ::testing::AssertionFailure(); } status = mFrontend->close(); + mFrontend = nullptr; return ::testing::AssertionResult(status == Result::SUCCESS); } @@ -437,11 +551,11 @@ class TunerHidlTest : public ::testing::VtsHalHidlTargetTestBase { ::testing::AssertionResult TunerHidlTest::createDemuxWithFrontend(int32_t frontendId) { Result status; - if (createDemux() == ::testing::AssertionFailure()) { + if (!mDemux && createDemux() == ::testing::AssertionFailure()) { return ::testing::AssertionFailure(); } - if (createFrontend(frontendId) == ::testing::AssertionFailure()) { + if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) { return ::testing::AssertionFailure(); } @@ -450,149 +564,223 @@ class TunerHidlTest : public ::testing::VtsHalHidlTargetTestBase { return ::testing::AssertionResult(status == Result::SUCCESS); } -::testing::AssertionResult TunerHidlTest::addSectionFilterToDemux() { +::testing::AssertionResult TunerHidlTest::closeDemux() { Result status; + if (!mDemux && createDemux() == ::testing::AssertionFailure()) { + return ::testing::AssertionFailure(); + } - if (createDemux() == ::testing::AssertionFailure()) { + status = mDemux->close(); + mDemux = nullptr; + return ::testing::AssertionResult(status == Result::SUCCESS); +} + +::testing::AssertionResult TunerHidlTest::createDescrambler() { + Result status; + + mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) { + mDescrambler = descrambler; + status = result; + }); + if (status != Result::SUCCESS) { return ::testing::AssertionFailure(); } - // Create demux callback - mDemuxCallback = new DemuxCallback(); + if (!mDemux && createDemux() == ::testing::AssertionFailure()) { + return ::testing::AssertionFailure(); + } - // Add section filter to the local demux - mDemux->addFilter(DemuxFilterType::SECTION, FMQ_SIZE_4K, mDemuxCallback, - [&](Result result, uint32_t filterId) { - mFilterId = filterId; - status = result; - }); + status = mDescrambler->setDemuxSource(mDemuxId); + if (status != Result::SUCCESS) { + return ::testing::AssertionFailure(); + } - // Add another section filter to the local demux - mDemux->addFilter(DemuxFilterType::SECTION, FMQ_SIZE_4K, mDemuxCallback, - [&](Result result, uint32_t filterId) { - mFilterId = filterId; - status = result; - }); + // Test if demux source can be set more than once. + status = mDescrambler->setDemuxSource(mDemuxId); + return ::testing::AssertionResult(status == Result::INVALID_STATE); +} - // TODO Test configure the filter +::testing::AssertionResult TunerHidlTest::closeDescrambler() { + Result status; + if (!mDescrambler && createDescrambler() == ::testing::AssertionFailure()) { + return ::testing::AssertionFailure(); + } + status = mDescrambler->close(); + mDescrambler = nullptr; return ::testing::AssertionResult(status == Result::SUCCESS); } -::testing::AssertionResult TunerHidlTest::addPesFilterToDemux() { +::testing::AssertionResult TunerHidlTest::addInputToDemux(DemuxInputSettings setting) { Result status; - if (createDemux() == ::testing::AssertionFailure()) { + if (!mDemux && createDemux() == ::testing::AssertionFailure()) { return ::testing::AssertionFailure(); } // Create demux callback - mDemuxCallback = new DemuxCallback(); + if (!mDemuxCallback) { + mDemuxCallback = new DemuxCallback(); + } - // Add PES filter to the local demux - mDemux->addFilter(DemuxFilterType::PES, FMQ_SIZE_4K, mDemuxCallback, - [&](Result result, uint32_t filterId) { - mFilterId = filterId; - status = result; - }); + // Add section filter to the local demux + status = mDemux->addInput(FMQ_SIZE_1M, mDemuxCallback); - // Add another PES filter to the local demux - mDemux->addFilter(DemuxFilterType::PES, FMQ_SIZE_4K, mDemuxCallback, - [&](Result result, uint32_t filterId) { - mFilterId = filterId; - status = result; - }); + if (status != Result::SUCCESS) { + return ::testing::AssertionFailure(); + } - // TODO Test configure the filter + status = mDemux->configureInput(setting); return ::testing::AssertionResult(status == Result::SUCCESS); } -::testing::AssertionResult TunerHidlTest::getFilterMQDescriptor(sp<IDemux>& demux, - const uint32_t filterId) { +::testing::AssertionResult TunerHidlTest::getInputMQDescriptor() { Result status; - if (!demux) { + if (!mDemux && createDemux() == ::testing::AssertionFailure()) { return ::testing::AssertionFailure(); } - mDemux->getFilterQueueDesc(filterId, [&](Result result, const FilterMQDesc& filterMQDesc) { - mFilterMQDescriptor = filterMQDesc; + mDemux->getInputQueueDesc([&](Result result, const MQDesc& inputMQDesc) { + mInputMQDescriptor = inputMQDesc; status = result; }); return ::testing::AssertionResult(status == Result::SUCCESS); } -::testing::AssertionResult TunerHidlTest::readSectionFilterDataOutput() { - if (addSectionFilterToDemux() == ::testing::AssertionFailure() || - getFilterMQDescriptor(mDemux, mFilterId) == ::testing::AssertionFailure()) { +::testing::AssertionResult TunerHidlTest::addSectionFilterToDemux() { + Result status; + + if (!mDemux && createDemux() == ::testing::AssertionFailure()) { return ::testing::AssertionFailure(); } - // Test start filter and read the output data - mDemuxCallback->testOnSectionFilterEvent(mDemux, mFilterId, mFilterMQDescriptor); + // Create demux callback + if (!mDemuxCallback) { + mDemuxCallback = new DemuxCallback(); + } - return ::testing::AssertionResult(true); + // Add section filter to the local demux + mDemux->addFilter(DemuxFilterType::SECTION, FMQ_SIZE_4K, mDemuxCallback, + [&](Result result, uint32_t filterId) { + mFilterId = filterId; + status = result; + }); + + return ::testing::AssertionResult(status == Result::SUCCESS); } -::testing::AssertionResult TunerHidlTest::readPesFilterDataOutput() { - if (addPesFilterToDemux() == ::testing::AssertionFailure() || - getFilterMQDescriptor(mDemux, mFilterId) == ::testing::AssertionFailure()) { +::testing::AssertionResult TunerHidlTest::addFilterToDemux(DemuxFilterType type, + DemuxFilterSettings setting) { + Result status; + + if (!mDemux && createDemux() == ::testing::AssertionFailure()) { return ::testing::AssertionFailure(); } - // Test start filter and read the output data - mDemuxCallback->testOnPesFilterEvent(mDemux, mFilterId, mFilterMQDescriptor); + // Create demux callback + if (!mDemuxCallback) { + mDemuxCallback = new DemuxCallback(); + } - return ::testing::AssertionResult(true); -} + // Add filter to the local demux + mDemux->addFilter(type, FMQ_SIZE_4K, mDemuxCallback, [&](Result result, uint32_t filterId) { + // TODO use a map to save all the filter id and FMQ + mFilterId = filterId; + status = result; + }); -::testing::AssertionResult TunerHidlTest::closeDemux() { - Result status; - if (createDemux() == ::testing::AssertionFailure()) { + if (status != Result::SUCCESS) { return ::testing::AssertionFailure(); } - status = mDemux->close(); + // Configure the filter + status = mDemux->configureFilter(mFilterId, setting); + return ::testing::AssertionResult(status == Result::SUCCESS); } -::testing::AssertionResult TunerHidlTest::createDescrambler() { +::testing::AssertionResult TunerHidlTest::getFilterMQDescriptor(const uint32_t filterId) { Result status; - mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) { - mDescrambler = descrambler; - status = result; - }); - if (status != Result::SUCCESS) { + if (!mDemux) { return ::testing::AssertionFailure(); } - if (createDemux() == ::testing::AssertionFailure()) { - return ::testing::AssertionFailure(); - } + mDemux->getFilterQueueDesc(filterId, [&](Result result, const MQDesc& filterMQDesc) { + mFilterMQDescriptor = filterMQDesc; + status = result; + }); - status = mDescrambler->setDemuxSource(mDemuxId); - if (status != Result::SUCCESS) { + return ::testing::AssertionResult(status == Result::SUCCESS); +} + +::testing::AssertionResult TunerHidlTest::readSectionFilterDataOutput() { + // Filter Configuration Module + DemuxInputSettings setting{ + .statusMask = 0xf, + .lowThreshold = 0x1000, + .highThreshold = 0x100000, + .dataFormat = DemuxDataFormat::TS, + .packetSize = 188, + }; + if (addSectionFilterToDemux() == ::testing::AssertionFailure() || + getFilterMQDescriptor(mFilterId) == ::testing::AssertionFailure() || + addInputToDemux(setting) == ::testing::AssertionFailure() || + getInputMQDescriptor() == ::testing::AssertionFailure()) { return ::testing::AssertionFailure(); } - // Test if demux source can be set more than once. - status = mDescrambler->setDemuxSource(mDemuxId); - return ::testing::AssertionResult(status == Result::INVALID_STATE); + // Data Verify Module + // Test start filter and read the output data + mDemuxCallback->testOnSectionFilterEvent(mDemux, mFilterId, mFilterMQDescriptor, + mInputMQDescriptor); + + // Clean Up Module + return closeDemux(); //::testing::AssertionSuccess(); } -::testing::AssertionResult TunerHidlTest::closeDescrambler() { +::testing::AssertionResult TunerHidlTest::playbackDataFlowTest(vector<FilterConf> filterConf, + InputConf inputConf, + string /*goldenOutput*/) { Result status; - if (createDescrambler() == ::testing::AssertionFailure()) { + // Filter Configuration Module + for (int i = 0; i < filterConf.size(); i++) { + if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) == + ::testing::AssertionFailure() || + // TODO use a map to save the FMQs/EvenFlags and pass to callback + getFilterMQDescriptor(mFilterId) == ::testing::AssertionFailure()) { + return ::testing::AssertionFailure(); + } + } + + // Playback Input Module + DemuxInputSettings inputSetting = inputConf.setting; + if (addInputToDemux(inputSetting) == ::testing::AssertionFailure() || + getInputMQDescriptor() == ::testing::AssertionFailure()) { + return ::testing::AssertionFailure(); + } + mDemuxCallback->startPlaybackInputThread(inputConf, mInputMQDescriptor); + status = mDemux->startInput(); + if (status != Result::SUCCESS) { return ::testing::AssertionFailure(); } - status = mDescrambler->close(); - return ::testing::AssertionResult(status == Result::SUCCESS); + // Data Verify Module + // golden output, created FMQ to read and EventFlags to DATA_CONSUMED + // Maintain each filter's real output (and how to assemble?????) + // mDemuxCallback->testPlaybackDataFlow(); + + // Clean Up Module + // TODO what about remove input, remove filters + return closeDemux(); } +/* + * API STATUS TESTS + */ TEST_F(TunerHidlTest, CreateFrontend) { Result status; hidl_vec<FrontendId> feIds; @@ -673,12 +861,6 @@ TEST_F(TunerHidlTest, CloseFrontend) { } } -TEST_F(TunerHidlTest, CreateDemux) { - description("Create Demux"); - - ASSERT_TRUE(createDemux()); -} - TEST_F(TunerHidlTest, CreateDemuxWithFrontend) { Result status; hidl_vec<FrontendId> feIds; @@ -699,50 +881,34 @@ TEST_F(TunerHidlTest, CreateDemuxWithFrontend) { } } -TEST_F(TunerHidlTest, AddSectionFilterToDemux) { - description("Add a section filter to a created demux"); - ASSERT_TRUE(addSectionFilterToDemux()); -} - -TEST_F(TunerHidlTest, AddPesFilterToDemux) { - description("Add a pes filter to a created demux"); - ASSERT_TRUE(addPesFilterToDemux()); -} - -TEST_F(TunerHidlTest, GetFilterMQDescriptor) { - description("Get MQ Descriptor from a created filter"); - ASSERT_TRUE(addSectionFilterToDemux()); - ASSERT_TRUE(getFilterMQDescriptor(mDemux, mFilterId)); -} - -TEST_F(TunerHidlTest, ReadSectionFilterOutput) { - description("Read data output from FMQ of a Section Filter"); - ASSERT_TRUE(readSectionFilterDataOutput()); -} - -TEST_F(TunerHidlTest, ReadPesFilterOutput) { - description("Read data output from FMQ of a PES Filter"); - ASSERT_TRUE(readPesFilterDataOutput()); +TEST_F(TunerHidlTest, CreateDemux) { + description("Create Demux"); + ASSERT_TRUE(createDemux()); } TEST_F(TunerHidlTest, CloseDemux) { description("Close Demux"); - ASSERT_TRUE(closeDemux()); } TEST_F(TunerHidlTest, CreateDescrambler) { description("Create Descrambler"); - ASSERT_TRUE(createDescrambler()); } TEST_F(TunerHidlTest, CloseDescrambler) { description("Close Descrambler"); - ASSERT_TRUE(closeDescrambler()); } +/* + * DATA FLOW TESTS + */ +TEST_F(TunerHidlTest, ReadSectionFilterOutput) { + description("Read data output from FMQ of a Section Filter"); + ASSERT_TRUE(readSectionFilterDataOutput()); +} + } // namespace int main(int argc, char** argv) { |