Separate Demux and Filter fixture classes from the Tuner HAL VTS target
test

Test: atest VtsHalTvTunerV1_0TargetTest
Bug: 150953857
Change-Id: I373c3ba56ab80e02c79d24f865a956dae4b44226
diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
index b4dbda7..448575e 100644
--- a/tv/tuner/1.0/vts/functional/Android.bp
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -20,6 +20,8 @@
     srcs: [
         "VtsHalTvTunerV1_0TargetTest.cpp",
         "FrontendTests.cpp",
+        "DemuxTests.cpp",
+        "FilterTests.cpp",
     ],
     static_libs: [
         "android.hardware.tv.tuner@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 0000000..b1d8a0a
--- /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 0000000..f405a79
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.h
@@ -0,0 +1,57 @@
+/*
+ * 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 <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/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;
+};
\ No newline at end of file
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 0000000..82e955d
--- /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 0000000..eab963b
--- /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 <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#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;
+
+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;
+};
\ No newline at end of file
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.cpp b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
index 5bc3705..fc5071c 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
@@ -307,4 +307,4 @@
     ASSERT_TRUE(scanFrontend(frontendConf, scanType));
     ASSERT_TRUE(stopScanFrontend());
     ASSERT_TRUE(closeFrontend());
-}
\ No newline at end of file
+}
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.h b/tv/tuner/1.0/vts/functional/FrontendTests.h
index 5aa6e15..701be82 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.h
@@ -45,10 +45,7 @@
 using android::Mutex;
 using android::sp;
 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::Return;
 using android::hardware::Void;
 using android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 59c9479..d836c26 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -17,119 +17,6 @@
 #include "VtsHalTvTunerV1_0TargetTest.h"
 
 namespace {
-/******************************** Start FilterCallback **********************************/
-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 **********************************/
 void DvrCallback::startPlaybackInputThread(PlaybackConf playbackConf,
@@ -303,134 +190,9 @@
 }
 /********************************** End DvrCallback ************************************/
 
-/*============================ 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.";
-    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;
@@ -464,7 +226,6 @@
 /*============================ 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();
@@ -485,7 +246,6 @@
 
 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) {
@@ -499,12 +259,10 @@
 
 /*========================== Start Data Flow Tests Implementation ==========================*/
 AssertionResult TunerHidlTest::broadcastDataFlowTest(vector<string> /*goldenOutputFiles*/) {
-    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();
@@ -668,74 +426,26 @@
     }
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
-    ASSERT_TRUE(openDemux());
-    ASSERT_TRUE(setDemuxFrontendDataSource(feId));
-    ASSERT_TRUE(openFilterInDemux(filterConf.type));
+    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(mFrontendTests.tuneFrontend(frontendConf));
     // broadcast data flow test
     ASSERT_TRUE(broadcastDataFlowTest(goldenOutputFiles));
     ASSERT_TRUE(mFrontendTests.stopTuneFrontend());
-    ASSERT_TRUE(stopFilter(filterId));
-    ASSERT_TRUE(closeFilter(filterId));
-    ASSERT_TRUE(closeDemux());
+    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 **********************************/
@@ -754,28 +464,39 @@
     mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_BLIND);
 }
 
-/*============================ 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;
     mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
-    ASSERT_TRUE(openDemux());
-    ASSERT_TRUE(setDemuxFrontendDataSource(feId));
-    ASSERT_TRUE(openFilterInDemux(filterArray[TS_VIDEO0].type));
+    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(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 ============================*/
 /*
@@ -911,4 +632,14 @@
         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
index 4d6715e..f177047 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -14,70 +14,27 @@
  * limitations under the License.
  */
 
-#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/types.h>
-#include <binder/MemoryDealer.h>
-#include <fmq/MessageQueue.h>
 #include <fstream>
 #include <iostream>
-#include <map>
 
+#include "DemuxTests.h"
+#include "FilterTests.h"
 #include "FrontendTests.h"
 
-using android::hardware::EventFlag;
-using android::hardware::kSynchronizedReadWrite;
-using android::hardware::MessageQueue;
-using android::hardware::MQDescriptorSync;
 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::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::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 FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-using MQDesc = MQDescriptorSync<uint8_t>;
-
-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;
@@ -93,68 +50,6 @@
 
 namespace {
 
-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 DvrCallback : public IDvrCallback {
   public:
     virtual Return<void> onRecordStatus(DemuxFilterStatus status) override {
@@ -240,9 +135,6 @@
 
 class TunerFrontendHidlTest : public testing::TestWithParam<std::string> {
   public:
-    sp<ITuner> mService;
-    FrontendTests mFrontendTests;
-
     virtual void SetUp() override {
         mService = ITuner::getService(GetParam());
         ASSERT_NE(mService, nullptr);
@@ -256,12 +148,69 @@
     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());
@@ -271,6 +220,8 @@
         initFilterConfig();
 
         mFrontendTests.setService(mService);
+        mDemuxTests.setService(mService);
+        mFilterTests.setService(mService);
     }
 
   protected:
@@ -279,43 +230,21 @@
     }
 
     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<IDemux> mDemux;
+    uint32_t mDemuxId;
 
-    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 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();
 
@@ -327,7 +256,5 @@
     AssertionResult broadcastDataFlowTest(vector<string> goldenOutputFiles);
 
     void broadcastSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf);
-
-    FilterEventType getFilterEventType(DemuxFilterType type);
 };
 }  // namespace
\ No newline at end of file