diff options
author | Amy Zhang <amyjojo@google.com> | 2020-04-08 17:30:52 -0700 |
---|---|---|
committer | Amy Zhang <amyjojo@google.com> | 2020-04-21 01:16:57 -0700 |
commit | 0fe25be00596c588a6c76f1d417c0dcd713456e0 (patch) | |
tree | 3c80580acb9324df1ce3632717a1b6fc37906844 /tv | |
parent | 4f6980571a8430eb0c13c033822c470c0aa66a1b (diff) | |
download | platform_hardware_interfaces-0fe25be00596c588a6c76f1d417c0dcd713456e0.tar.gz platform_hardware_interfaces-0fe25be00596c588a6c76f1d417c0dcd713456e0.tar.bz2 platform_hardware_interfaces-0fe25be00596c588a6c76f1d417c0dcd713456e0.zip |
Make dvr tests a separate module
Test: atest VtsHalTvTunerV1_0TargetTest
Bug: 150989084
Change-Id: I35d717f357b176d5cbec5d154f4df30fd2c4a18e
Diffstat (limited to 'tv')
-rw-r--r-- | tv/tuner/1.0/default/Demux.cpp | 8 | ||||
-rw-r--r-- | tv/tuner/1.0/default/Demux.h | 2 | ||||
-rw-r--r-- | tv/tuner/1.0/default/Frontend.cpp | 1 | ||||
-rw-r--r-- | tv/tuner/1.0/default/Tuner.cpp | 9 | ||||
-rw-r--r-- | tv/tuner/1.0/default/Tuner.h | 1 | ||||
-rw-r--r-- | tv/tuner/1.0/vts/functional/Android.bp | 1 | ||||
-rw-r--r-- | tv/tuner/1.0/vts/functional/DemuxTests.h | 3 | ||||
-rw-r--r-- | tv/tuner/1.0/vts/functional/DvrTests.cpp | 267 | ||||
-rw-r--r-- | tv/tuner/1.0/vts/functional/DvrTests.h | 187 | ||||
-rw-r--r-- | tv/tuner/1.0/vts/functional/FilterTests.h | 1 | ||||
-rw-r--r-- | tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp | 350 | ||||
-rw-r--r-- | tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h | 159 | ||||
-rw-r--r-- | tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h | 69 |
13 files changed, 670 insertions, 388 deletions
diff --git a/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp index 43c4e3a086..95b4ebc7a6 100644 --- a/tv/tuner/1.0/default/Demux.cpp +++ b/tv/tuner/1.0/default/Demux.cpp @@ -52,7 +52,7 @@ Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) { mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId); - return startFrontendInputLoop(); + return Result::SUCCESS; } Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize, @@ -60,7 +60,6 @@ Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize, ALOGV("%s", __FUNCTION__); uint32_t filterId; - if (!mUnusedFilterIds.empty()) { filterId = *mUnusedFilterIds.begin(); @@ -83,7 +82,6 @@ Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize, _hidl_cb(Result::UNKNOWN_ERROR, filter); return Void(); } - mFilters[filterId] = filter; _hidl_cb(Result::SUCCESS, filter); @@ -234,11 +232,9 @@ uint16_t Demux::getFilterTpid(uint32_t filterId) { return mFilters[filterId]->getTpid(); } -Result Demux::startFrontendInputLoop() { +void Demux::startFrontendInputLoop() { pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this); pthread_setname_np(mFrontendInputThread, "frontend_input_thread"); - - return Result::SUCCESS; } void* Demux::__threadLoopFrontend(void* user) { diff --git a/tv/tuner/1.0/default/Demux.h b/tv/tuner/1.0/default/Demux.h index 1405d0c2ca..759e348d93 100644 --- a/tv/tuner/1.0/default/Demux.h +++ b/tv/tuner/1.0/default/Demux.h @@ -89,6 +89,7 @@ class Demux : public IDemux { void updateFilterOutput(uint16_t filterId, vector<uint8_t> data); uint16_t getFilterTpid(uint32_t filterId); void setIsRecording(bool isRecording); + void startFrontendInputLoop(); private: // Tuner service @@ -104,7 +105,6 @@ class Demux : public IDemux { uint32_t filterId; }; - Result startFrontendInputLoop(); static void* __threadLoopFrontend(void* user); void frontendInputThreadLoop(); diff --git a/tv/tuner/1.0/default/Frontend.cpp b/tv/tuner/1.0/default/Frontend.cpp index 2cff9be459..7d55739cff 100644 --- a/tv/tuner/1.0/default/Frontend.cpp +++ b/tv/tuner/1.0/default/Frontend.cpp @@ -64,6 +64,7 @@ Return<Result> Frontend::tune(const FrontendSettings& /* settings */) { return Result::INVALID_STATE; } + mTunerService->frontendStartTune(mId); mCallback->onEvent(FrontendEventType::LOCKED); mIsLocked = false; return Result::SUCCESS; diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp index e39333ce3e..14a428970a 100644 --- a/tv/tuner/1.0/default/Tuner.cpp +++ b/tv/tuner/1.0/default/Tuner.cpp @@ -236,6 +236,15 @@ void Tuner::frontendStopTune(uint32_t frontendId) { } } +void Tuner::frontendStartTune(uint32_t frontendId) { + map<uint32_t, uint32_t>::iterator it = mFrontendToDemux.find(frontendId); + uint32_t demuxId; + if (it != mFrontendToDemux.end()) { + demuxId = it->second; + mDemuxes[demuxId]->startFrontendInputLoop(); + } +} + } // namespace implementation } // namespace V1_0 } // namespace tuner diff --git a/tv/tuner/1.0/default/Tuner.h b/tv/tuner/1.0/default/Tuner.h index d17b5aeb64..ada0f81cac 100644 --- a/tv/tuner/1.0/default/Tuner.h +++ b/tv/tuner/1.0/default/Tuner.h @@ -62,6 +62,7 @@ class Tuner : public ITuner { void setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId); + void frontendStartTune(uint32_t frontendId); void frontendStopTune(uint32_t frontendId); private: diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp index 448575ea7a..b152a292cb 100644 --- a/tv/tuner/1.0/vts/functional/Android.bp +++ b/tv/tuner/1.0/vts/functional/Android.bp @@ -22,6 +22,7 @@ cc_test { "FrontendTests.cpp", "DemuxTests.cpp", "FilterTests.cpp", + "DvrTests.cpp", ], static_libs: [ "android.hardware.tv.tuner@1.0", diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.h b/tv/tuner/1.0/vts/functional/DemuxTests.h index f405a79ae8..31b3e7bafc 100644 --- a/tv/tuner/1.0/vts/functional/DemuxTests.h +++ b/tv/tuner/1.0/vts/functional/DemuxTests.h @@ -40,8 +40,6 @@ using ::testing::AssertionResult; class DemuxTests { public: - sp<ITuner> mService; - void setService(sp<ITuner> tuner) { mService = tuner; } AssertionResult openDemux(sp<IDemux>& demux, uint32_t& demuxId); @@ -53,5 +51,6 @@ class DemuxTests { static AssertionResult success() { return ::testing::AssertionSuccess(); } + sp<ITuner> mService; sp<IDemux> mDemux; };
\ No newline at end of file diff --git a/tv/tuner/1.0/vts/functional/DvrTests.cpp b/tv/tuner/1.0/vts/functional/DvrTests.cpp new file mode 100644 index 0000000000..a1ce23d730 --- /dev/null +++ b/tv/tuner/1.0/vts/functional/DvrTests.cpp @@ -0,0 +1,267 @@ +/* + * 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 "DvrTests.h" + +void DvrCallback::startPlaybackInputThread(PlaybackConf playbackConf, + MQDesc& playbackMQDescriptor) { + mPlaybackMQ = std::make_unique<FilterMQ>(playbackMQDescriptor, true /* resetPointers */); + EXPECT_TRUE(mPlaybackMQ); + struct PlaybackThreadArgs* threadArgs = + (struct PlaybackThreadArgs*)malloc(sizeof(struct PlaybackThreadArgs)); + threadArgs->user = this; + threadArgs->playbackConf = &playbackConf; + threadArgs->keepWritingPlaybackFMQ = &mKeepWritingPlaybackFMQ; + + pthread_create(&mPlaybackThread, NULL, __threadLoopPlayback, (void*)threadArgs); + pthread_setname_np(mPlaybackThread, "test_playback_input_loop"); +} + +void DvrCallback::stopPlaybackThread() { + mPlaybackThreadRunning = false; + mKeepWritingPlaybackFMQ = false; + + android::Mutex::Autolock autoLock(mPlaybackThreadLock); +} + +void* DvrCallback::__threadLoopPlayback(void* threadArgs) { + DvrCallback* const self = + static_cast<DvrCallback*>(((struct PlaybackThreadArgs*)threadArgs)->user); + self->playbackThreadLoop(((struct PlaybackThreadArgs*)threadArgs)->playbackConf, + ((struct PlaybackThreadArgs*)threadArgs)->keepWritingPlaybackFMQ); + return 0; +} + +void DvrCallback::playbackThreadLoop(PlaybackConf* playbackConf, bool* keepWritingPlaybackFMQ) { + android::Mutex::Autolock autoLock(mPlaybackThreadLock); + mPlaybackThreadRunning = true; + + // Create the EventFlag that is used to signal the HAL impl that data have been + // written into the Playback FMQ + EventFlag* playbackMQEventFlag; + EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) == + android::OK); + + // open the stream and get its length + std::ifstream inputData(playbackConf->inputDataFile, std::ifstream::binary); + int writeSize = playbackConf->setting.packetSize * 6; + char* buffer = new char[writeSize]; + ALOGW("[vts] playback thread loop start %s", playbackConf->inputDataFile.c_str()); + if (!inputData.is_open()) { + mPlaybackThreadRunning = false; + ALOGW("[vts] Error %s", strerror(errno)); + } + + while (mPlaybackThreadRunning) { + // move the stream pointer for packet size * 6 every read until the end + while (*keepWritingPlaybackFMQ) { + inputData.read(buffer, writeSize); + if (!inputData) { + int leftSize = inputData.gcount(); + if (leftSize == 0) { + mPlaybackThreadRunning = false; + break; + } + inputData.clear(); + inputData.read(buffer, leftSize); + // Write the left over of the input data and quit the thread + if (leftSize > 0) { + EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], leftSize)); + playbackMQEventFlag->wake( + static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY)); + } + mPlaybackThreadRunning = false; + break; + } + // Write input FMQ and notify the Tuner Implementation + EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], writeSize)); + playbackMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY)); + inputData.seekg(writeSize, inputData.cur); + sleep(1); + } + } + + ALOGW("[vts] Playback thread end."); + + delete[] buffer; + inputData.close(); +} + +void DvrCallback::testRecordOutput() { + android::Mutex::Autolock autoLock(mMsgLock); + while (mDataOutputBuffer.empty()) { + if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) { + EXPECT_TRUE(false) << "record output matching pid does not output within timeout"; + return; + } + } + stopRecordThread(); + ALOGW("[vts] record pass and stop"); +} + +void DvrCallback::startRecordOutputThread(RecordSettings recordSettings, + MQDesc& recordMQDescriptor) { + mRecordMQ = std::make_unique<FilterMQ>(recordMQDescriptor, true /* resetPointers */); + EXPECT_TRUE(mRecordMQ); + struct RecordThreadArgs* threadArgs = + (struct RecordThreadArgs*)malloc(sizeof(struct RecordThreadArgs)); + threadArgs->user = this; + threadArgs->recordSettings = &recordSettings; + threadArgs->keepReadingRecordFMQ = &mKeepReadingRecordFMQ; + + pthread_create(&mRecordThread, NULL, __threadLoopRecord, (void*)threadArgs); + pthread_setname_np(mRecordThread, "test_record_input_loop"); +} + +void* DvrCallback::__threadLoopRecord(void* threadArgs) { + DvrCallback* const self = + static_cast<DvrCallback*>(((struct RecordThreadArgs*)threadArgs)->user); + self->recordThreadLoop(((struct RecordThreadArgs*)threadArgs)->recordSettings, + ((struct RecordThreadArgs*)threadArgs)->keepReadingRecordFMQ); + return 0; +} + +void DvrCallback::recordThreadLoop(RecordSettings* /*recordSettings*/, bool* keepReadingRecordFMQ) { + ALOGD("[vts] DvrCallback record threadLoop start."); + android::Mutex::Autolock autoLock(mRecordThreadLock); + mRecordThreadRunning = true; + + // Create the EventFlag that is used to signal the HAL impl that data have been + // read from the Record FMQ + EventFlag* recordMQEventFlag; + EXPECT_TRUE(EventFlag::createEventFlag(mRecordMQ->getEventFlagWord(), &recordMQEventFlag) == + android::OK); + + while (mRecordThreadRunning) { + while (*keepReadingRecordFMQ) { + uint32_t efState = 0; + android::status_t status = recordMQEventFlag->wait( + static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT, + true /* retry on spurious wake */); + if (status != android::OK) { + ALOGD("[vts] wait for data ready on the record FMQ"); + continue; + } + // Our current implementation filter the data and write it into the filter FMQ + // immediately after the DATA_READY from the VTS/framework + if (!readRecordFMQ()) { + ALOGD("[vts] record data failed to be filtered. Ending thread"); + mRecordThreadRunning = false; + break; + } + } + } + + mRecordThreadRunning = false; + ALOGD("[vts] record thread ended."); +} + +bool DvrCallback::readRecordFMQ() { + android::Mutex::Autolock autoLock(mMsgLock); + bool result = false; + mDataOutputBuffer.clear(); + mDataOutputBuffer.resize(mRecordMQ->availableToRead()); + result = mRecordMQ->read(mDataOutputBuffer.data(), mRecordMQ->availableToRead()); + EXPECT_TRUE(result) << "can't read from Record MQ"; + mMsgCondition.signal(); + return result; +} + +void DvrCallback::stopRecordThread() { + mKeepReadingRecordFMQ = false; + mRecordThreadRunning = false; + android::Mutex::Autolock autoLock(mRecordThreadLock); +} + +AssertionResult DvrTests::openDvrInDemux(DvrType type) { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + + // Create dvr callback + mDvrCallback = new DvrCallback(); + + mDemux->openDvr(type, FMQ_SIZE_1M, mDvrCallback, [&](Result result, const sp<IDvr>& dvr) { + mDvr = dvr; + status = result; + }); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::configDvr(DvrSettings setting) { + Result status = mDvr->configure(setting); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::getDvrMQDescriptor() { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mDvr) << "Test with openDvr first."; + + mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) { + mDvrMQDescriptor = dvrMQDesc; + status = result; + }); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::attachFilterToDvr(sp<IFilter> filter) { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mDvr) << "Test with openDvr first."; + + status = mDvr->attachFilter(filter); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::detachFilterToDvr(sp<IFilter> filter) { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mDvr) << "Test with openDvr first."; + + status = mDvr->detachFilter(filter); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::startDvr() { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mDvr) << "Test with openDvr first."; + + status = mDvr->start(); + + return AssertionResult(status == Result::SUCCESS); +} + +AssertionResult DvrTests::stopDvr() { + Result status; + EXPECT_TRUE(mDemux) << "Test with openDemux first."; + EXPECT_TRUE(mDvr) << "Test with openDvr first."; + + status = mDvr->stop(); + + return AssertionResult(status == Result::SUCCESS); +} + +void DvrTests::closeDvr() { + ASSERT_TRUE(mDemux); + ASSERT_TRUE(mDvr); + ASSERT_TRUE(mDvr->close() == Result::SUCCESS); +}
\ No newline at end of file diff --git a/tv/tuner/1.0/vts/functional/DvrTests.h b/tv/tuner/1.0/vts/functional/DvrTests.h new file mode 100644 index 0000000000..74ef58ebf1 --- /dev/null +++ b/tv/tuner/1.0/vts/functional/DvrTests.h @@ -0,0 +1,187 @@ +/* + * 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/IDvr.h> +#include <android/hardware/tv/tuner/1.0/IDvrCallback.h> +#include <android/hardware/tv/tuner/1.0/ITuner.h> +#include <android/hardware/tv/tuner/1.0/types.h> +#include <fmq/MessageQueue.h> +#include <hidl/Status.h> +#include <utils/Condition.h> +#include <utils/Mutex.h> +#include <fstream> +#include <iostream> +#include <map> + +#include "FilterTests.h" + +using android::Condition; +using android::Mutex; +using android::sp; +using android::hardware::EventFlag; +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::DemuxFilterStatus; +using android::hardware::tv::tuner::V1_0::DvrSettings; +using android::hardware::tv::tuner::V1_0::DvrType; +using android::hardware::tv::tuner::V1_0::IDvr; +using android::hardware::tv::tuner::V1_0::IDvrCallback; +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; + +#define WAIT_TIMEOUT 3000000000 + +struct PlaybackConf { + string inputDataFile; + PlaybackSettings setting; +}; + +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 stopPlaybackThread(); + void testRecordOutput(); + void stopRecordThread(); + + void startPlaybackInputThread(PlaybackConf playbackConf, MQDesc& playbackMQDescriptor); + void startRecordOutputThread(RecordSettings recordSettings, 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* recordSettings; + 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 DvrTests { + public: + void setService(sp<ITuner> tuner) { mService = tuner; } + void setDemux(sp<IDemux> demux) { mDemux = demux; } + + void startPlaybackInputThread(string dataInputFile, PlaybackSettings settings) { + PlaybackConf conf{ + .inputDataFile = dataInputFile, + .setting = settings, + }; + mDvrCallback->startPlaybackInputThread(conf, mDvrMQDescriptor); + }; + + void startRecordOutputThread(RecordSettings settings) { + mDvrCallback->startRecordOutputThread(settings, mDvrMQDescriptor); + }; + + void stopPlaybackThread() { mDvrCallback->stopPlaybackThread(); } + void testRecordOutput() { mDvrCallback->testRecordOutput(); } + void stopRecordThread() { mDvrCallback->stopPlaybackThread(); } + + AssertionResult openDvrInDemux(DvrType type); + AssertionResult configDvr(DvrSettings setting); + AssertionResult getDvrMQDescriptor(); + AssertionResult attachFilterToDvr(sp<IFilter> filter); + AssertionResult detachFilterToDvr(sp<IFilter> filter); + AssertionResult stopDvr(); + AssertionResult startDvr(); + void closeDvr(); + + protected: + static AssertionResult failure() { return ::testing::AssertionFailure(); } + + static AssertionResult success() { return ::testing::AssertionSuccess(); } + + sp<ITuner> mService; + sp<IDvr> mDvr; + sp<IDemux> mDemux; + sp<DvrCallback> mDvrCallback; + MQDesc mDvrMQDescriptor; + + pthread_t mPlaybackshread; + bool mPlaybackThreadRunning; +};
\ 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 index eab963bc34..39462dcbbe 100644 --- a/tv/tuner/1.0/vts/functional/FilterTests.h +++ b/tv/tuner/1.0/vts/functional/FilterTests.h @@ -149,6 +149,7 @@ class FilterTests { public: void setService(sp<ITuner> tuner) { mService = tuner; } void setDemux(sp<IDemux> demux) { mDemux = demux; } + sp<IFilter> getFilterById(uint32_t filterId) { return mFilters[filterId]; } std::map<uint32_t, sp<FilterCallback>> getFilterCallbacks() { return mFilterCallbacks; } diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp index d836c26f9f..f211be2e90 100644 --- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp +++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp @@ -17,181 +17,8 @@ #include "VtsHalTvTunerV1_0TargetTest.h" namespace { - -/******************************** Start DvrCallback **********************************/ -void DvrCallback::startPlaybackInputThread(PlaybackConf playbackConf, - MQDesc& playbackMQDescriptor) { - mPlaybackMQ = std::make_unique<FilterMQ>(playbackMQDescriptor, true /* resetPointers */); - EXPECT_TRUE(mPlaybackMQ); - struct PlaybackThreadArgs* threadArgs = - (struct PlaybackThreadArgs*)malloc(sizeof(struct PlaybackThreadArgs)); - threadArgs->user = this; - threadArgs->playbackConf = &playbackConf; - threadArgs->keepWritingPlaybackFMQ = &mKeepWritingPlaybackFMQ; - - pthread_create(&mPlaybackThread, NULL, __threadLoopPlayback, (void*)threadArgs); - pthread_setname_np(mPlaybackThread, "test_playback_input_loop"); -} - -void DvrCallback::stopPlaybackThread() { - mPlaybackThreadRunning = false; - mKeepWritingPlaybackFMQ = false; - - android::Mutex::Autolock autoLock(mPlaybackThreadLock); -} - -void* DvrCallback::__threadLoopPlayback(void* threadArgs) { - DvrCallback* const self = - static_cast<DvrCallback*>(((struct PlaybackThreadArgs*)threadArgs)->user); - self->playbackThreadLoop(((struct PlaybackThreadArgs*)threadArgs)->playbackConf, - ((struct PlaybackThreadArgs*)threadArgs)->keepWritingPlaybackFMQ); - return 0; -} - -void DvrCallback::playbackThreadLoop(PlaybackConf* playbackConf, bool* keepWritingPlaybackFMQ) { - android::Mutex::Autolock autoLock(mPlaybackThreadLock); - mPlaybackThreadRunning = true; - - // Create the EventFlag that is used to signal the HAL impl that data have been - // written into the Playback FMQ - EventFlag* playbackMQEventFlag; - EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) == - android::OK); - - // open the stream and get its length - std::ifstream inputData(playbackConf->inputDataFile, std::ifstream::binary); - int writeSize = playbackConf->setting.packetSize * 6; - char* buffer = new char[writeSize]; - ALOGW("[vts] playback thread loop start %s", playbackConf->inputDataFile.c_str()); - if (!inputData.is_open()) { - mPlaybackThreadRunning = false; - ALOGW("[vts] Error %s", strerror(errno)); - } - - while (mPlaybackThreadRunning) { - // move the stream pointer for packet size * 6 every read until the end - while (*keepWritingPlaybackFMQ) { - inputData.read(buffer, writeSize); - if (!inputData) { - int leftSize = inputData.gcount(); - if (leftSize == 0) { - mPlaybackThreadRunning = false; - break; - } - inputData.clear(); - inputData.read(buffer, leftSize); - // Write the left over of the input data and quit the thread - if (leftSize > 0) { - EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], leftSize)); - playbackMQEventFlag->wake( - static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY)); - } - mPlaybackThreadRunning = false; - break; - } - // Write input FMQ and notify the Tuner Implementation - EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], writeSize)); - playbackMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY)); - inputData.seekg(writeSize, inputData.cur); - sleep(1); - } - } - - ALOGW("[vts] Playback thread end."); - - delete[] buffer; - inputData.close(); -} - -void DvrCallback::testRecordOutput() { - android::Mutex::Autolock autoLock(mMsgLock); - while (mDataOutputBuffer.empty()) { - if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) { - EXPECT_TRUE(false) << "record output matching pid does not output within timeout"; - return; - } - } - stopRecordThread(); - ALOGW("[vts] record pass and stop"); -} - -void DvrCallback::startRecordOutputThread(RecordSettings recordSetting, - MQDesc& recordMQDescriptor) { - mRecordMQ = std::make_unique<FilterMQ>(recordMQDescriptor, true /* resetPointers */); - EXPECT_TRUE(mRecordMQ); - struct RecordThreadArgs* threadArgs = - (struct RecordThreadArgs*)malloc(sizeof(struct RecordThreadArgs)); - threadArgs->user = this; - threadArgs->recordSetting = &recordSetting; - threadArgs->keepReadingRecordFMQ = &mKeepReadingRecordFMQ; - - pthread_create(&mRecordThread, NULL, __threadLoopRecord, (void*)threadArgs); - pthread_setname_np(mRecordThread, "test_record_input_loop"); -} - -void* DvrCallback::__threadLoopRecord(void* threadArgs) { - DvrCallback* const self = - static_cast<DvrCallback*>(((struct RecordThreadArgs*)threadArgs)->user); - self->recordThreadLoop(((struct RecordThreadArgs*)threadArgs)->recordSetting, - ((struct RecordThreadArgs*)threadArgs)->keepReadingRecordFMQ); - return 0; -} - -void DvrCallback::recordThreadLoop(RecordSettings* /*recordSetting*/, bool* keepReadingRecordFMQ) { - ALOGD("[vts] DvrCallback record threadLoop start."); - android::Mutex::Autolock autoLock(mRecordThreadLock); - mRecordThreadRunning = true; - - // Create the EventFlag that is used to signal the HAL impl that data have been - // read from the Record FMQ - EventFlag* recordMQEventFlag; - EXPECT_TRUE(EventFlag::createEventFlag(mRecordMQ->getEventFlagWord(), &recordMQEventFlag) == - android::OK); - - while (mRecordThreadRunning) { - while (*keepReadingRecordFMQ) { - uint32_t efState = 0; - android::status_t status = recordMQEventFlag->wait( - static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT, - true /* retry on spurious wake */); - if (status != android::OK) { - ALOGD("[vts] wait for data ready on the record FMQ"); - continue; - } - // Our current implementation filter the data and write it into the filter FMQ - // immediately after the DATA_READY from the VTS/framework - if (!readRecordFMQ()) { - ALOGD("[vts] record data failed to be filtered. Ending thread"); - mRecordThreadRunning = false; - break; - } - } - } - - mRecordThreadRunning = false; - ALOGD("[vts] record thread ended."); -} - -bool DvrCallback::readRecordFMQ() { - android::Mutex::Autolock autoLock(mMsgLock); - bool result = false; - mDataOutputBuffer.clear(); - mDataOutputBuffer.resize(mRecordMQ->availableToRead()); - result = mRecordMQ->read(mDataOutputBuffer.data(), mRecordMQ->availableToRead()); - EXPECT_TRUE(result) << "can't read from Record MQ"; - mMsgCondition.signal(); - return result; -} - -void DvrCallback::stopRecordThread() { - mKeepReadingRecordFMQ = false; - mRecordThreadRunning = false; - android::Mutex::Autolock autoLock(mRecordThreadLock); -} -/********************************** End DvrCallback ************************************/ - /*======================== Start Descrambler APIs Tests Implementation ========================*/ -AssertionResult TunerHidlTest::createDescrambler() { +AssertionResult TunerHidlTest::createDescrambler(uint32_t demuxId) { Result status; mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) { mDescrambler = descrambler; @@ -201,21 +28,19 @@ AssertionResult TunerHidlTest::createDescrambler() { return failure(); } - status = mDescrambler->setDemuxSource(mDemuxId); + status = mDescrambler->setDemuxSource(demuxId); if (status != Result::SUCCESS) { return failure(); } // Test if demux source can be set more than once. - status = mDescrambler->setDemuxSource(mDemuxId); + status = mDescrambler->setDemuxSource(demuxId); return AssertionResult(status == Result::INVALID_STATE); } AssertionResult TunerHidlTest::closeDescrambler() { Result status; - if (!mDescrambler && createDescrambler() == failure()) { - return failure(); - } + EXPECT_TRUE(mDescrambler); status = mDescrambler->close(); mDescrambler = nullptr; @@ -223,40 +48,6 @@ AssertionResult TunerHidlTest::closeDescrambler() { } /*========================= End Descrambler APIs Tests Implementation =========================*/ -/*============================ Start Dvr APIs Tests Implementation ============================*/ -AssertionResult TunerHidlTest::openDvrInDemux(DvrType type) { - Result status; - - // Create dvr callback - mDvrCallback = new DvrCallback(); - - mDemux->openDvr(type, FMQ_SIZE_1M, mDvrCallback, [&](Result result, const sp<IDvr>& dvr) { - mDvr = dvr; - status = result; - }); - - return AssertionResult(status == Result::SUCCESS); -} - -AssertionResult TunerHidlTest::configDvr(DvrSettings setting) { - Result status = mDvr->configure(setting); - - return AssertionResult(status == Result::SUCCESS); -} - -AssertionResult TunerHidlTest::getDvrMQDescriptor() { - Result status; - EXPECT_TRUE(mDvr) << "Test with openDvr first."; - - mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) { - mDvrMQDescriptor = dvrMQDesc; - status = result; - }); - - return AssertionResult(status == Result::SUCCESS); -} -/*============================ End Dvr APIs Tests Implementation ============================*/ - /*========================== Start Data Flow Tests Implementation ==========================*/ AssertionResult TunerHidlTest::broadcastDataFlowTest(vector<string> /*goldenOutputFiles*/) { // Data Verify Module @@ -417,6 +208,10 @@ AssertionResult TunerHidlTest::recordDataFlowTest(vector<FilterConf> filterConf, void TunerHidlTest::broadcastSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf) { uint32_t feId; + uint32_t demuxId; + sp<IDemux> demux; + uint32_t filterId; + mFrontendTests.getFrontendIdByType(frontendConf.type, feId); if (feId == INVALID_ID) { // TODO broadcast test on Cuttlefish needs licensed ts input, @@ -426,13 +221,12 @@ void TunerHidlTest::broadcastSingleFilterTest(FilterConfig filterConf, } ASSERT_TRUE(mFrontendTests.openFrontendById(feId)); ASSERT_TRUE(mFrontendTests.setFrontendCallback()); - ASSERT_TRUE(mDemuxTests.openDemux(mDemux, mDemuxId)); - mFilterTests.setDemux(mDemux); + ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId)); ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId)); + mFilterTests.setDemux(demux); ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type)); - uint32_t filterId; ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId)); - ASSERT_TRUE(mFilterTests.configFilter(filterConf.setting, filterId)); + ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId)); ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId)); ASSERT_TRUE(mFilterTests.startFilter(filterId)); // tune test @@ -445,6 +239,67 @@ void TunerHidlTest::broadcastSingleFilterTest(FilterConfig filterConf, ASSERT_TRUE(mDemuxTests.closeDemux()); ASSERT_TRUE(mFrontendTests.closeFrontend()); } + +void TunerDvrHidlTest::attachSingleFilterToDvrTest(FilterConfig filterConf, + FrontendConfig frontendConf, DvrConfig dvrConf) { + description("Open and configure a Dvr in Demux."); + uint32_t feId; + uint32_t demuxId; + sp<IDemux> demux; + uint32_t filterId; + sp<IFilter> filter; + + mFrontendTests.getFrontendIdByType(frontendConf.type, feId); + ASSERT_TRUE(feId != INVALID_ID); + ASSERT_TRUE(mFrontendTests.openFrontendById(feId)); + ASSERT_TRUE(mFrontendTests.setFrontendCallback()); + ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId)); + ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId)); + mFilterTests.setDemux(demux); + mDvrTests.setDemux(demux); + ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type)); + ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings)); + ASSERT_TRUE(mDvrTests.getDvrMQDescriptor()); + ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type)); + ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId)); + ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId)); + ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId)); + ASSERT_TRUE(mFilterTests.startFilter(filterId)); + filter = mFilterTests.getFilterById(filterId); + ASSERT_TRUE(filter != nullptr); + ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter)); + ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter)); + ASSERT_TRUE(mFilterTests.stopFilter(filterId)); + ASSERT_TRUE(mFilterTests.closeFilter(filterId)); + mDvrTests.closeDvr(); + ASSERT_TRUE(mDemuxTests.closeDemux()); + ASSERT_TRUE(mFrontendTests.closeFrontend()); +} + +void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig filterConf, + FrontendConfig frontendConf) { + uint32_t feId; + uint32_t demuxId; + sp<IDemux> demux; + uint32_t filterId; + + mFrontendTests.getFrontendIdByType(frontendConf.type, feId); + ASSERT_TRUE(feId != INVALID_ID); + ASSERT_TRUE(mFrontendTests.openFrontendById(feId)); + ASSERT_TRUE(mFrontendTests.setFrontendCallback()); + ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId)); + ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId)); + mFilterTests.setDemux(demux); + ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type)); + ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId)); + ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId)); + ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId)); + ASSERT_TRUE(mFilterTests.startFilter(filterId)); + ASSERT_TRUE(mFilterTests.stopFilter(filterId)); + ASSERT_TRUE(mFilterTests.closeFilter(filterId)); + ASSERT_TRUE(mDemuxTests.closeDemux()); + ASSERT_TRUE(mFrontendTests.closeFrontend()); +} /*================================== End Test Module ==================================*/ /***************************** End Test Implementation *****************************/ @@ -467,50 +322,56 @@ TEST_P(TunerFrontendHidlTest, BlindScanFrontend) { TEST_P(TunerDemuxHidlTest, openDemux) { description("Open and close a Demux."); uint32_t feId; + uint32_t demuxId; + sp<IDemux> demux; 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.openDemux(demux, demuxId)); 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(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(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()); + // TODO use paramterized tests + configSingleFilterInDemuxTest(filterArray[TS_VIDEO0], frontendArray[DVBT]); +} + +TEST_P(TunerDvrHidlTest, AttachFiltersToRecordTest) { + description("Attach a single filter to the record dvr test."); + // TODO use paramterized tests + attachSingleFilterToDvrTest(filterArray[TS_VIDEO0], frontendArray[DVBT], dvrArray[DVR_RECORD0]); +} + +TEST_P(TunerDvrHidlTest, AttachFiltersToPlaybackTest) { + description("Attach a single filter to the playback dvr test."); + // TODO use paramterized tests + attachSingleFilterToDvrTest(filterArray[TS_VIDEO0], frontendArray[DVBT], + dvrArray[DVR_PLAYBACK0]); } /*============================ Start Descrambler Tests ============================*/ /* * TODO: re-enable the tests after finalizing the test refactoring. */ -/*TEST_P(TunerHidlTest, CreateDescrambler) { +TEST_P(TunerHidlTest, CreateDescrambler) { description("Create Descrambler"); - ASSERT_TRUE(createDescrambler()); + uint32_t feId; + uint32_t demuxId; + sp<IDemux> demux; + mFrontendTests.getFrontendIdByType(frontendArray[DVBT].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)); + ASSERT_TRUE(createDescrambler(demuxId)); + ASSERT_TRUE(mDemuxTests.closeDemux()); + ASSERT_TRUE(closeDescrambler()); } -TEST_P(TunerHidlTest, CloseDescrambler) { - description("Close Descrambler"); - ASSERT_TRUE(closeDescrambler()); -}*/ /*============================== End Descrambler Tests ==============================*/ /*============================== Start Data Flow Tests ==============================*/ @@ -642,4 +503,9 @@ INSTANTIATE_TEST_SUITE_P( PerInstance, TunerFilterHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)), android::hardware::PrintInstanceNameToString); + +INSTANTIATE_TEST_SUITE_P( + PerInstance, TunerDvrHidlTest, + 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 f17704774c..37b28660fb 100644 --- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h +++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h @@ -15,30 +15,13 @@ */ #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 "DvrTests.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(); @@ -50,89 +33,6 @@ static AssertionResult success() { 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 { @@ -174,8 +74,6 @@ class TunerDemuxHidlTest : public testing::TestWithParam<std::string> { sp<ITuner> mService; FrontendTests mFrontendTests; DemuxTests mDemuxTests; - sp<IDemux> mDemux; - uint32_t mDemuxId; }; class TunerFilterHidlTest : public testing::TestWithParam<std::string> { @@ -197,21 +95,47 @@ class TunerFilterHidlTest : public testing::TestWithParam<std::string> { RecordProperty("description", description); } + void configSingleFilterInDemuxTest(FilterConfig filterConf, FrontendConfig frontendConf); + sp<ITuner> mService; FrontendTests mFrontendTests; DemuxTests mDemuxTests; FilterTests mFilterTests; - sp<IDemux> mDemux; - uint32_t mDemuxId; }; -class TunerHidlTest : public testing::TestWithParam<std::string> { +class TunerDvrHidlTest : public testing::TestWithParam<std::string> { public: + virtual void SetUp() override { + mService = ITuner::getService(GetParam()); + ASSERT_NE(mService, nullptr); + initFrontendConfig(); + initFrontendScanConfig(); + initFilterConfig(); + initDvrConfig(); + + mFrontendTests.setService(mService); + mDemuxTests.setService(mService); + mFilterTests.setService(mService); + mDvrTests.setService(mService); + } + + protected: + static void description(const std::string& description) { + RecordProperty("description", description); + } + + void attachSingleFilterToDvrTest(FilterConfig filterConf, FrontendConfig frontendConf, + DvrConfig dvrConf); + sp<ITuner> mService; FrontendTests mFrontendTests; DemuxTests mDemuxTests; FilterTests mFilterTests; + DvrTests mDvrTests; +}; +class TunerHidlTest : public testing::TestWithParam<std::string> { + public: virtual void SetUp() override { mService = ITuner::getService(GetParam()); ASSERT_NE(mService, nullptr); @@ -229,23 +153,14 @@ class TunerHidlTest : public testing::TestWithParam<std::string> { 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; + sp<ITuner> mService; + FrontendTests mFrontendTests; + DemuxTests mDemuxTests; + FilterTests mFilterTests; - AssertionResult openDvrInDemux(DvrType type); - AssertionResult configDvr(DvrSettings setting); - AssertionResult getDvrMQDescriptor(); + sp<IDescrambler> mDescrambler; - AssertionResult createDescrambler(); + AssertionResult createDescrambler(uint32_t demuxId); AssertionResult closeDescrambler(); AssertionResult playbackDataFlowTest(vector<FilterConfig> filterConf, PlaybackConf playbackConf, @@ -257,4 +172,4 @@ class TunerHidlTest : public testing::TestWithParam<std::string> { void broadcastSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf); }; -} // namespace
\ No newline at end of file +} // namespace diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h index 10c60142ba..1c25c51cf9 100644 --- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h +++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h @@ -21,12 +21,15 @@ #include <hidl/Status.h> #include <hidlmemory/FrameworkUtils.h> +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::DemuxFilterSettings; using android::hardware::tv::tuner::V1_0::DemuxFilterType; using android::hardware::tv::tuner::V1_0::DemuxTpid; 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::FrontendDvbtBandwidth; using android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate; using android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation; @@ -37,6 +40,8 @@ using android::hardware::tv::tuner::V1_0::FrontendDvbtStandard; 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 android::hardware::tv::tuner::V1_0::PlaybackSettings; +using android::hardware::tv::tuner::V1_0::RecordSettings; typedef enum { TS_VIDEO0, @@ -60,9 +65,15 @@ typedef enum { SCAN_MAX, } FrontendScan; +typedef enum { + DVR_RECORD0, + DVR_PLAYBACK0, + DVR_MAX, +} Dvr; + struct FilterConfig { DemuxFilterType type; - DemuxFilterSettings setting; + DemuxFilterSettings settings; }; struct FrontendConfig { @@ -78,10 +89,16 @@ struct ChannelConfig { DemuxTpid audioPid; }; +struct DvrConfig { + DvrType type; + DvrSettings settings; +}; + static FrontendConfig frontendArray[FILTER_MAX]; static FrontendConfig frontendScanArray[SCAN_MAX]; static ChannelConfig channelArray[FRONTEND_MAX]; static FilterConfig filterArray[FILTER_MAX]; +static DvrConfig dvrArray[DVR_MAX]; static vector<string> goldenOutputFiles; /** Configuration array for the frontend tune test */ @@ -124,40 +141,62 @@ inline void initFilterConfig() { // TS VIDEO filter setting for default implementation testing filterArray[TS_VIDEO0].type.mainType = DemuxFilterMainType::TS; filterArray[TS_VIDEO0].type.subType.tsFilterType(DemuxTsFilterType::VIDEO); - filterArray[TS_VIDEO0].setting.ts().tpid = 119; - filterArray[TS_VIDEO0].setting.ts().filterSettings.av({.isPassthrough = false}); + filterArray[TS_VIDEO0].settings.ts().tpid = 119; + filterArray[TS_VIDEO0].settings.ts().filterSettings.av({.isPassthrough = false}); filterArray[TS_VIDEO1].type.mainType = DemuxFilterMainType::TS; filterArray[TS_VIDEO1].type.subType.tsFilterType(DemuxTsFilterType::VIDEO); - filterArray[TS_VIDEO1].setting.ts().tpid = 81; - filterArray[TS_VIDEO1].setting.ts().filterSettings.av({.isPassthrough = false}); + filterArray[TS_VIDEO1].settings.ts().tpid = 81; + filterArray[TS_VIDEO1].settings.ts().filterSettings.av({.isPassthrough = false}); // TS AUDIO filter setting filterArray[TS_AUDIO0].type.mainType = DemuxFilterMainType::TS; filterArray[TS_AUDIO0].type.subType.tsFilterType(DemuxTsFilterType::AUDIO); - filterArray[TS_AUDIO0].setting.ts().tpid = 84; - filterArray[TS_AUDIO0].setting.ts().filterSettings.av({.isPassthrough = false}); + filterArray[TS_AUDIO0].settings.ts().tpid = 84; + filterArray[TS_AUDIO0].settings.ts().filterSettings.av({.isPassthrough = false}); // TS PES filter setting filterArray[TS_PES0].type.mainType = DemuxFilterMainType::TS; filterArray[TS_PES0].type.subType.tsFilterType(DemuxTsFilterType::PES); - filterArray[TS_PES0].setting.ts().tpid = 256; - filterArray[TS_PES0].setting.ts().filterSettings.pesData({ + filterArray[TS_PES0].settings.ts().tpid = 256; + filterArray[TS_PES0].settings.ts().filterSettings.pesData({ .isRaw = false, .streamId = 0xbd, }); // TS PCR filter setting filterArray[TS_PCR0].type.mainType = DemuxFilterMainType::TS; filterArray[TS_PCR0].type.subType.tsFilterType(DemuxTsFilterType::PCR); - filterArray[TS_PCR0].setting.ts().tpid = 81; - filterArray[TS_PCR0].setting.ts().filterSettings.noinit(); + filterArray[TS_PCR0].settings.ts().tpid = 81; + filterArray[TS_PCR0].settings.ts().filterSettings.noinit(); // TS filter setting filterArray[TS_TS0].type.mainType = DemuxFilterMainType::TS; filterArray[TS_TS0].type.subType.tsFilterType(DemuxTsFilterType::TS); - filterArray[TS_TS0].setting.ts().tpid = 48; - filterArray[TS_TS0].setting.ts().filterSettings.noinit(); + filterArray[TS_TS0].settings.ts().tpid = 48; + filterArray[TS_TS0].settings.ts().filterSettings.noinit(); // TS SECTION filter setting filterArray[TS_SECTION0].type.mainType = DemuxFilterMainType::TS; filterArray[TS_SECTION0].type.subType.tsFilterType(DemuxTsFilterType::SECTION); - filterArray[TS_SECTION0].setting.ts().tpid = 48; - filterArray[TS_SECTION0].setting.ts().filterSettings.section({ + filterArray[TS_SECTION0].settings.ts().tpid = 48; + filterArray[TS_SECTION0].settings.ts().filterSettings.section({ .isRaw = false, }); }; + +/** Configuration array for the dvr test */ +inline void initDvrConfig() { + RecordSettings recordSettings{ + .statusMask = 0xf, + .lowThreshold = 0x1000, + .highThreshold = 0x07fff, + .dataFormat = DataFormat::TS, + .packetSize = 188, + }; + dvrArray[DVR_RECORD0].type = DvrType::RECORD; + dvrArray[DVR_RECORD0].settings.record(recordSettings); + PlaybackSettings playbackSettings{ + .statusMask = 0xf, + .lowThreshold = 0x1000, + .highThreshold = 0x07fff, + .dataFormat = DataFormat::TS, + .packetSize = 188, + }; + dvrArray[DVR_PLAYBACK0].type = DvrType::PLAYBACK; + dvrArray[DVR_PLAYBACK0].settings.playback(playbackSettings); +};
\ No newline at end of file |