Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 149b0871 authored by Patrick Rohr's avatar Patrick Rohr
Browse files

Add VTS for Filter TimeDelayHint

Test: atest VtsHalTvTunerTargetTest
Bug: 183057734
Change-Id: I4a97d81c0100ca4114353ed84335fc1593bff800
parent 80bbf093
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -23,6 +23,33 @@

using ::aidl::android::hardware::common::NativeHandle;

::ndk::ScopedAStatus FilterCallback::onFilterEvent(const vector<DemuxFilterEvent>& events) {
    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
    readFilterEventsData(events);
    mPidFilterOutputCount++;
    mMsgCondition.signal();

    // HACK: we need to cast the const away as DemuxFilterEvent contains a ScopedFileDescriptor
    // that cannot be copied.
    for (auto&& e : const_cast<std::vector<DemuxFilterEvent>&>(events)) {
        auto it = mFilterEventPromises.find(e.getTag());
        if (it != mFilterEventPromises.cend()) {
            it->second.set_value(std::move(e));
            mFilterEventPromises.erase(it);
        }
    }

    return ::ndk::ScopedAStatus::ok();
}

std::future<DemuxFilterEvent> FilterCallback::getNextFilterEventWithTag(DemuxFilterEvent::Tag tag) {
    // Note: this currently only supports one future per DemuxFilterEvent::Tag.
    mFilterEventPromises[tag] = std::promise<DemuxFilterEvent>();
    return mFilterEventPromises[tag].get_future();
}

void FilterCallback::testFilterDataOutput() {
    android::Mutex::Autolock autoLock(mMsgLock);
    while (mPidFilterOutputCount < 1) {
+6 −9
Original line number Diff line number Diff line
@@ -24,7 +24,9 @@
#include <log/log.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <future>
#include <map>
#include <unordered_map>

#include <fmq/AidlMessageQueue.h>

@@ -58,15 +60,9 @@ using MQDesc = MQDescriptor<int8_t, SynchronizedReadWrite>;

class FilterCallback : public BnFilterCallback {
  public:
    virtual ::ndk::ScopedAStatus onFilterEvent(const vector<DemuxFilterEvent>& events) 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
        readFilterEventsData(events);
        mPidFilterOutputCount++;
        mMsgCondition.signal();
        return ::ndk::ScopedAStatus::ok();
    }
    virtual ::ndk::ScopedAStatus onFilterEvent(const vector<DemuxFilterEvent>& events) override;

    std::future<DemuxFilterEvent> getNextFilterEventWithTag(DemuxFilterEvent::Tag tag);

    virtual ::ndk::ScopedAStatus onFilterStatus(const DemuxFilterStatus /*status*/) override {
        return ::ndk::ScopedAStatus::ok();
@@ -89,6 +85,7 @@ class FilterCallback : public BnFilterCallback {
    int32_t mFilterId;
    std::shared_ptr<IFilter> mFilter;

    std::unordered_map<DemuxFilterEvent::Tag, std::promise<DemuxFilterEvent>> mFilterEventPromises;
    native_handle_t* mAvSharedHandle = nullptr;
    uint64_t mAvSharedMemSize = -1;

+51 −0
Original line number Diff line number Diff line
@@ -640,6 +640,57 @@ TEST_P(TunerFilterAidlTest, testTimeFilter) {
    testTimeFilter(timeFilterMap[timeFilter.timeFilterId]);
}

// TODO: move boilerplate into text fixture
TEST_P(TunerFilterAidlTest, FilterTimeDelayHintTest) {
    description("Test filter delay hint.");

    int32_t feId;
    int32_t demuxId;
    std::shared_ptr<IDemux> demux;
    int64_t filterId;

    mFrontendTests.getFrontendIdByType(frontendMap[live.frontendId].type, feId);
    ASSERT_TRUE(feId != INVALID_ID);
    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
    mFilterTests.setDemux(demux);

    const auto& filterConf = filterMap[live.ipFilterId];
    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
    ASSERT_TRUE(mFilterTests.configIpFilterCid(filterConf.ipCid, filterId));

    auto filter = mFilterTests.getFilterById(filterId);

    auto delayValue = std::chrono::milliseconds(5000);
    FilterDelayHint delayHint;
    delayHint.hintType = FilterDelayHintType::TIME_DELAY_IN_MS;
    delayHint.hintValue = delayValue.count();

    auto status = filter->setDelayHint(delayHint);
    ASSERT_TRUE(status.isOk());

    auto startTime = std::chrono::steady_clock::now();
    ASSERT_TRUE(mFilterTests.startFilter(filterId));

    auto cb = mFilterTests.getFilterCallbacks().at(filterId);
    auto future = cb->getNextFilterEventWithTag(DemuxFilterEvent::Tag::ipPayload);

    // block and wait for callback to be received.
    ASSERT_EQ(future.wait_for(std::chrono::seconds(10)), std::future_status::ready);
    auto duration = std::chrono::steady_clock::now() - startTime;
    ASSERT_GE(duration, delayValue);

    // cleanup
    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
    ASSERT_TRUE(mFilterTests.closeFilter(filterId));
    ASSERT_TRUE(mDemuxTests.closeDemux());
    ASSERT_TRUE(mFrontendTests.closeFrontend());
}

TEST_P(TunerPlaybackAidlTest, PlaybackDataFlowWithTsSectionFilterTest) {
    description("Feed ts data from playback and configure Ts section filter to get output");
    if (!playback.support || playback.sectionFilterId.compare(emptyHardwareId) == 0) {