summaryrefslogtreecommitdiffstats
path: root/tv
diff options
context:
space:
mode:
Diffstat (limited to 'tv')
-rw-r--r--tv/tuner/1.0/vts/functional/Android.bp7
-rw-r--r--tv/tuner/1.0/vts/functional/DemuxTests.cpp41
-rw-r--r--tv/tuner/1.0/vts/functional/DemuxTests.h55
-rw-r--r--tv/tuner/1.0/vts/functional/FilterTests.cpp226
-rw-r--r--tv/tuner/1.0/vts/functional/FilterTests.h226
-rw-r--r--tv/tuner/1.0/vts/functional/FrontendTests.cpp310
-rw-r--r--tv/tuner/1.0/vts/functional/FrontendTests.h124
-rw-r--r--tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp1115
-rw-r--r--tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h260
-rw-r--r--tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h2
10 files changed, 1319 insertions, 1047 deletions
diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
index 641e16a937..448575ea7a 100644
--- a/tv/tuner/1.0/vts/functional/Android.bp
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -17,7 +17,12 @@
cc_test {
name: "VtsHalTvTunerV1_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
- srcs: ["VtsHalTvTunerV1_0TargetTest.cpp"],
+ srcs: [
+ "VtsHalTvTunerV1_0TargetTest.cpp",
+ "FrontendTests.cpp",
+ "DemuxTests.cpp",
+ "FilterTests.cpp",
+ ],
static_libs: [
"android.hardware.tv.tuner@1.0",
"android.hidl.allocator@1.0",
diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.cpp b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
new file mode 100644
index 0000000000..b1d8a0a0b2
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DemuxTests.h"
+
+AssertionResult DemuxTests::openDemux(sp<IDemux>& demux, uint32_t& demuxId) {
+ Result status;
+ mService->openDemux([&](Result result, uint32_t id, const sp<IDemux>& demuxSp) {
+ mDemux = demuxSp;
+ demux = demuxSp;
+ demuxId = id;
+ status = result;
+ });
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DemuxTests::setDemuxFrontendDataSource(uint32_t frontendId) {
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ auto status = mDemux->setFrontendDataSource(frontendId);
+ return AssertionResult(status.isOk());
+}
+
+AssertionResult DemuxTests::closeDemux() {
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ auto status = mDemux->close();
+ mDemux = nullptr;
+ return AssertionResult(status.isOk());
+} \ No newline at end of file
diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.h b/tv/tuner/1.0/vts/functional/DemuxTests.h
new file mode 100644
index 0000000000..a72c09fd0c
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/tv/tuner/1.0/IDemux.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <binder/MemoryDealer.h>
+#include <gtest/gtest.h>
+#include <hidl/ServiceManagement.h>
+#include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <map>
+
+using android::sp;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::IDemux;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::Result;
+
+using ::testing::AssertionResult;
+
+class DemuxTests {
+ public:
+ sp<ITuner> mService;
+
+ void setService(sp<ITuner> tuner) { mService = tuner; }
+
+ AssertionResult openDemux(sp<IDemux>& demux, uint32_t& demuxId);
+ AssertionResult setDemuxFrontendDataSource(uint32_t frontendId);
+ AssertionResult closeDemux();
+
+ protected:
+ static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+ static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+ sp<IDemux> mDemux;
+};
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.cpp b/tv/tuner/1.0/vts/functional/FilterTests.cpp
new file mode 100644
index 0000000000..82e955d90e
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/FilterTests.cpp
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FilterTests.h"
+
+void FilterCallback::startFilterEventThread(DemuxFilterEvent event) {
+ struct FilterThreadArgs* threadArgs =
+ (struct FilterThreadArgs*)malloc(sizeof(struct FilterThreadArgs));
+ threadArgs->user = this;
+ threadArgs->event = event;
+
+ pthread_create(&mFilterThread, NULL, __threadLoopFilter, (void*)threadArgs);
+ pthread_setname_np(mFilterThread, "test_playback_input_loop");
+}
+
+void FilterCallback::testFilterDataOutput() {
+ android::Mutex::Autolock autoLock(mMsgLock);
+ while (mPidFilterOutputCount < 1) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
+ return;
+ }
+ }
+ mPidFilterOutputCount = 0;
+ ALOGW("[vts] pass and stop");
+}
+
+void FilterCallback::updateFilterMQ(MQDesc& filterMQDescriptor) {
+ mFilterMQ = std::make_unique<FilterMQ>(filterMQDescriptor, true /* resetPointers */);
+ EXPECT_TRUE(mFilterMQ);
+ EXPECT_TRUE(EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterMQEventFlag) ==
+ android::OK);
+}
+
+void FilterCallback::updateGoldenOutputMap(string goldenOutputFile) {
+ mFilterIdToGoldenOutput = goldenOutputFile;
+}
+
+void* FilterCallback::__threadLoopFilter(void* threadArgs) {
+ FilterCallback* const self =
+ static_cast<FilterCallback*>(((struct FilterThreadArgs*)threadArgs)->user);
+ self->filterThreadLoop(((struct FilterThreadArgs*)threadArgs)->event);
+ return 0;
+}
+
+void FilterCallback::filterThreadLoop(DemuxFilterEvent& /* event */) {
+ android::Mutex::Autolock autoLock(mFilterOutputLock);
+ // Read from mFilterMQ[event.filterId] per event and filter type
+
+ // Assemble to filterOutput[filterId]
+
+ // check if filterOutput[filterId] matches goldenOutput[filterId]
+
+ // If match, remove filterId entry from MQ map
+
+ // end thread
+}
+
+bool FilterCallback::readFilterEventData() {
+ bool result = false;
+ DemuxFilterEvent filterEvent = mFilterEvent;
+ ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
+ // todo separate filter handlers
+ for (int i = 0; i < filterEvent.events.size(); i++) {
+ switch (mFilterEventType) {
+ case FilterEventType::SECTION:
+ mDataLength = filterEvent.events[i].section().dataLength;
+ break;
+ case FilterEventType::PES:
+ mDataLength = filterEvent.events[i].pes().dataLength;
+ break;
+ case FilterEventType::MEDIA:
+ return dumpAvData(filterEvent.events[i].media());
+ case FilterEventType::RECORD:
+ break;
+ case FilterEventType::MMTPRECORD:
+ break;
+ case FilterEventType::DOWNLOAD:
+ break;
+ default:
+ break;
+ }
+ // 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(goldenDataOutputBuffer[i] == mDataOutputBuffer[i]) << "data does not match";
+ }*/
+ }
+ mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
+ return result;
+}
+
+bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
+ uint32_t length = event.dataLength;
+ uint64_t dataId = event.avDataId;
+ // read data from buffer pointed by a handle
+ hidl_handle handle = event.avMemory;
+
+ 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 /*offset*/));
+ if (buffer == MAP_FAILED) {
+ ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
+ return false;
+ }
+ uint8_t output[length + 1];
+ memcpy(output, buffer, length);
+ // print buffer and check with golden output.
+ EXPECT_TRUE(mFilter->releaseAvHandle(handle, dataId) == Result::SUCCESS);
+ return true;
+}
+
+AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type) {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+
+ // Create demux callback
+ mFilterCallback = new FilterCallback();
+
+ // Add filter to the local demux
+ mDemux->openFilter(type, FMQ_SIZE_16M, mFilterCallback,
+ [&](Result result, const sp<IFilter>& filter) {
+ mFilter = filter;
+ status = result;
+ });
+
+ if (status == Result::SUCCESS) {
+ mFilterCallback->setFilterEventType(getFilterEventType(type));
+ }
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::getNewlyOpenedFilterId(uint32_t& filterId) {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mFilter) << "Test with openFilterInDemux first.";
+ EXPECT_TRUE(mFilterCallback) << "Test with openFilterInDemux first.";
+
+ mFilter->getId([&](Result result, uint32_t filterId) {
+ mFilterId = filterId;
+ status = result;
+ });
+
+ if (status == Result::SUCCESS) {
+ mFilterCallback->setFilterId(mFilterId);
+ mFilterCallback->setFilterInterface(mFilter);
+ mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
+ mFilters[mFilterId] = mFilter;
+ mFilterCallbacks[mFilterId] = mFilterCallback;
+ filterId = mFilterId;
+ }
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::configFilter(DemuxFilterSettings setting, uint32_t filterId) {
+ Result status;
+ EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+ status = mFilters[filterId]->configure(setting);
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::getFilterMQDescriptor(uint32_t filterId) {
+ Result status;
+ EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+ EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
+
+ mFilter->getQueueDesc([&](Result result, const MQDesc& filterMQDesc) {
+ mFilterMQDescriptor = filterMQDesc;
+ status = result;
+ });
+
+ if (status == Result::SUCCESS) {
+ mFilterCallbacks[filterId]->updateFilterMQ(mFilterMQDescriptor);
+ }
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::startFilter(uint32_t filterId) {
+ EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+ Result status = mFilters[filterId]->start();
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::stopFilter(uint32_t filterId) {
+ EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+ Result status = mFilters[filterId]->stop();
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+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;
+ }
+ }
+ mFilterCallbacks.erase(filterId);
+ mFilters.erase(filterId);
+ }
+ return AssertionResult(status == Result::SUCCESS);
+} \ No newline at end of file
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.h b/tv/tuner/1.0/vts/functional/FilterTests.h
new file mode 100644
index 0000000000..3cc06e578d
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/FilterTests.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/tv/tuner/1.0/IFilter.h>
+#include <android/hardware/tv/tuner/1.0/IFilterCallback.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/Status.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <map>
+
+using android::Condition;
+using android::Mutex;
+using android::sp;
+using android::hardware::EventFlag;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::MessageQueue;
+using android::hardware::MQDescriptorSync;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
+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::DemuxQueueNotifyBits;
+using android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
+using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using android::hardware::tv::tuner::V1_0::IDemux;
+using android::hardware::tv::tuner::V1_0::IFilter;
+using android::hardware::tv::tuner::V1_0::IFilterCallback;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::Result;
+
+using ::testing::AssertionResult;
+
+using namespace std;
+
+enum FilterEventType : uint8_t {
+ UNDEFINED,
+ SECTION,
+ MEDIA,
+ PES,
+ RECORD,
+ MMTPRECORD,
+ DOWNLOAD,
+ TEMI,
+};
+
+using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+using MQDesc = MQDescriptorSync<uint8_t>;
+
+const uint32_t FMQ_SIZE_1M = 0x100000;
+const uint32_t FMQ_SIZE_16M = 0x1000000;
+
+#define WAIT_TIMEOUT 3000000000
+
+class FilterCallback : public IFilterCallback {
+ public:
+ virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent) override {
+ android::Mutex::Autolock autoLock(mMsgLock);
+ // Temprarily we treat the first coming back filter data on the matching pid a success
+ // once all of the MQ are cleared, means we got all the expected output
+ mFilterEvent = filterEvent;
+ readFilterEventData();
+ mPidFilterOutputCount++;
+ // mFilterIdToMQ.erase(filterEvent.filterId);
+
+ // startFilterEventThread(filterEvent);
+ mMsgCondition.signal();
+ return Void();
+ }
+
+ virtual Return<void> onFilterStatus(const DemuxFilterStatus /*status*/) override {
+ return Void();
+ }
+
+ void setFilterId(uint32_t filterId) { mFilterId = filterId; }
+ void setFilterInterface(sp<IFilter> filter) { mFilter = filter; }
+ void setFilterEventType(FilterEventType type) { mFilterEventType = type; }
+
+ void testFilterDataOutput();
+
+ void startFilterEventThread(DemuxFilterEvent event);
+ static void* __threadLoopFilter(void* threadArgs);
+ void filterThreadLoop(DemuxFilterEvent& event);
+
+ void updateFilterMQ(MQDesc& filterMQDescriptor);
+ void updateGoldenOutputMap(string goldenOutputFile);
+ bool readFilterEventData();
+ bool dumpAvData(DemuxFilterMediaEvent event);
+
+ private:
+ struct FilterThreadArgs {
+ FilterCallback* user;
+ DemuxFilterEvent event;
+ };
+ uint16_t mDataLength = 0;
+ std::vector<uint8_t> mDataOutputBuffer;
+
+ string mFilterIdToGoldenOutput;
+
+ uint32_t mFilterId;
+ sp<IFilter> mFilter;
+ FilterEventType mFilterEventType;
+ std::unique_ptr<FilterMQ> mFilterMQ;
+ EventFlag* mFilterMQEventFlag;
+ DemuxFilterEvent mFilterEvent;
+
+ android::Mutex mMsgLock;
+ android::Mutex mFilterOutputLock;
+ android::Condition mMsgCondition;
+ android::Condition mFilterOutputCondition;
+
+ pthread_t mFilterThread;
+
+ int mPidFilterOutputCount = 0;
+};
+
+class FilterTests {
+ public:
+ void setService(sp<ITuner> tuner) { mService = tuner; }
+ void setDemux(sp<IDemux> demux) { mDemux = demux; }
+
+ std::map<uint32_t, sp<FilterCallback>> getFilterCallbacks() { return mFilterCallbacks; }
+
+ AssertionResult openFilterInDemux(DemuxFilterType type);
+ AssertionResult getNewlyOpenedFilterId(uint32_t& filterId);
+ AssertionResult configFilter(DemuxFilterSettings setting, uint32_t filterId);
+ AssertionResult getFilterMQDescriptor(uint32_t filterId);
+ AssertionResult startFilter(uint32_t filterId);
+ AssertionResult stopFilter(uint32_t filterId);
+ AssertionResult closeFilter(uint32_t filterId);
+
+ FilterEventType getFilterEventType(DemuxFilterType type) {
+ FilterEventType eventType = FilterEventType::UNDEFINED;
+ switch (type.mainType) {
+ case DemuxFilterMainType::TS:
+ switch (type.subType.tsFilterType()) {
+ case DemuxTsFilterType::UNDEFINED:
+ break;
+ case DemuxTsFilterType::SECTION:
+ eventType = FilterEventType::SECTION;
+ break;
+ case DemuxTsFilterType::PES:
+ eventType = FilterEventType::PES;
+ break;
+ case DemuxTsFilterType::TS:
+ break;
+ case DemuxTsFilterType::AUDIO:
+ case DemuxTsFilterType::VIDEO:
+ eventType = FilterEventType::MEDIA;
+ break;
+ case DemuxTsFilterType::PCR:
+ break;
+ case DemuxTsFilterType::RECORD:
+ eventType = FilterEventType::RECORD;
+ break;
+ case DemuxTsFilterType::TEMI:
+ eventType = FilterEventType::TEMI;
+ break;
+ }
+ break;
+ case DemuxFilterMainType::MMTP:
+ /*mmtpSettings*/
+ break;
+ case DemuxFilterMainType::IP:
+ /*ipSettings*/
+ break;
+ case DemuxFilterMainType::TLV:
+ /*tlvSettings*/
+ break;
+ case DemuxFilterMainType::ALP:
+ /*alpSettings*/
+ break;
+ default:
+ break;
+ }
+ return eventType;
+ }
+
+ protected:
+ static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+ static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+ sp<ITuner> mService;
+ sp<IFilter> mFilter;
+ sp<IDemux> mDemux;
+ std::map<uint32_t, sp<IFilter>> mFilters;
+ std::map<uint32_t, sp<FilterCallback>> mFilterCallbacks;
+
+ sp<FilterCallback> mFilterCallback;
+ MQDesc mFilterMQDescriptor;
+ vector<uint32_t> mUsedFilterIds;
+
+ uint32_t mFilterId = -1;
+};
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.cpp b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
new file mode 100644
index 0000000000..fc5071ceaa
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FrontendTests.h"
+
+Return<void> FrontendCallback::onEvent(FrontendEventType frontendEventType) {
+ android::Mutex::Autolock autoLock(mMsgLock);
+ ALOGD("[vts] frontend event received. Type: %d", frontendEventType);
+ mEventReceived = true;
+ mMsgCondition.signal();
+ switch (frontendEventType) {
+ case FrontendEventType::LOCKED:
+ mLockMsgReceived = true;
+ mLockMsgCondition.signal();
+ return Void();
+ default:
+ // do nothing
+ return Void();
+ }
+}
+
+Return<void> FrontendCallback::onScanMessage(FrontendScanMessageType type,
+ const FrontendScanMessage& message) {
+ android::Mutex::Autolock autoLock(mMsgLock);
+ while (!mScanMsgProcessed) {
+ mMsgCondition.wait(mMsgLock);
+ }
+ ALOGD("[vts] frontend scan message. Type: %d", type);
+ mScanMessageReceived = true;
+ mScanMsgProcessed = false;
+ mScanMessageType = type;
+ mScanMessage = message;
+ mMsgCondition.signal();
+ return Void();
+}
+
+void FrontendCallback::tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings) {
+ Result result = frontend->tune(settings);
+ EXPECT_TRUE(result == Result::SUCCESS);
+
+ android::Mutex::Autolock autoLock(mMsgLock);
+ while (!mEventReceived) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ EXPECT_TRUE(false) << "Event not received within timeout";
+ mLockMsgReceived = false;
+ return;
+ }
+ }
+ mEventReceived = false;
+}
+
+void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings) {
+ Result result = frontend->tune(settings);
+ EXPECT_TRUE(result == Result::SUCCESS);
+
+ android::Mutex::Autolock autoLock(mMsgLock);
+ while (!mLockMsgReceived) {
+ if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ EXPECT_TRUE(false) << "Event LOCKED not received within timeout";
+ mLockMsgReceived = false;
+ return;
+ }
+ }
+ mLockMsgReceived = false;
+}
+
+void FrontendCallback::scanTest(sp<IFrontend>& frontend, FrontendConfig config,
+ FrontendScanType type) {
+ uint32_t targetFrequency = getTargetFrequency(config.settings, config.type);
+ if (type == FrontendScanType::SCAN_BLIND) {
+ // reset the frequency in the scan configuration to test blind scan. The settings param of
+ // passed in means the real input config on the transponder connected to the DUT.
+ // We want the blind the test to start from lower frequency than this to check the blind
+ // scan implementation.
+ resetBlindScanStartingFrequency(config, targetFrequency - 100);
+ }
+
+ Result result = frontend->scan(config.settings, type);
+ EXPECT_TRUE(result == Result::SUCCESS);
+
+ bool scanMsgLockedReceived = false;
+ bool targetFrequencyReceived = false;
+
+ android::Mutex::Autolock autoLock(mMsgLock);
+wait:
+ while (!mScanMessageReceived) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ EXPECT_TRUE(false) << "Scan message not received within timeout";
+ mScanMessageReceived = false;
+ mScanMsgProcessed = true;
+ return;
+ }
+ }
+
+ if (mScanMessageType != FrontendScanMessageType::END) {
+ if (mScanMessageType == FrontendScanMessageType::LOCKED) {
+ scanMsgLockedReceived = true;
+ Result result = frontend->scan(config.settings, type);
+ EXPECT_TRUE(result == Result::SUCCESS);
+ }
+
+ if (mScanMessageType == FrontendScanMessageType::FREQUENCY) {
+ targetFrequencyReceived = mScanMessage.frequencies().size() > 0 &&
+ mScanMessage.frequencies()[0] == targetFrequency;
+ }
+
+ if (mScanMessageType == FrontendScanMessageType::PROGRESS_PERCENT) {
+ ALOGD("[vts] Scan in progress...[%d%%]", mScanMessage.progressPercent());
+ }
+
+ mScanMessageReceived = false;
+ mScanMsgProcessed = true;
+ mMsgCondition.signal();
+ goto wait;
+ }
+
+ EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END";
+ EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
+ mScanMessageReceived = false;
+ mScanMsgProcessed = true;
+}
+
+uint32_t FrontendCallback::getTargetFrequency(FrontendSettings settings, FrontendType type) {
+ switch (type) {
+ case FrontendType::ANALOG:
+ return settings.analog().frequency;
+ case FrontendType::ATSC:
+ return settings.atsc().frequency;
+ case FrontendType::ATSC3:
+ return settings.atsc3().frequency;
+ case FrontendType::DVBC:
+ return settings.dvbc().frequency;
+ case FrontendType::DVBS:
+ return settings.dvbs().frequency;
+ case FrontendType::DVBT:
+ return settings.dvbt().frequency;
+ case FrontendType::ISDBS:
+ return settings.isdbs().frequency;
+ case FrontendType::ISDBS3:
+ return settings.isdbs3().frequency;
+ case FrontendType::ISDBT:
+ return settings.isdbt().frequency;
+ default:
+ return 0;
+ }
+}
+
+void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig& config,
+ uint32_t resetingFreq) {
+ switch (config.type) {
+ case FrontendType::ANALOG:
+ config.settings.analog().frequency = resetingFreq;
+ break;
+ case FrontendType::ATSC:
+ config.settings.atsc().frequency = resetingFreq;
+ break;
+ case FrontendType::ATSC3:
+ config.settings.atsc3().frequency = resetingFreq;
+ break;
+ case FrontendType::DVBC:
+ config.settings.dvbc().frequency = resetingFreq;
+ break;
+ case FrontendType::DVBS:
+ config.settings.dvbs().frequency = resetingFreq;
+ break;
+ case FrontendType::DVBT:
+ config.settings.dvbt().frequency = resetingFreq;
+ break;
+ case FrontendType::ISDBS:
+ config.settings.isdbs().frequency = resetingFreq;
+ break;
+ case FrontendType::ISDBS3:
+ config.settings.isdbs3().frequency = resetingFreq;
+ break;
+ case FrontendType::ISDBT:
+ config.settings.isdbt().frequency = resetingFreq;
+ break;
+ default:
+ // do nothing
+ return;
+ }
+}
+
+AssertionResult FrontendTests::getFrontendIds() {
+ Result status;
+ mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+ status = result;
+ mFeIds = frontendIds;
+ });
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::getFrontendInfo(uint32_t frontendId) {
+ Result status;
+ mService->getFrontendInfo(frontendId, [&](Result result, const FrontendInfo& frontendInfo) {
+ mFrontendInfo = frontendInfo;
+ status = result;
+ });
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::openFrontendById(uint32_t frontendId) {
+ Result status;
+ mService->openFrontendById(frontendId, [&](Result result, const sp<IFrontend>& frontend) {
+ mFrontend = frontend;
+ status = result;
+ });
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::setFrontendCallback() {
+ EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+ mFrontendCallback = new FrontendCallback();
+ auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
+ return AssertionResult(callbackStatus.isOk());
+}
+
+AssertionResult FrontendTests::scanFrontend(FrontendConfig config, FrontendScanType type) {
+ EXPECT_TRUE(mFrontendCallback)
+ << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
+
+ EXPECT_TRUE(mFrontendInfo.type == config.type)
+ << "FrontendConfig does not match the frontend info of the given id.";
+
+ mFrontendCallback->scanTest(mFrontend, config, type);
+ return AssertionResult(true);
+}
+
+AssertionResult FrontendTests::stopScanFrontend() {
+ EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+ Result status;
+ status = mFrontend->stopScan();
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::tuneFrontend(FrontendConfig config) {
+ EXPECT_TRUE(mFrontendCallback)
+ << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
+
+ EXPECT_TRUE(mFrontendInfo.type == config.type)
+ << "FrontendConfig does not match the frontend info of the given id.";
+
+ mFrontendCallback->tuneTestOnLock(mFrontend, config.settings);
+ return AssertionResult(true);
+}
+
+AssertionResult FrontendTests::stopTuneFrontend() {
+ EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+ Result status;
+ status = mFrontend->stopTune();
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::closeFrontend() {
+ EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+ Result status;
+ status = mFrontend->close();
+ mFrontend = nullptr;
+ mFrontendCallback = nullptr;
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+void FrontendTests::getFrontendIdByType(FrontendType feType, uint32_t& feId) {
+ ASSERT_TRUE(getFrontendIds());
+ ASSERT_TRUE(mFeIds.size() > 0);
+ for (size_t i = 0; i < mFeIds.size(); i++) {
+ ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
+ if (mFrontendInfo.type != feType) {
+ continue;
+ }
+ feId = mFeIds[i];
+ return;
+ }
+ feId = INVALID_ID;
+}
+
+void FrontendTests::tuneTest(FrontendConfig frontendConf) {
+ uint32_t feId;
+ getFrontendIdByType(frontendConf.type, feId);
+ ASSERT_TRUE(feId != INVALID_ID);
+ ASSERT_TRUE(openFrontendById(feId));
+ ASSERT_TRUE(setFrontendCallback());
+ ASSERT_TRUE(tuneFrontend(frontendConf));
+ ASSERT_TRUE(stopTuneFrontend());
+ ASSERT_TRUE(closeFrontend());
+}
+
+void FrontendTests::scanTest(FrontendConfig frontendConf, FrontendScanType scanType) {
+ uint32_t feId;
+ getFrontendIdByType(frontendConf.type, feId);
+ ASSERT_TRUE(feId != INVALID_ID);
+ ASSERT_TRUE(openFrontendById(feId));
+ ASSERT_TRUE(setFrontendCallback());
+ ASSERT_TRUE(scanFrontend(frontendConf, scanType));
+ ASSERT_TRUE(stopScanFrontend());
+ ASSERT_TRUE(closeFrontend());
+}
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.h b/tv/tuner/1.0/vts/functional/FrontendTests.h
new file mode 100644
index 0000000000..1a9bec9627
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/tv/tuner/1.0/IFrontend.h>
+#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <binder/MemoryDealer.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/ServiceManagement.h>
+#include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <map>
+
+#include "VtsHalTvTunerV1_0TestConfigurations.h"
+
+#define WAIT_TIMEOUT 3000000000
+#define INVALID_ID -1
+
+using android::Condition;
+using android::IMemory;
+using android::IMemoryHeap;
+using android::MemoryDealer;
+using android::Mutex;
+using android::sp;
+using android::hardware::fromHeap;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
+using android::hardware::tv::tuner::V1_0::FrontendAtscSettings;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
+using android::hardware::tv::tuner::V1_0::FrontendEventType;
+using android::hardware::tv::tuner::V1_0::FrontendId;
+using android::hardware::tv::tuner::V1_0::FrontendInfo;
+using android::hardware::tv::tuner::V1_0::FrontendInnerFec;
+using android::hardware::tv::tuner::V1_0::FrontendScanMessage;
+using android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
+using android::hardware::tv::tuner::V1_0::FrontendScanType;
+using android::hardware::tv::tuner::V1_0::FrontendSettings;
+using android::hardware::tv::tuner::V1_0::IFrontend;
+using android::hardware::tv::tuner::V1_0::IFrontendCallback;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::Result;
+
+using ::testing::AssertionResult;
+
+using namespace std;
+
+#define INVALID_ID -1
+#define WAIT_TIMEOUT 3000000000
+
+class FrontendCallback : public IFrontendCallback {
+ public:
+ virtual Return<void> onEvent(FrontendEventType frontendEventType) override;
+ virtual Return<void> onScanMessage(FrontendScanMessageType type,
+ const FrontendScanMessage& message) override;
+
+ void tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings);
+ void tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings);
+ void scanTest(sp<IFrontend>& frontend, FrontendConfig config, FrontendScanType type);
+
+ // Helper methods
+ uint32_t getTargetFrequency(FrontendSettings settings, FrontendType type);
+ void resetBlindScanStartingFrequency(FrontendConfig& config, uint32_t resetingFreq);
+
+ private:
+ bool mEventReceived = false;
+ bool mScanMessageReceived = false;
+ bool mLockMsgReceived = false;
+ bool mScanMsgProcessed = true;
+ FrontendScanMessageType mScanMessageType;
+ FrontendScanMessage mScanMessage;
+ hidl_vec<uint8_t> mEventMessage;
+ android::Mutex mMsgLock;
+ android::Condition mMsgCondition;
+ android::Condition mLockMsgCondition;
+};
+
+class FrontendTests {
+ public:
+ sp<ITuner> mService;
+
+ void setService(sp<ITuner> tuner) { mService = tuner; }
+
+ AssertionResult getFrontendIds();
+ AssertionResult getFrontendInfo(uint32_t frontendId);
+ AssertionResult openFrontendById(uint32_t frontendId);
+ AssertionResult setFrontendCallback();
+ AssertionResult scanFrontend(FrontendConfig config, FrontendScanType type);
+ AssertionResult stopScanFrontend();
+ AssertionResult tuneFrontend(FrontendConfig config);
+ AssertionResult stopTuneFrontend();
+ AssertionResult closeFrontend();
+
+ void getFrontendIdByType(FrontendType feType, uint32_t& feId);
+ void tuneTest(FrontendConfig frontendConf);
+ void scanTest(FrontendConfig frontend, FrontendScanType type);
+
+ protected:
+ sp<IFrontend> mFrontend;
+ FrontendInfo mFrontendInfo;
+ sp<FrontendCallback> mFrontendCallback;
+ hidl_vec<FrontendId> mFeIds;
+};
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 5e98367af6..d836c26f9f 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -14,630 +14,11 @@
* limitations under the License.
*/
-#define LOG_TAG "Tuner_hidl_hal_test"
-
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
-#include <android-base/logging.h>
-#include <android/hardware/tv/tuner/1.0/IDemux.h>
-#include <android/hardware/tv/tuner/1.0/IDescrambler.h>
-#include <android/hardware/tv/tuner/1.0/IDvr.h>
-#include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
-#include <android/hardware/tv/tuner/1.0/IFilter.h>
-#include <android/hardware/tv/tuner/1.0/IFilterCallback.h>
-#include <android/hardware/tv/tuner/1.0/IFrontend.h>
-#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
-#include <android/hardware/tv/tuner/1.0/ITuner.h>
-#include <android/hardware/tv/tuner/1.0/types.h>
-#include <binder/MemoryDealer.h>
-#include <fmq/MessageQueue.h>
-#include <gtest/gtest.h>
-#include <hidl/GtestPrinter.h>
-#include <hidl/HidlSupport.h>
-#include <hidl/HidlTransportSupport.h>
-#include <hidl/ServiceManagement.h>
-#include <hidl/Status.h>
-#include <hidlmemory/FrameworkUtils.h>
-#include <utils/Condition.h>
-#include <utils/Mutex.h>
-#include <fstream>
-#include <iostream>
-#include <map>
-
-#include "VtsHalTvTunerV1_0TestConfigurations.h"
-
-#define WAIT_TIMEOUT 3000000000
-#define INVALID_ID -1
-
-using android::Condition;
-using android::IMemory;
-using android::IMemoryHeap;
-using android::MemoryDealer;
-using android::Mutex;
-using android::sp;
-using android::hardware::EventFlag;
-using android::hardware::fromHeap;
-using android::hardware::hidl_handle;
-using android::hardware::hidl_string;
-using android::hardware::hidl_vec;
-using android::hardware::HidlMemory;
-using android::hardware::kSynchronizedReadWrite;
-using android::hardware::MessageQueue;
-using android::hardware::MQDescriptorSync;
-using android::hardware::Return;
-using android::hardware::Void;
-using android::hardware::tv::tuner::V1_0::DataFormat;
-using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
-using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
-using android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent;
-using android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
-using android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent;
-using android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings;
-using android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent;
-using android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
-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::DemuxQueueNotifyBits;
-using android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
-using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
-using android::hardware::tv::tuner::V1_0::DvrSettings;
-using android::hardware::tv::tuner::V1_0::DvrType;
-using android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
-using android::hardware::tv::tuner::V1_0::FrontendAtscSettings;
-using android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
-using android::hardware::tv::tuner::V1_0::FrontendEventType;
-using android::hardware::tv::tuner::V1_0::FrontendId;
-using android::hardware::tv::tuner::V1_0::FrontendInfo;
-using android::hardware::tv::tuner::V1_0::FrontendInnerFec;
-using android::hardware::tv::tuner::V1_0::FrontendScanMessage;
-using android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
-using android::hardware::tv::tuner::V1_0::FrontendScanType;
-using android::hardware::tv::tuner::V1_0::FrontendSettings;
-using android::hardware::tv::tuner::V1_0::IDemux;
-using android::hardware::tv::tuner::V1_0::IDescrambler;
-using android::hardware::tv::tuner::V1_0::IDvr;
-using android::hardware::tv::tuner::V1_0::IDvrCallback;
-using android::hardware::tv::tuner::V1_0::IFilter;
-using android::hardware::tv::tuner::V1_0::IFilterCallback;
-using android::hardware::tv::tuner::V1_0::IFrontend;
-using android::hardware::tv::tuner::V1_0::IFrontendCallback;
-using android::hardware::tv::tuner::V1_0::ITuner;
-using android::hardware::tv::tuner::V1_0::PlaybackSettings;
-using android::hardware::tv::tuner::V1_0::PlaybackStatus;
-using android::hardware::tv::tuner::V1_0::RecordSettings;
-using android::hardware::tv::tuner::V1_0::RecordStatus;
-using android::hardware::tv::tuner::V1_0::Result;
-
-using ::testing::AssertionResult;
+#include "VtsHalTvTunerV1_0TargetTest.h"
namespace {
-using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-using MQDesc = MQDescriptorSync<uint8_t>;
-
-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,
- 0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
- 0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
- 0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
- 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
- 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
- 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
- 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
- 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x2d, 0x20,
- 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x62, 0x61, 0x63, 0x3d,
- 0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
- 0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x65, 0x3d,
- 0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68, 0x65,
- 0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
- 0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e,
- 0x30, 0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20,
- 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72,
- 0x6f, 0x6d, 0x61, 0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69,
- 0x73, 0x3d, 0x31, 0x20, 0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71,
- 0x6d, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31,
- 0x2c, 0x31, 0x31, 0x20, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d,
- 0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66,
- 0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d,
- 0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x68,
- 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x5f,
- 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e, 0x72, 0x3d, 0x30, 0x20,
- 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69, 0x6e, 0x74, 0x65,
- 0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72, 0x61, 0x79,
- 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
- 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
- 0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68,
- 0x74, 0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30,
- 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20,
- 0x73, 0x63, 0x65, 0x6e, 0x65,
-};
-
-// const uint16_t FMQ_SIZE_4K = 0x1000;
-const uint32_t FMQ_SIZE_1M = 0x100000;
-const uint32_t FMQ_SIZE_16M = 0x1000000;
-
-enum FilterEventType : uint8_t {
- UNDEFINED,
- SECTION,
- MEDIA,
- PES,
- RECORD,
- MMTPRECORD,
- DOWNLOAD,
- TEMI,
-};
-
-struct PlaybackConf {
- string inputDataFile;
- PlaybackSettings setting;
-};
-
-/******************************** Start FrontendCallback **********************************/
-class FrontendCallback : public IFrontendCallback {
- public:
- virtual Return<void> onEvent(FrontendEventType frontendEventType) override {
- android::Mutex::Autolock autoLock(mMsgLock);
- ALOGD("[vts] frontend event received. Type: %d", frontendEventType);
- mEventReceived = true;
- mMsgCondition.signal();
- switch (frontendEventType) {
- case FrontendEventType::LOCKED:
- mLockMsgReceived = true;
- mLockMsgCondition.signal();
- return Void();
- default:
- // do nothing
- return Void();
- }
- }
-
- virtual Return<void> onScanMessage(FrontendScanMessageType type,
- const FrontendScanMessage& message) override {
- android::Mutex::Autolock autoLock(mMsgLock);
- while (!mScanMsgProcessed) {
- mMsgCondition.wait(mMsgLock);
- }
- ALOGD("[vts] frontend scan message. Type: %d", type);
- mScanMessageReceived = true;
- mScanMsgProcessed = false;
- mScanMessageType = type;
- mScanMessage = message;
- mMsgCondition.signal();
- return Void();
- }
-
- void tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings);
- void tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings);
- void scanTest(sp<IFrontend>& frontend, FrontendConfig config, FrontendScanType type);
-
- // Helper methods
- uint32_t getTargetFrequency(FrontendSettings settings, FrontendType type);
- void resetBlindScanStartingFrequency(FrontendConfig& config, uint32_t resetingFreq);
-
- private:
- bool mEventReceived = false;
- bool mScanMessageReceived = false;
- bool mLockMsgReceived = false;
- bool mScanMsgProcessed = true;
- FrontendScanMessageType mScanMessageType;
- FrontendScanMessage mScanMessage;
- hidl_vec<uint8_t> mEventMessage;
- android::Mutex mMsgLock;
- android::Condition mMsgCondition;
- android::Condition mLockMsgCondition;
-};
-
-void FrontendCallback::tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings) {
- Result result = frontend->tune(settings);
- EXPECT_TRUE(result == Result::SUCCESS);
-
- android::Mutex::Autolock autoLock(mMsgLock);
- while (!mEventReceived) {
- if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
- EXPECT_TRUE(false) << "Event not received within timeout";
- mLockMsgReceived = false;
- return;
- }
- }
- mEventReceived = false;
-}
-
-void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings) {
- Result result = frontend->tune(settings);
- EXPECT_TRUE(result == Result::SUCCESS);
-
- android::Mutex::Autolock autoLock(mMsgLock);
- while (!mLockMsgReceived) {
- if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
- EXPECT_TRUE(false) << "Event LOCKED not received within timeout";
- mLockMsgReceived = false;
- return;
- }
- }
- mLockMsgReceived = false;
-}
-
-void FrontendCallback::scanTest(sp<IFrontend>& frontend, FrontendConfig config,
- FrontendScanType type) {
- uint32_t targetFrequency = getTargetFrequency(config.settings, config.type);
- if (type == FrontendScanType::SCAN_BLIND) {
- // reset the frequency in the scan configuration to test blind scan. The settings param of
- // passed in means the real input config on the transponder connected to the DUT.
- // We want the blind the test to start from lower frequency than this to check the blind
- // scan implementation.
- resetBlindScanStartingFrequency(config, targetFrequency - 100);
- }
-
- Result result = frontend->scan(config.settings, type);
- EXPECT_TRUE(result == Result::SUCCESS);
-
- bool scanMsgLockedReceived = false;
- bool targetFrequencyReceived = false;
-
- android::Mutex::Autolock autoLock(mMsgLock);
-wait:
- while (!mScanMessageReceived) {
- if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
- EXPECT_TRUE(false) << "Scan message not received within timeout";
- mScanMessageReceived = false;
- mScanMsgProcessed = true;
- return;
- }
- }
-
- if (mScanMessageType != FrontendScanMessageType::END) {
- if (mScanMessageType == FrontendScanMessageType::LOCKED) {
- scanMsgLockedReceived = true;
- Result result = frontend->scan(config.settings, type);
- EXPECT_TRUE(result == Result::SUCCESS);
- }
-
- if (mScanMessageType == FrontendScanMessageType::FREQUENCY) {
- targetFrequencyReceived = mScanMessage.frequencies().size() > 0 &&
- mScanMessage.frequencies()[0] == targetFrequency;
- }
-
- if (mScanMessageType == FrontendScanMessageType::PROGRESS_PERCENT) {
- ALOGD("[vts] Scan in progress...[%d%%]", mScanMessage.progressPercent());
- }
-
- mScanMessageReceived = false;
- mScanMsgProcessed = true;
- mMsgCondition.signal();
- goto wait;
- }
-
- EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END";
- EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
- mScanMessageReceived = false;
- mScanMsgProcessed = true;
-}
-
-uint32_t FrontendCallback::getTargetFrequency(FrontendSettings settings, FrontendType type) {
- switch (type) {
- case FrontendType::ANALOG:
- return settings.analog().frequency;
- case FrontendType::ATSC:
- return settings.atsc().frequency;
- case FrontendType::ATSC3:
- return settings.atsc3().frequency;
- case FrontendType::DVBC:
- return settings.dvbc().frequency;
- case FrontendType::DVBS:
- return settings.dvbs().frequency;
- case FrontendType::DVBT:
- return settings.dvbt().frequency;
- case FrontendType::ISDBS:
- return settings.isdbs().frequency;
- case FrontendType::ISDBS3:
- return settings.isdbs3().frequency;
- case FrontendType::ISDBT:
- return settings.isdbt().frequency;
- default:
- return 0;
- }
-}
-
-void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig& config,
- uint32_t resetingFreq) {
- switch (config.type) {
- case FrontendType::ANALOG:
- config.settings.analog().frequency = resetingFreq;
- break;
- case FrontendType::ATSC:
- config.settings.atsc().frequency = resetingFreq;
- break;
- case FrontendType::ATSC3:
- config.settings.atsc3().frequency = resetingFreq;
- break;
- case FrontendType::DVBC:
- config.settings.dvbc().frequency = resetingFreq;
- break;
- case FrontendType::DVBS:
- config.settings.dvbs().frequency = resetingFreq;
- break;
- case FrontendType::DVBT:
- config.settings.dvbt().frequency = resetingFreq;
- break;
- case FrontendType::ISDBS:
- config.settings.isdbs().frequency = resetingFreq;
- break;
- case FrontendType::ISDBS3:
- config.settings.isdbs3().frequency = resetingFreq;
- break;
- case FrontendType::ISDBT:
- config.settings.isdbt().frequency = resetingFreq;
- break;
- default:
- // do nothing
- return;
- }
-}
-/******************************** End FrontendCallback **********************************/
-
-/******************************** Start FilterCallback **********************************/
-class FilterCallback : public IFilterCallback {
- public:
- virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent) override {
- android::Mutex::Autolock autoLock(mMsgLock);
- // Temprarily we treat the first coming back filter data on the matching pid a success
- // once all of the MQ are cleared, means we got all the expected output
- mFilterEvent = filterEvent;
- readFilterEventData();
- mPidFilterOutputCount++;
- // mFilterIdToMQ.erase(filterEvent.filterId);
-
- // startFilterEventThread(filterEvent);
- mMsgCondition.signal();
- return Void();
- }
-
- virtual Return<void> onFilterStatus(const DemuxFilterStatus /*status*/) override {
- return Void();
- }
-
- void setFilterId(uint32_t filterId) { mFilterId = filterId; }
- void setFilterInterface(sp<IFilter> filter) { mFilter = filter; }
- void setFilterEventType(FilterEventType type) { mFilterEventType = type; }
-
- void testFilterDataOutput();
-
- void startFilterEventThread(DemuxFilterEvent event);
- static void* __threadLoopFilter(void* threadArgs);
- void filterThreadLoop(DemuxFilterEvent& event);
-
- void updateFilterMQ(MQDesc& filterMQDescriptor);
- void updateGoldenOutputMap(string goldenOutputFile);
- bool readFilterEventData();
- bool dumpAvData(DemuxFilterMediaEvent event);
-
- private:
- struct FilterThreadArgs {
- FilterCallback* user;
- DemuxFilterEvent event;
- };
- uint16_t mDataLength = 0;
- std::vector<uint8_t> mDataOutputBuffer;
-
- string mFilterIdToGoldenOutput;
-
- uint32_t mFilterId;
- sp<IFilter> mFilter;
- FilterEventType mFilterEventType;
- std::unique_ptr<FilterMQ> mFilterMQ;
- EventFlag* mFilterMQEventFlag;
- DemuxFilterEvent mFilterEvent;
-
- android::Mutex mMsgLock;
- android::Mutex mFilterOutputLock;
- android::Condition mMsgCondition;
- android::Condition mFilterOutputCondition;
-
- pthread_t mFilterThread;
-
- int mPidFilterOutputCount = 0;
-};
-
-void FilterCallback::startFilterEventThread(DemuxFilterEvent event) {
- struct FilterThreadArgs* threadArgs =
- (struct FilterThreadArgs*)malloc(sizeof(struct FilterThreadArgs));
- threadArgs->user = this;
- threadArgs->event = event;
-
- pthread_create(&mFilterThread, NULL, __threadLoopFilter, (void*)threadArgs);
- pthread_setname_np(mFilterThread, "test_playback_input_loop");
-}
-
-void FilterCallback::testFilterDataOutput() {
- android::Mutex::Autolock autoLock(mMsgLock);
- while (mPidFilterOutputCount < 1) {
- if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
- EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
- return;
- }
- }
- mPidFilterOutputCount = 0;
- ALOGW("[vts] pass and stop");
-}
-
-void FilterCallback::updateFilterMQ(MQDesc& filterMQDescriptor) {
- mFilterMQ = std::make_unique<FilterMQ>(filterMQDescriptor, true /* resetPointers */);
- EXPECT_TRUE(mFilterMQ);
- EXPECT_TRUE(EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterMQEventFlag) ==
- android::OK);
-}
-
-void FilterCallback::updateGoldenOutputMap(string goldenOutputFile) {
- mFilterIdToGoldenOutput = goldenOutputFile;
-}
-
-void* FilterCallback::__threadLoopFilter(void* threadArgs) {
- FilterCallback* const self =
- static_cast<FilterCallback*>(((struct FilterThreadArgs*)threadArgs)->user);
- self->filterThreadLoop(((struct FilterThreadArgs*)threadArgs)->event);
- return 0;
-}
-
-void FilterCallback::filterThreadLoop(DemuxFilterEvent& /* event */) {
- android::Mutex::Autolock autoLock(mFilterOutputLock);
- // Read from mFilterMQ[event.filterId] per event and filter type
-
- // Assemble to filterOutput[filterId]
-
- // check if filterOutput[filterId] matches goldenOutput[filterId]
-
- // If match, remove filterId entry from MQ map
-
- // end thread
-}
-
-bool FilterCallback::readFilterEventData() {
- bool result = false;
- DemuxFilterEvent filterEvent = mFilterEvent;
- ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
- // todo separate filter handlers
- for (int i = 0; i < filterEvent.events.size(); i++) {
- switch (mFilterEventType) {
- case FilterEventType::SECTION:
- mDataLength = filterEvent.events[i].section().dataLength;
- break;
- case FilterEventType::PES:
- mDataLength = filterEvent.events[i].pes().dataLength;
- break;
- case FilterEventType::MEDIA:
- return dumpAvData(filterEvent.events[i].media());
- case FilterEventType::RECORD:
- break;
- case FilterEventType::MMTPRECORD:
- break;
- case FilterEventType::DOWNLOAD:
- break;
- default:
- break;
- }
- // 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(goldenDataOutputBuffer[i] == mDataOutputBuffer[i]) << "data does not match";
- }*/
- }
- mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
- return result;
-}
-
-bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
- uint32_t length = event.dataLength;
- uint64_t dataId = event.avDataId;
- // read data from buffer pointed by a handle
- hidl_handle handle = event.avMemory;
-
- 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 /*offset*/));
- if (buffer == MAP_FAILED) {
- ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
- return false;
- }
- uint8_t output[length + 1];
- memcpy(output, buffer, length);
- // print buffer and check with golden output.
- EXPECT_TRUE(mFilter->releaseAvHandle(handle, dataId) == Result::SUCCESS);
- return true;
-}
-/******************************** End FilterCallback **********************************/
-
/******************************** Start DvrCallback **********************************/
-class DvrCallback : public IDvrCallback {
- public:
- virtual Return<void> onRecordStatus(DemuxFilterStatus status) override {
- ALOGW("[vts] record status %hhu", status);
- switch (status) {
- case DemuxFilterStatus::DATA_READY:
- break;
- case DemuxFilterStatus::LOW_WATER:
- break;
- case DemuxFilterStatus::HIGH_WATER:
- case DemuxFilterStatus::OVERFLOW:
- ALOGW("[vts] record overflow. Flushing");
- break;
- }
- return Void();
- }
-
- virtual Return<void> onPlaybackStatus(PlaybackStatus status) override {
- // android::Mutex::Autolock autoLock(mMsgLock);
- ALOGW("[vts] playback status %d", status);
- switch (status) {
- case PlaybackStatus::SPACE_EMPTY:
- case PlaybackStatus::SPACE_ALMOST_EMPTY:
- ALOGW("[vts] keep playback inputing %d", status);
- mKeepWritingPlaybackFMQ = true;
- break;
- case PlaybackStatus::SPACE_ALMOST_FULL:
- case PlaybackStatus::SPACE_FULL:
- ALOGW("[vts] stop playback inputing %d", status);
- mKeepWritingPlaybackFMQ = false;
- break;
- }
- return Void();
- }
-
- void testFilterDataOutput();
- void stopPlaybackThread();
- void testRecordOutput();
- void stopRecordThread();
-
- void startPlaybackInputThread(PlaybackConf playbackConf, MQDesc& playbackMQDescriptor);
- void startRecordOutputThread(RecordSettings recordSetting, MQDesc& recordMQDescriptor);
- static void* __threadLoopPlayback(void* threadArgs);
- static void* __threadLoopRecord(void* threadArgs);
- void playbackThreadLoop(PlaybackConf* playbackConf, bool* keepWritingPlaybackFMQ);
- void recordThreadLoop(RecordSettings* recordSetting, bool* keepWritingPlaybackFMQ);
-
- bool readRecordFMQ();
-
- private:
- struct PlaybackThreadArgs {
- DvrCallback* user;
- PlaybackConf* playbackConf;
- bool* keepWritingPlaybackFMQ;
- };
- struct RecordThreadArgs {
- DvrCallback* user;
- RecordSettings* recordSetting;
- bool* keepReadingRecordFMQ;
- };
- uint16_t mDataLength = 0;
- std::vector<uint8_t> mDataOutputBuffer;
-
- std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterMQ;
- std::unique_ptr<FilterMQ> mPlaybackMQ;
- std::unique_ptr<FilterMQ> mRecordMQ;
- std::map<uint32_t, EventFlag*> mFilterMQEventFlag;
-
- android::Mutex mMsgLock;
- android::Mutex mPlaybackThreadLock;
- android::Mutex mRecordThreadLock;
- android::Condition mMsgCondition;
-
- bool mKeepWritingPlaybackFMQ = true;
- bool mKeepReadingRecordFMQ = true;
- bool mPlaybackThreadRunning;
- bool mRecordThreadRunning;
- pthread_t mPlaybackThread;
- pthread_t mRecordThread;
-
- int mPidFilterOutputCount = 0;
-};
-
void DvrCallback::startPlaybackInputThread(PlaybackConf playbackConf,
MQDesc& playbackMQDescriptor) {
mPlaybackMQ = std::make_unique<FilterMQ>(playbackMQDescriptor, true /* resetPointers */);
@@ -809,305 +190,9 @@ void DvrCallback::stopRecordThread() {
}
/********************************** End DvrCallback ************************************/
-/***************************** Start Test Implementation ******************************/
-class TunerHidlTest : public testing::TestWithParam<std::string> {
- public:
- virtual void SetUp() override {
- mService = ITuner::getService(GetParam());
- ASSERT_NE(mService, nullptr);
- initFrontendConfig();
- initFrontendScanConfig();
- initFilterConfig();
- }
-
- sp<ITuner> mService;
-
- protected:
- static AssertionResult failure() { return ::testing::AssertionFailure(); }
-
- static AssertionResult success() { return ::testing::AssertionSuccess(); }
-
- static void description(const std::string& description) {
- RecordProperty("description", description);
- }
-
- sp<IFrontend> mFrontend;
- FrontendInfo mFrontendInfo;
- sp<FrontendCallback> mFrontendCallback;
- sp<IDescrambler> mDescrambler;
- sp<IDemux> mDemux;
- sp<IDvr> mDvr;
- sp<IFilter> mFilter;
- std::map<uint32_t, sp<IFilter>> mFilters;
- std::map<uint32_t, sp<FilterCallback>> mFilterCallbacks;
-
- sp<FilterCallback> mFilterCallback;
- sp<DvrCallback> mDvrCallback;
- MQDesc mFilterMQDescriptor;
- MQDesc mDvrMQDescriptor;
- MQDesc mRecordMQDescriptor;
- vector<uint32_t> mUsedFilterIds;
- hidl_vec<FrontendId> mFeIds;
-
- uint32_t mDemuxId;
- uint32_t mFilterId = -1;
-
- pthread_t mPlaybackshread;
- bool mPlaybackThreadRunning;
-
- AssertionResult getFrontendIds();
- AssertionResult getFrontendInfo(uint32_t frontendId);
- AssertionResult openFrontendById(uint32_t frontendId);
- AssertionResult setFrontendCallback();
- AssertionResult scanFrontend(FrontendConfig config, FrontendScanType type);
- AssertionResult stopScanFrontend();
- AssertionResult tuneFrontend(FrontendConfig config);
- AssertionResult stopTuneFrontend();
- AssertionResult closeFrontend();
-
- AssertionResult openDemux();
- AssertionResult setDemuxFrontendDataSource(uint32_t frontendId);
- AssertionResult closeDemux();
-
- AssertionResult openDvrInDemux(DvrType type);
- AssertionResult configDvr(DvrSettings setting);
- AssertionResult getDvrMQDescriptor();
-
- AssertionResult openFilterInDemux(DemuxFilterType type);
- AssertionResult getNewlyOpenedFilterId(uint32_t& filterId);
- AssertionResult configFilter(DemuxFilterSettings setting, uint32_t filterId);
- AssertionResult getFilterMQDescriptor(uint32_t filterId);
- AssertionResult startFilter(uint32_t filterId);
- AssertionResult stopFilter(uint32_t filterId);
- AssertionResult closeFilter(uint32_t filterId);
-
- AssertionResult createDescrambler();
- AssertionResult closeDescrambler();
-
- AssertionResult playbackDataFlowTest(vector<FilterConfig> filterConf, PlaybackConf playbackConf,
- vector<string> goldenOutputFiles);
- AssertionResult recordDataFlowTest(vector<FilterConfig> filterConf,
- RecordSettings recordSetting,
- vector<string> goldenOutputFiles);
- AssertionResult broadcastDataFlowTest(vector<string> goldenOutputFiles);
-
- void broadcastSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf);
- void getFrontendIdByType(FrontendType feType, uint32_t& feId);
- void scanTest(FrontendConfig frontend, FrontendScanType type);
-
- FilterEventType getFilterEventType(DemuxFilterType type);
-};
-
-/*========================== Start Frontend APIs Tests Implementation ==========================*/
-AssertionResult TunerHidlTest::getFrontendIds() {
- Result status;
- mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
- status = result;
- mFeIds = frontendIds;
- });
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult TunerHidlTest::getFrontendInfo(uint32_t frontendId) {
- Result status;
- mService->getFrontendInfo(frontendId, [&](Result result, const FrontendInfo& frontendInfo) {
- mFrontendInfo = frontendInfo;
- status = result;
- });
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult TunerHidlTest::openFrontendById(uint32_t frontendId) {
- Result status;
- mService->openFrontendById(frontendId, [&](Result result, const sp<IFrontend>& frontend) {
- mFrontend = frontend;
- status = result;
- });
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult TunerHidlTest::setFrontendCallback() {
- EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
- mFrontendCallback = new FrontendCallback();
- auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
- return AssertionResult(callbackStatus.isOk());
-}
-
-AssertionResult TunerHidlTest::scanFrontend(FrontendConfig config, FrontendScanType type) {
- EXPECT_TRUE(mFrontendCallback)
- << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
-
- EXPECT_TRUE(mFrontendInfo.type == config.type)
- << "FrontendConfig does not match the frontend info of the given id.";
-
- mFrontendCallback->scanTest(mFrontend, config, type);
- return AssertionResult(true);
-}
-
-AssertionResult TunerHidlTest::stopScanFrontend() {
- EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
- Result status;
- status = mFrontend->stopScan();
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult TunerHidlTest::tuneFrontend(FrontendConfig config) {
- EXPECT_TRUE(mFrontendCallback)
- << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
-
- EXPECT_TRUE(mFrontendInfo.type == config.type)
- << "FrontendConfig does not match the frontend info of the given id.";
-
- mFrontendCallback->tuneTestOnLock(mFrontend, config.settings);
- return AssertionResult(true);
-}
-
-AssertionResult TunerHidlTest::stopTuneFrontend() {
- EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
- Result status;
- status = mFrontend->stopTune();
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult TunerHidlTest::closeFrontend() {
- EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
- Result status;
- status = mFrontend->close();
- mFrontend = nullptr;
- mFrontendCallback = nullptr;
- return AssertionResult(status == Result::SUCCESS);
-}
-/*=========================== End Frontend APIs Tests Implementation ===========================*/
-
-/*============================ Start Demux APIs Tests Implementation ============================*/
-AssertionResult TunerHidlTest::openDemux() {
- Result status;
- mService->openDemux([&](Result result, uint32_t demuxId, const sp<IDemux>& demux) {
- mDemux = demux;
- mDemuxId = demuxId;
- status = result;
- });
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult TunerHidlTest::setDemuxFrontendDataSource(uint32_t frontendId) {
- EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
- auto status = mDemux->setFrontendDataSource(frontendId);
- return AssertionResult(status.isOk());
-}
-
-AssertionResult TunerHidlTest::closeDemux() {
- EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- auto status = mDemux->close();
- mDemux = nullptr;
- return AssertionResult(status.isOk());
-}
-
-AssertionResult TunerHidlTest::openFilterInDemux(DemuxFilterType type) {
- Result status;
- EXPECT_TRUE(mDemux) << "Test with openDemux first.";
-
- // Create demux callback
- mFilterCallback = new FilterCallback();
-
- // Add filter to the local demux
- mDemux->openFilter(type, FMQ_SIZE_16M, mFilterCallback,
- [&](Result result, const sp<IFilter>& filter) {
- mFilter = filter;
- status = result;
- });
-
- if (status == Result::SUCCESS) {
- mFilterCallback->setFilterEventType(getFilterEventType(type));
- }
-
- return AssertionResult(status == Result::SUCCESS);
-}
-/*============================ End Demux APIs Tests Implementation ============================*/
-
-/*=========================== Start Filter APIs Tests Implementation ===========================*/
-AssertionResult TunerHidlTest::getNewlyOpenedFilterId(uint32_t& filterId) {
- Result status;
- EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- EXPECT_TRUE(mFilter) << "Test with openFilterInDemux first.";
- EXPECT_TRUE(mFilterCallback) << "Test with openFilterInDemux first.";
-
- mFilter->getId([&](Result result, uint32_t filterId) {
- mFilterId = filterId;
- status = result;
- });
-
- if (status == Result::SUCCESS) {
- mFilterCallback->setFilterId(mFilterId);
- mFilterCallback->setFilterInterface(mFilter);
- mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
- mFilters[mFilterId] = mFilter;
- mFilterCallbacks[mFilterId] = mFilterCallback;
- filterId = mFilterId;
- }
-
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult TunerHidlTest::configFilter(DemuxFilterSettings setting, uint32_t filterId) {
- Result status;
- EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
- status = mFilters[filterId]->configure(setting);
-
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult TunerHidlTest::getFilterMQDescriptor(uint32_t filterId) {
- Result status;
- EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
- EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
-
- mFilter->getQueueDesc([&](Result result, const MQDesc& filterMQDesc) {
- mFilterMQDescriptor = filterMQDesc;
- status = result;
- });
-
- if (status == Result::SUCCESS) {
- mFilterCallbacks[filterId]->updateFilterMQ(mFilterMQDescriptor);
- }
-
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult TunerHidlTest::startFilter(uint32_t filterId) {
- EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
- Result status = mFilters[filterId]->start();
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult TunerHidlTest::stopFilter(uint32_t filterId) {
- EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
- Result status = mFilters[filterId]->stop();
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult TunerHidlTest::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;
- }
- }
- mFilterCallbacks.erase(filterId);
- mFilters.erase(filterId);
- }
- return AssertionResult(status == Result::SUCCESS);
-}
-/*=========================== End Filter APIs Tests Implementation ===========================*/
-
/*======================== Start Descrambler APIs Tests Implementation ========================*/
AssertionResult TunerHidlTest::createDescrambler() {
Result status;
- EXPECT_TRUE(mDemux) << "Test with openDemux first.";
mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) {
mDescrambler = descrambler;
status = result;
@@ -1141,7 +226,6 @@ AssertionResult TunerHidlTest::closeDescrambler() {
/*============================ Start Dvr APIs Tests Implementation ============================*/
AssertionResult TunerHidlTest::openDvrInDemux(DvrType type) {
Result status;
- EXPECT_TRUE(mDemux) << "Test with openDemux first.";
// Create dvr callback
mDvrCallback = new DvrCallback();
@@ -1162,7 +246,6 @@ AssertionResult TunerHidlTest::configDvr(DvrSettings setting) {
AssertionResult TunerHidlTest::getDvrMQDescriptor() {
Result status;
- EXPECT_TRUE(mDemux) << "Test with openDemux first.";
EXPECT_TRUE(mDvr) << "Test with openDvr first.";
mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
@@ -1176,13 +259,10 @@ AssertionResult TunerHidlTest::getDvrMQDescriptor() {
/*========================== Start Data Flow Tests Implementation ==========================*/
AssertionResult TunerHidlTest::broadcastDataFlowTest(vector<string> /*goldenOutputFiles*/) {
- EXPECT_TRUE(mFrontend) << "Test with openFilterInDemux first.";
- EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- EXPECT_TRUE(mFilterCallback) << "Test with getFilterMQDescriptor first.";
-
// Data Verify Module
std::map<uint32_t, sp<FilterCallback>>::iterator it;
- for (it = mFilterCallbacks.begin(); it != mFilterCallbacks.end(); it++) {
+ std::map<uint32_t, sp<FilterCallback>> filterCallbacks = mFilterTests.getFilterCallbacks();
+ for (it = filterCallbacks.begin(); it != filterCallbacks.end(); it++) {
it->second->testFilterDataOutput();
}
return success();
@@ -1334,160 +414,89 @@ AssertionResult TunerHidlTest::recordDataFlowTest(vector<FilterConf> filterConf,
/*========================= End Data Flow Tests Implementation =========================*/
/*================================= Start Test Module =================================*/
-void TunerHidlTest::getFrontendIdByType(FrontendType feType, uint32_t& feId) {
- ASSERT_TRUE(getFrontendIds());
- ASSERT_TRUE(mFeIds.size() > 0);
- for (size_t i = 0; i < mFeIds.size(); i++) {
- ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
- if (mFrontendInfo.type != feType) {
- continue;
- }
- feId = mFeIds[i];
- return;
- }
- feId = INVALID_ID;
-}
-
void TunerHidlTest::broadcastSingleFilterTest(FilterConfig filterConf,
FrontendConfig frontendConf) {
uint32_t feId;
- getFrontendIdByType(frontendConf.type, feId);
+ mFrontendTests.getFrontendIdByType(frontendConf.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.
return;
}
- ASSERT_TRUE(openFrontendById(feId));
- ASSERT_TRUE(setFrontendCallback());
- ASSERT_TRUE(openDemux());
- ASSERT_TRUE(setDemuxFrontendDataSource(feId));
- ASSERT_TRUE(openFilterInDemux(filterConf.type));
+ ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+ ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+ ASSERT_TRUE(mDemuxTests.openDemux(mDemux, mDemuxId));
+ mFilterTests.setDemux(mDemux);
+ ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type));
uint32_t filterId;
- ASSERT_TRUE(getNewlyOpenedFilterId(filterId));
- ASSERT_TRUE(configFilter(filterConf.setting, filterId));
- ASSERT_TRUE(getFilterMQDescriptor(filterId));
- ASSERT_TRUE(startFilter(filterId));
+ ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
+ ASSERT_TRUE(mFilterTests.configFilter(filterConf.setting, filterId));
+ ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+ ASSERT_TRUE(mFilterTests.startFilter(filterId));
// tune test
- ASSERT_TRUE(tuneFrontend(frontendConf));
+ ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf));
// broadcast data flow test
ASSERT_TRUE(broadcastDataFlowTest(goldenOutputFiles));
- ASSERT_TRUE(stopTuneFrontend());
- ASSERT_TRUE(stopFilter(filterId));
- ASSERT_TRUE(closeFilter(filterId));
- ASSERT_TRUE(closeDemux());
- ASSERT_TRUE(closeFrontend());
-}
-
-void TunerHidlTest::scanTest(FrontendConfig frontendConf, FrontendScanType scanType) {
- uint32_t feId;
- getFrontendIdByType(frontendConf.type, feId);
- ASSERT_TRUE(feId != INVALID_ID);
- ASSERT_TRUE(openFrontendById(feId));
- ASSERT_TRUE(setFrontendCallback());
- ASSERT_TRUE(scanFrontend(frontendConf, scanType));
- ASSERT_TRUE(stopScanFrontend());
- ASSERT_TRUE(closeFrontend());
+ ASSERT_TRUE(mFrontendTests.stopTuneFrontend());
+ ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+ ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+ ASSERT_TRUE(mFrontendTests.closeFrontend());
}
/*================================== End Test Module ==================================*/
-
-/*=============================== Start Helper Functions ===============================*/
-FilterEventType TunerHidlTest::getFilterEventType(DemuxFilterType type) {
- FilterEventType eventType = FilterEventType::UNDEFINED;
- switch (type.mainType) {
- case DemuxFilterMainType::TS:
- switch (type.subType.tsFilterType()) {
- case DemuxTsFilterType::UNDEFINED:
- break;
- case DemuxTsFilterType::SECTION:
- eventType = FilterEventType::SECTION;
- break;
- case DemuxTsFilterType::PES:
- eventType = FilterEventType::PES;
- break;
- case DemuxTsFilterType::TS:
- break;
- case DemuxTsFilterType::AUDIO:
- case DemuxTsFilterType::VIDEO:
- eventType = FilterEventType::MEDIA;
- break;
- case DemuxTsFilterType::PCR:
- break;
- case DemuxTsFilterType::RECORD:
- eventType = FilterEventType::RECORD;
- break;
- case DemuxTsFilterType::TEMI:
- eventType = FilterEventType::TEMI;
- break;
- }
- break;
- case DemuxFilterMainType::MMTP:
- /*mmtpSettings*/
- break;
- case DemuxFilterMainType::IP:
- /*ipSettings*/
- break;
- case DemuxFilterMainType::TLV:
- /*tlvSettings*/
- break;
- case DemuxFilterMainType::ALP:
- /*alpSettings*/
- break;
- default:
- break;
- }
- return eventType;
-}
-/*============================== End Helper Functions ==============================*/
/***************************** End Test Implementation *****************************/
/******************************** Start Test Entry **********************************/
-/*============================== Start Frontend Tests ==============================*/
-TEST_P(TunerHidlTest, TuneFrontend) {
+TEST_P(TunerFrontendHidlTest, TuneFrontend) {
description("Tune one Frontend with specific setting and check Lock event");
- uint32_t feId;
- getFrontendIdByType(frontendArray[DVBT].type, feId);
- ASSERT_TRUE(feId != INVALID_ID);
- ASSERT_TRUE(openFrontendById(feId));
- ASSERT_TRUE(setFrontendCallback());
- ASSERT_TRUE(tuneFrontend(frontendArray[DVBT]));
- ASSERT_TRUE(stopTuneFrontend());
- ASSERT_TRUE(closeFrontend());
+ mFrontendTests.tuneTest(frontendArray[DVBT]);
}
-TEST_P(TunerHidlTest, AutoScanFrontend) {
+TEST_P(TunerFrontendHidlTest, AutoScanFrontend) {
description("Run an auto frontend scan with specific setting and check lock scanMessage");
- scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_AUTO);
+ mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_AUTO);
}
-TEST_P(TunerHidlTest, BlindScanFrontend) {
+TEST_P(TunerFrontendHidlTest, BlindScanFrontend) {
description("Run an blind frontend scan with specific setting and check lock scanMessage");
- scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_BLIND);
+ mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_BLIND);
}
-/*=============================== End Frontend Tests ===============================*/
-/*============================ Start Demux/Filter Tests ============================*/
-TEST_P(TunerHidlTest, StartFilterInDemux) {
+TEST_P(TunerDemuxHidlTest, openDemux) {
+ description("Open and close a Demux.");
+ uint32_t feId;
+ mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
+ ASSERT_TRUE(feId != INVALID_ID);
+ ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+ ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+ ASSERT_TRUE(mDemuxTests.openDemux(mDemux, mDemuxId));
+ ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+}
+
+TEST_P(TunerFilterHidlTest, StartFilterInDemux) {
description("Open and start a filter in Demux.");
uint32_t feId;
- getFrontendIdByType(frontendArray[DVBT].type, feId);
+ mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
ASSERT_TRUE(feId != INVALID_ID);
- ASSERT_TRUE(openFrontendById(feId));
- ASSERT_TRUE(setFrontendCallback());
- ASSERT_TRUE(openDemux());
- ASSERT_TRUE(setDemuxFrontendDataSource(feId));
- ASSERT_TRUE(openFilterInDemux(filterArray[TS_VIDEO0].type));
+ ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+ ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+ ASSERT_TRUE(mDemuxTests.openDemux(mDemux, mDemuxId));
+ mFilterTests.setDemux(mDemux);
+ ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_VIDEO0].type));
uint32_t filterId;
- ASSERT_TRUE(getNewlyOpenedFilterId(filterId));
- ASSERT_TRUE(configFilter(filterArray[TS_VIDEO0].setting, filterId));
- ASSERT_TRUE(getFilterMQDescriptor(filterId));
- ASSERT_TRUE(startFilter(filterId));
- ASSERT_TRUE(stopFilter(filterId));
- ASSERT_TRUE(closeFilter(filterId));
- ASSERT_TRUE(closeDemux());
- ASSERT_TRUE(closeFrontend());
+ ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
+ ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_VIDEO0].setting, filterId));
+ ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+ ASSERT_TRUE(mFilterTests.startFilter(filterId));
+ ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+ ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+ ASSERT_TRUE(mFrontendTests.closeFrontend());
}
-/*============================ End Demux/Filter Tests ============================*/
/*============================ Start Descrambler Tests ============================*/
/*
@@ -1614,9 +623,23 @@ TEST_P(TunerHidlTest, RecordDataFlowWithTsRecordFilterTest) {
}*/
/*============================== End Data Flow Tests ==============================*/
/******************************** End Test Entry **********************************/
-} // namespace
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, TunerFrontendHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+ android::hardware::PrintInstanceNameToString);
INSTANTIATE_TEST_SUITE_P(
PerInstance, TunerHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, TunerDemuxHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+ android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, TunerFilterHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+ android::hardware::PrintInstanceNameToString);
+} // namespace
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
new file mode 100644
index 0000000000..f17704774c
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/tv/tuner/1.0/IDescrambler.h>
+#include <android/hardware/tv/tuner/1.0/IDvr.h>
+#include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
+#include <fstream>
+#include <iostream>
+
+#include "DemuxTests.h"
+#include "FilterTests.h"
+#include "FrontendTests.h"
+
+using android::hardware::tv::tuner::V1_0::DataFormat;
+using android::hardware::tv::tuner::V1_0::DvrSettings;
+using android::hardware::tv::tuner::V1_0::DvrType;
+using android::hardware::tv::tuner::V1_0::IDescrambler;
+using android::hardware::tv::tuner::V1_0::IDvr;
+using android::hardware::tv::tuner::V1_0::IDvrCallback;
+using android::hardware::tv::tuner::V1_0::PlaybackSettings;
+using android::hardware::tv::tuner::V1_0::PlaybackStatus;
+using android::hardware::tv::tuner::V1_0::RecordSettings;
+using android::hardware::tv::tuner::V1_0::RecordStatus;
+
+struct PlaybackConf {
+ string inputDataFile;
+ PlaybackSettings setting;
+};
+
+static AssertionResult failure() {
+ return ::testing::AssertionFailure();
+}
+
+static AssertionResult success() {
+ return ::testing::AssertionSuccess();
+}
+
+namespace {
+
+class DvrCallback : public IDvrCallback {
+ public:
+ virtual Return<void> onRecordStatus(DemuxFilterStatus status) override {
+ ALOGW("[vts] record status %hhu", status);
+ switch (status) {
+ case DemuxFilterStatus::DATA_READY:
+ break;
+ case DemuxFilterStatus::LOW_WATER:
+ break;
+ case DemuxFilterStatus::HIGH_WATER:
+ case DemuxFilterStatus::OVERFLOW:
+ ALOGW("[vts] record overflow. Flushing");
+ break;
+ }
+ return Void();
+ }
+
+ virtual Return<void> onPlaybackStatus(PlaybackStatus status) override {
+ // android::Mutex::Autolock autoLock(mMsgLock);
+ ALOGW("[vts] playback status %d", status);
+ switch (status) {
+ case PlaybackStatus::SPACE_EMPTY:
+ case PlaybackStatus::SPACE_ALMOST_EMPTY:
+ ALOGW("[vts] keep playback inputing %d", status);
+ mKeepWritingPlaybackFMQ = true;
+ break;
+ case PlaybackStatus::SPACE_ALMOST_FULL:
+ case PlaybackStatus::SPACE_FULL:
+ ALOGW("[vts] stop playback inputing %d", status);
+ mKeepWritingPlaybackFMQ = false;
+ break;
+ }
+ return Void();
+ }
+
+ void testFilterDataOutput();
+ void stopPlaybackThread();
+ void testRecordOutput();
+ void stopRecordThread();
+
+ void startPlaybackInputThread(PlaybackConf playbackConf, MQDesc& playbackMQDescriptor);
+ void startRecordOutputThread(RecordSettings recordSetting, MQDesc& recordMQDescriptor);
+ static void* __threadLoopPlayback(void* threadArgs);
+ static void* __threadLoopRecord(void* threadArgs);
+ void playbackThreadLoop(PlaybackConf* playbackConf, bool* keepWritingPlaybackFMQ);
+ void recordThreadLoop(RecordSettings* recordSetting, bool* keepWritingPlaybackFMQ);
+
+ bool readRecordFMQ();
+
+ private:
+ struct PlaybackThreadArgs {
+ DvrCallback* user;
+ PlaybackConf* playbackConf;
+ bool* keepWritingPlaybackFMQ;
+ };
+ struct RecordThreadArgs {
+ DvrCallback* user;
+ RecordSettings* recordSetting;
+ bool* keepReadingRecordFMQ;
+ };
+ uint16_t mDataLength = 0;
+ std::vector<uint8_t> mDataOutputBuffer;
+
+ std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterMQ;
+ std::unique_ptr<FilterMQ> mPlaybackMQ;
+ std::unique_ptr<FilterMQ> mRecordMQ;
+ std::map<uint32_t, EventFlag*> mFilterMQEventFlag;
+
+ android::Mutex mMsgLock;
+ android::Mutex mPlaybackThreadLock;
+ android::Mutex mRecordThreadLock;
+ android::Condition mMsgCondition;
+
+ bool mKeepWritingPlaybackFMQ = true;
+ bool mKeepReadingRecordFMQ = true;
+ bool mPlaybackThreadRunning;
+ bool mRecordThreadRunning;
+ pthread_t mPlaybackThread;
+ pthread_t mRecordThread;
+
+ int mPidFilterOutputCount = 0;
+};
+
+class TunerFrontendHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mService = ITuner::getService(GetParam());
+ ASSERT_NE(mService, nullptr);
+ initFrontendConfig();
+ initFrontendScanConfig();
+
+ mFrontendTests.setService(mService);
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ sp<ITuner> mService;
+ FrontendTests mFrontendTests;
+};
+
+class TunerDemuxHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mService = ITuner::getService(GetParam());
+ ASSERT_NE(mService, nullptr);
+ initFrontendConfig();
+ initFrontendScanConfig();
+ initFilterConfig();
+
+ mFrontendTests.setService(mService);
+ mDemuxTests.setService(mService);
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ sp<ITuner> mService;
+ FrontendTests mFrontendTests;
+ DemuxTests mDemuxTests;
+ sp<IDemux> mDemux;
+ uint32_t mDemuxId;
+};
+
+class TunerFilterHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mService = ITuner::getService(GetParam());
+ ASSERT_NE(mService, nullptr);
+ initFrontendConfig();
+ initFrontendScanConfig();
+ initFilterConfig();
+
+ mFrontendTests.setService(mService);
+ mDemuxTests.setService(mService);
+ mFilterTests.setService(mService);
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ sp<ITuner> mService;
+ FrontendTests mFrontendTests;
+ DemuxTests mDemuxTests;
+ FilterTests mFilterTests;
+ sp<IDemux> mDemux;
+ uint32_t mDemuxId;
+};
+
+class TunerHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ sp<ITuner> mService;
+ FrontendTests mFrontendTests;
+ DemuxTests mDemuxTests;
+ FilterTests mFilterTests;
+
+ virtual void SetUp() override {
+ mService = ITuner::getService(GetParam());
+ ASSERT_NE(mService, nullptr);
+ initFrontendConfig();
+ initFrontendScanConfig();
+ initFilterConfig();
+
+ mFrontendTests.setService(mService);
+ mDemuxTests.setService(mService);
+ mFilterTests.setService(mService);
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ sp<IDescrambler> mDescrambler;
+ sp<IDvr> mDvr;
+ sp<IDemux> mDemux;
+ uint32_t mDemuxId;
+
+ sp<DvrCallback> mDvrCallback;
+ MQDesc mDvrMQDescriptor;
+ MQDesc mRecordMQDescriptor;
+
+ pthread_t mPlaybackshread;
+ bool mPlaybackThreadRunning;
+
+ AssertionResult openDvrInDemux(DvrType type);
+ AssertionResult configDvr(DvrSettings setting);
+ AssertionResult getDvrMQDescriptor();
+
+ AssertionResult createDescrambler();
+ AssertionResult closeDescrambler();
+
+ AssertionResult playbackDataFlowTest(vector<FilterConfig> filterConf, PlaybackConf playbackConf,
+ vector<string> goldenOutputFiles);
+ AssertionResult recordDataFlowTest(vector<FilterConfig> filterConf,
+ RecordSettings recordSetting,
+ vector<string> goldenOutputFiles);
+ AssertionResult broadcastDataFlowTest(vector<string> goldenOutputFiles);
+
+ void broadcastSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf);
+};
+} // namespace \ No newline at end of file
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index 10c60142ba..538773a209 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -38,6 +38,8 @@ using android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
using android::hardware::tv::tuner::V1_0::FrontendSettings;
using android::hardware::tv::tuner::V1_0::FrontendType;
+using namespace std;
+
typedef enum {
TS_VIDEO0,
TS_VIDEO1,