summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmy Zhang <amyjojo@google.com>2020-04-08 17:30:52 -0700
committerAmy Zhang <amyjojo@google.com>2020-04-21 01:16:57 -0700
commit0fe25be00596c588a6c76f1d417c0dcd713456e0 (patch)
tree3c80580acb9324df1ce3632717a1b6fc37906844
parent4f6980571a8430eb0c13c033822c470c0aa66a1b (diff)
downloadplatform_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
-rw-r--r--tv/tuner/1.0/default/Demux.cpp8
-rw-r--r--tv/tuner/1.0/default/Demux.h2
-rw-r--r--tv/tuner/1.0/default/Frontend.cpp1
-rw-r--r--tv/tuner/1.0/default/Tuner.cpp9
-rw-r--r--tv/tuner/1.0/default/Tuner.h1
-rw-r--r--tv/tuner/1.0/vts/functional/Android.bp1
-rw-r--r--tv/tuner/1.0/vts/functional/DemuxTests.h3
-rw-r--r--tv/tuner/1.0/vts/functional/DvrTests.cpp267
-rw-r--r--tv/tuner/1.0/vts/functional/DvrTests.h187
-rw-r--r--tv/tuner/1.0/vts/functional/FilterTests.h1
-rw-r--r--tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp350
-rw-r--r--tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h159
-rw-r--r--tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h69
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