Merge "Add API to get the shared memory Audio/Video handle"

This commit is contained in:
Amy Zhang
2020-09-22 17:17:56 +00:00
committed by Android (Google) Code Review
7 changed files with 394 additions and 60 deletions

View File

@@ -51,4 +51,23 @@ interface IFilter extends @1.0::IFilter {
* UNKNOWN_ERROR if failed for other reasons.
*/
configureIpCid(uint32_t ipCid) generates (Result result);
/**
* Get the shared AV memory handle. Use IFilter.releaseAvHandle to release the handle.
*
* When media filters are opened, call this API to initialize the share memory handle if it's
* needed.
*
* If DemuxFilterMediaEvent.avMemory contains file descriptor, share memory should be ignored.
*
* @return avMemory A handle associated to the shared memory for audio or video.
* avMemory.data[0] is normally an fd for ION memory. When the avMemory->numFd is 0, the
* share memory is not initialized and does not contain valid fd.
* avMemory.data[avMemory.numFds] is an index used as a parameter of
* C2DataIdInfo to build C2 buffer in Codec. No C2 buffer would be created if the index
* does not exist.
* @return avMemSize the size of the shared av memory. It should be ignored when the share
* memory is not initialized.
*/
getAvSharedHandle() generates (Result result, handle avMemory, uint64_t avMemSize);
};

View File

@@ -163,8 +163,17 @@ Return<Result> Filter::flush() {
return Result::SUCCESS;
}
Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/, uint64_t avDataId) {
Return<Result> Filter::releaseAvHandle(const hidl_handle& avMemory, uint64_t avDataId) {
ALOGV("%s", __FUNCTION__);
if ((avMemory.getNativeHandle()->numFds > 0) &&
(mSharedAvMemHandle.getNativeHandle()->numFds > 0) &&
(sameFile(avMemory.getNativeHandle()->data[0],
mSharedAvMemHandle.getNativeHandle()->data[0]))) {
freeSharedAvHandle();
return Result::SUCCESS;
}
if (mDataId2Avfd.find(avDataId) == mDataId2Avfd.end()) {
return Result::INVALID_ARGUMENT;
}
@@ -190,6 +199,35 @@ Return<Result> Filter::configureIpCid(uint32_t ipCid) {
return Result::SUCCESS;
}
Return<void> Filter::getAvSharedHandle(getAvSharedHandle_cb _hidl_cb) {
ALOGV("%s", __FUNCTION__);
if (!mIsMediaFilter) {
_hidl_cb(Result::INVALID_STATE, NULL, BUFFER_SIZE_16M);
return Void();
}
if (mSharedAvMemHandle.getNativeHandle() != nullptr) {
_hidl_cb(Result::SUCCESS, mSharedAvMemHandle, BUFFER_SIZE_16M);
return Void();
}
int av_fd = createAvIonFd(BUFFER_SIZE_16M);
if (av_fd == -1) {
_hidl_cb(Result::UNKNOWN_ERROR, NULL, 0);
}
native_handle_t* nativeHandle = createNativeHandle(av_fd);
if (nativeHandle == NULL) {
_hidl_cb(Result::UNKNOWN_ERROR, NULL, 0);
}
mSharedAvMemHandle.setTo(nativeHandle, /*shouldOwn=*/true);
::close(av_fd);
_hidl_cb(Result::SUCCESS, mSharedAvMemHandle, BUFFER_SIZE_16M);
return Void();
}
bool Filter::createFilterMQ() {
ALOGV("%s", __FUNCTION__);
@@ -313,10 +351,19 @@ void Filter::freeAvHandle() {
}
for (int i = 0; i < mFilterEvent.events.size(); i++) {
::close(mFilterEvent.events[i].media().avMemory.getNativeHandle()->data[0]);
native_handle_close(mFilterEvent.events[i].media().avMemory.getNativeHandle());
native_handle_delete(const_cast<native_handle_t*>(
mFilterEvent.events[i].media().avMemory.getNativeHandle()));
}
}
void Filter::freeSharedAvHandle() {
if (!mIsMediaFilter) {
return;
}
::close(mSharedAvMemHandle.getNativeHandle()->data[0]);
native_handle_delete(const_cast<native_handle_t*>(mSharedAvMemHandle.getNativeHandle()));
}
void Filter::maySendFilterStatusCallback() {
if (!mIsUsingFMQ) {
return;
@@ -509,8 +556,8 @@ Result Filter::startMediaFilterHandler() {
return Result::SUCCESS;
}
Result result;
if (mPts) {
Result result;
result = createMediaFilterEventWithIon(mFilterOutput);
if (result == Result::SUCCESS) {
mFilterOutput.clear();
@@ -551,7 +598,10 @@ Result Filter::startMediaFilterHandler() {
continue;
}
createMediaFilterEventWithIon(mPesOutput);
result = createMediaFilterEventWithIon(mPesOutput);
if (result != Result::SUCCESS) {
return result;
}
}
mFilterOutput.clear();
@@ -560,51 +610,14 @@ Result Filter::startMediaFilterHandler() {
}
Result Filter::createMediaFilterEventWithIon(vector<uint8_t> output) {
int av_fd = createAvIonFd(output.size());
if (av_fd == -1) {
return Result::UNKNOWN_ERROR;
if (mUsingSharedAvMem) {
if (mSharedAvMemHandle.getNativeHandle() == nullptr) {
return Result::UNKNOWN_ERROR;
}
return createShareMemMediaEvents(output);
}
// copy the filtered data to the buffer
uint8_t* avBuffer = getIonBuffer(av_fd, output.size());
if (avBuffer == NULL) {
return Result::UNKNOWN_ERROR;
}
memcpy(avBuffer, output.data(), output.size() * sizeof(uint8_t));
native_handle_t* nativeHandle = createNativeHandle(av_fd);
if (nativeHandle == NULL) {
return Result::UNKNOWN_ERROR;
}
hidl_handle handle;
handle.setTo(nativeHandle, /*shouldOwn=*/true);
// Create a dataId and add a <dataId, av_fd> pair into the dataId2Avfd map
uint64_t dataId = mLastUsedDataId++ /*createdUID*/;
mDataId2Avfd[dataId] = dup(av_fd);
// Create mediaEvent and send callback
DemuxFilterMediaEvent mediaEvent;
mediaEvent = {
.avMemory = std::move(handle),
.dataLength = static_cast<uint32_t>(output.size()),
.avDataId = dataId,
};
if (mPts) {
mediaEvent.pts = mPts;
mPts = 0;
}
int size = mFilterEvent.events.size();
mFilterEvent.events.resize(size + 1);
mFilterEvent.events[size].media(mediaEvent);
// Clear and log
output.clear();
mAvBufferCopyCount = 0;
::close(av_fd);
if (DEBUG_FILTER) {
ALOGD("[Filter] av data length %d", mediaEvent.dataLength);
}
return Result::SUCCESS;
return createIndependentMediaEvents(output);
}
Result Filter::startRecordFilterHandler() {
@@ -713,15 +726,119 @@ uint8_t* Filter::getIonBuffer(int fd, int size) {
}
native_handle_t* Filter::createNativeHandle(int fd) {
// Create a native handle to pass the av fd via the callback event.
native_handle_t* nativeHandle = native_handle_create(/*numFd*/ 1, 0);
native_handle_t* nativeHandle;
if (fd < 0) {
nativeHandle = native_handle_create(/*numFd*/ 0, 0);
} else {
// Create a native handle to pass the av fd via the callback event.
nativeHandle = native_handle_create(/*numFd*/ 1, 0);
}
if (nativeHandle == NULL) {
ALOGE("[Filter] Failed to create native_handle %d", errno);
return NULL;
}
nativeHandle->data[0] = dup(fd);
if (nativeHandle->numFds > 0) {
nativeHandle->data[0] = dup(fd);
}
return nativeHandle;
}
Result Filter::createIndependentMediaEvents(vector<uint8_t> output) {
int av_fd = createAvIonFd(output.size());
if (av_fd == -1) {
return Result::UNKNOWN_ERROR;
}
// copy the filtered data to the buffer
uint8_t* avBuffer = getIonBuffer(av_fd, output.size());
if (avBuffer == NULL) {
return Result::UNKNOWN_ERROR;
}
memcpy(avBuffer, output.data(), output.size() * sizeof(uint8_t));
native_handle_t* nativeHandle = createNativeHandle(av_fd);
if (nativeHandle == NULL) {
return Result::UNKNOWN_ERROR;
}
hidl_handle handle;
handle.setTo(nativeHandle, /*shouldOwn=*/true);
// Create a dataId and add a <dataId, av_fd> pair into the dataId2Avfd map
uint64_t dataId = mLastUsedDataId++ /*createdUID*/;
mDataId2Avfd[dataId] = dup(av_fd);
// Create mediaEvent and send callback
DemuxFilterMediaEvent mediaEvent;
mediaEvent = {
.avMemory = std::move(handle),
.dataLength = static_cast<uint32_t>(output.size()),
.avDataId = dataId,
};
if (mPts) {
mediaEvent.pts = mPts;
mPts = 0;
}
int size = mFilterEvent.events.size();
mFilterEvent.events.resize(size + 1);
mFilterEvent.events[size].media(mediaEvent);
// Clear and log
output.clear();
mAvBufferCopyCount = 0;
::close(av_fd);
if (DEBUG_FILTER) {
ALOGD("[Filter] av data length %d", mediaEvent.dataLength);
}
return Result::SUCCESS;
}
Result Filter::createShareMemMediaEvents(vector<uint8_t> output) {
// copy the filtered data to the shared buffer
uint8_t* sharedAvBuffer = getIonBuffer(mSharedAvMemHandle.getNativeHandle()->data[0],
output.size() + mSharedAvMemOffset);
if (sharedAvBuffer == NULL) {
return Result::UNKNOWN_ERROR;
}
memcpy(sharedAvBuffer + mSharedAvMemOffset, output.data(), output.size() * sizeof(uint8_t));
// Create a memory handle with numFds == 0
native_handle_t* nativeHandle = createNativeHandle(-1);
if (nativeHandle == NULL) {
return Result::UNKNOWN_ERROR;
}
hidl_handle handle;
handle.setTo(nativeHandle, /*shouldOwn=*/true);
// Create mediaEvent and send callback
DemuxFilterMediaEvent mediaEvent;
mediaEvent = {
.offset = static_cast<uint32_t>(mSharedAvMemOffset),
.dataLength = static_cast<uint32_t>(output.size()),
.avMemory = handle,
};
mSharedAvMemOffset += output.size();
if (mPts) {
mediaEvent.pts = mPts;
mPts = 0;
}
int size = mFilterEvent.events.size();
mFilterEvent.events.resize(size + 1);
mFilterEvent.events[size].media(mediaEvent);
// Clear and log
output.clear();
if (DEBUG_FILTER) {
ALOGD("[Filter] shared av data length %d", mediaEvent.dataLength);
}
return Result::SUCCESS;
}
bool Filter::sameFile(int fd1, int fd2) {
struct stat stat1, stat2;
if (fstat(fd1, &stat1) < 0 || fstat(fd2, &stat2) < 0) {
return false;
}
return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino);
}
} // namespace implementation
} // namespace V1_0
} // namespace tuner

View File

@@ -23,6 +23,7 @@
#include <inttypes.h>
#include <ion/ion.h>
#include <math.h>
#include <sys/stat.h>
#include <set>
#include "Demux.h"
#include "Dvr.h"
@@ -43,6 +44,7 @@ using ::android::hardware::MessageQueue;
using ::android::hardware::MQDescriptorSync;
using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
const uint32_t BUFFER_SIZE_16M = 0x1000000;
class Demux;
class Dvr;
@@ -78,6 +80,8 @@ class Filter : public V1_1::IFilter {
virtual Return<Result> configureIpCid(uint32_t ipCid) override;
virtual Return<void> getAvSharedHandle(getAvSharedHandle_cb _hidl_cb) override;
/**
* To create a FilterMQ and its Event Flag.
*
@@ -93,6 +97,7 @@ class Filter : public V1_1::IFilter {
void attachFilterToRecord(const sp<Dvr> dvr);
void detachFilterFromRecord();
void freeAvHandle();
void freeSharedAvHandle();
bool isMediaFilter() { return mIsMediaFilter; };
bool isPcrFilter() { return mIsPcrFilter; };
bool isRecordFilter() { return mIsRecordFilter; };
@@ -185,6 +190,9 @@ class Filter : public V1_1::IFilter {
uint8_t* getIonBuffer(int fd, int size);
native_handle_t* createNativeHandle(int fd);
Result createMediaFilterEventWithIon(vector<uint8_t> output);
Result createIndependentMediaEvents(vector<uint8_t> output);
Result createShareMemMediaEvents(vector<uint8_t> output);
bool sameFile(int fd1, int fd2);
/**
* Lock to protect writes to the FMQs
@@ -212,6 +220,11 @@ class Filter : public V1_1::IFilter {
std::map<uint64_t, int> mDataId2Avfd;
uint64_t mLastUsedDataId = 1;
int mAvBufferCopyCount = 0;
// Shared A/V memory handle
hidl_handle mSharedAvMemHandle;
bool mUsingSharedAvMem = true;
uint32_t mSharedAvMemOffset = 0;
};
} // namespace implementation

View File

@@ -16,22 +16,70 @@
#include "FilterTests.h"
bool FilterCallback::readFilterEventData() {
bool result = false;
ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
void FilterCallback::testFilterDataOutput() {
android::Mutex::Autolock autoLock(mMsgLock);
while (mPidFilterOutputCount < 1) {
if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
return;
}
}
mPidFilterOutputCount = 0;
ALOGW("[vts] pass and stop");
}
void FilterCallback::readFilterEventData() {
ALOGW("[vts] reading filter event");
// todo separate filter handlers
for (int i = 0; i < mFilterEvent.events.size(); i++) {
auto event = mFilterEvent.events[i];
switch (event.getDiscriminator()) {
case DemuxFilterEvent::Event::hidl_discriminator::media:
ALOGD("[vts] Media filter event, avMemHandle numFds=%d.",
event.media().avMemory.getNativeHandle()->numFds);
dumpAvData(event.media());
break;
default:
break;
}
}
for (int i = 0; i < mFilterEventExt.events.size(); i++) {
auto eventExt = mFilterEventExt.events[i];
switch (eventExt.getDiscriminator()) {
case DemuxFilterEventExt::Event::hidl_discriminator::tsRecord:
ALOGW("[vts] Extended TS record filter event, pts=%" PRIu64 ".",
ALOGD("[vts] Extended TS record filter event, pts=%" PRIu64 ".",
eventExt.tsRecord().pts);
break;
default:
break;
}
}
return result;
}
bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
uint32_t length = event.dataLength;
uint32_t offset = event.offset;
// read data from buffer pointed by a handle
hidl_handle handle = event.avMemory;
if (handle.getNativeHandle()->numFds == 0) {
if (mAvSharedHandle == NULL) {
return false;
}
handle = mAvSharedHandle;
}
int av_fd = handle.getNativeHandle()->data[0];
uint8_t* buffer =
static_cast<uint8_t*>(mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0));
if (buffer == MAP_FAILED) {
ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
return false;
}
uint8_t output[length + 1];
memcpy(output, buffer + offset, length);
// print buffer and check with golden output.
::close(av_fd);
return true;
}
AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, uint32_t bufferSize) {
@@ -81,6 +129,33 @@ AssertionResult FilterTests::getNewlyOpenedFilterId_64bit(uint64_t& filterId) {
return AssertionResult(status == Result::SUCCESS);
}
AssertionResult FilterTests::getSharedAvMemoryHandle(uint64_t filterId) {
EXPECT_TRUE(mFilters[filterId]) << "Open media filter first.";
Result status = Result::UNKNOWN_ERROR;
sp<android::hardware::tv::tuner::V1_1::IFilter> filter_v1_1 =
android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilters[filterId]);
if (filter_v1_1 != NULL) {
filter_v1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) {
status = r;
if (status == Result::SUCCESS) {
mFilterCallbacks[mFilterId]->setSharedHandle(avMemory);
mFilterCallbacks[mFilterId]->setMemSize(avMemSize);
mAvSharedHandle = avMemory;
}
});
}
return AssertionResult(status == Result::SUCCESS);
}
AssertionResult FilterTests::releaseShareAvHandle(uint64_t filterId) {
Result status;
EXPECT_TRUE(mFilters[filterId]) << "Open media filter first.";
EXPECT_TRUE(mAvSharedHandle) << "No shared av handle to release.";
status = mFilters[filterId]->releaseAvHandle(mAvSharedHandle, 0 /*dataId*/);
return AssertionResult(status == Result::SUCCESS);
}
AssertionResult FilterTests::configFilter(DemuxFilterSettings setting, uint64_t filterId) {
Result status;
EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";

View File

@@ -46,6 +46,7 @@ using android::hardware::Return;
using android::hardware::Void;
using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
using android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent;
using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
using android::hardware::tv::tuner::V1_0::DemuxFilterType;
@@ -93,7 +94,14 @@ class FilterCallback : public IFilterCallback {
}
virtual Return<void> onFilterEvent(
const android::hardware::tv::tuner::V1_0::DemuxFilterEvent& /*filterEvent*/) override {
const android::hardware::tv::tuner::V1_0::DemuxFilterEvent& filterEvent) override {
android::Mutex::Autolock autoLock(mMsgLock);
// Temprarily we treat the first coming back filter data on the matching pid a success
// once all of the MQ are cleared, means we got all the expected output
mFilterEvent = filterEvent;
readFilterEventData();
mPidFilterOutputCount++;
mMsgCondition.signal();
return Void();
}
@@ -104,8 +112,13 @@ class FilterCallback : public IFilterCallback {
void setFilterId(uint32_t filterId) { mFilterId = filterId; }
void setFilterInterface(sp<IFilter> filter) { mFilter = filter; }
void setFilterEventType(FilterEventType type) { mFilterEventType = type; }
void setSharedHandle(hidl_handle sharedHandle) { mAvSharedHandle = sharedHandle; }
void setMemSize(uint64_t size) { mAvSharedMemSize = size; }
bool readFilterEventData();
void testFilterDataOutput();
void readFilterEventData();
bool dumpAvData(DemuxFilterMediaEvent event);
private:
uint32_t mFilterId;
@@ -114,6 +127,9 @@ class FilterCallback : public IFilterCallback {
DemuxFilterEvent mFilterEvent;
DemuxFilterEventExt mFilterEventExt;
hidl_handle mAvSharedHandle = NULL;
uint64_t mAvSharedMemSize = -1;
android::Mutex mMsgLock;
android::Mutex mFilterOutputLock;
android::Condition mMsgCondition;
@@ -127,10 +143,12 @@ class FilterTests {
void setDemux(sp<IDemux> demux) { mDemux = demux; }
sp<IFilter> getFilterById(uint64_t filterId) { return mFilters[filterId]; }
std::map<uint64_t, sp<FilterCallback>> getFilterCallbacks() { return mFilterCallbacks; }
map<uint64_t, sp<FilterCallback>> getFilterCallbacks() { return mFilterCallbacks; }
AssertionResult openFilterInDemux(DemuxFilterType type, uint32_t bufferSize);
AssertionResult getNewlyOpenedFilterId_64bit(uint64_t& filterId);
AssertionResult getSharedAvMemoryHandle(uint64_t filterId);
AssertionResult releaseShareAvHandle(uint64_t filterId);
AssertionResult configFilter(DemuxFilterSettings setting, uint64_t filterId);
AssertionResult configIpFilterCid(uint32_t ipCid, uint64_t filterId);
AssertionResult getFilterMQDescriptor(uint64_t filterId);
@@ -193,12 +211,14 @@ class FilterTests {
sp<ITuner> mService;
sp<IFilter> mFilter;
sp<IDemux> mDemux;
std::map<uint64_t, sp<IFilter>> mFilters;
std::map<uint64_t, sp<FilterCallback>> mFilterCallbacks;
map<uint64_t, sp<IFilter>> mFilters;
map<uint64_t, sp<FilterCallback>> mFilterCallbacks;
sp<FilterCallback> mFilterCallback;
MQDesc mFilterMQDescriptor;
vector<uint64_t> mUsedFilterIds;
hidl_handle mAvSharedHandle = NULL;
uint64_t mFilterId = -1;
};

View File

@@ -18,6 +18,10 @@
namespace {
AssertionResult TunerBroadcastHidlTest::filterDataOutputTest() {
return filterDataOutputTestBase(mFilterTests);
}
void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig filterConf,
FrontendConfig frontendConf) {
uint32_t feId;
@@ -46,6 +50,38 @@ void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig filterConf,
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
void TunerBroadcastHidlTest::mediaFilterUsingSharedMemoryTest(FilterConfig filterConf,
FrontendConfig frontendConf) {
uint32_t feId;
uint32_t demuxId;
sp<IDemux> demux;
uint64_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));
mFrontendTests.setDemux(demux);
mFilterTests.setDemux(demux);
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
ASSERT_TRUE(mFilterTests.getSharedAvMemoryHandle(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
// tune test
ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
ASSERT_TRUE(filterDataOutputTest());
ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
ASSERT_TRUE(mFilterTests.releaseShareAvHandle(filterId));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
void TunerRecordHidlTest::recordSingleFilterTest(FilterConfig filterConf,
FrontendConfig frontendConf, DvrConfig dvrConf) {
uint32_t feId;
@@ -116,6 +152,16 @@ TEST_P(TunerFrontendHidlTest, BlindScanFrontendWithEndFrequency) {
mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_BLIND);
}
TEST_P(TunerBroadcastHidlTest, MediaFilterWithSharedMemoryHandle) {
description("Test the Media Filter with shared memory handle");
mediaFilterUsingSharedMemoryTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
}
INSTANTIATE_TEST_SUITE_P(
PerInstance, TunerBroadcastHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
android::hardware::PrintInstanceNameToString);
INSTANTIATE_TEST_SUITE_P(
PerInstance, TunerFrontendHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),

View File

@@ -26,6 +26,20 @@ void initConfiguration() {
initDvrConfig();
}
static AssertionResult success() {
return ::testing::AssertionSuccess();
}
AssertionResult filterDataOutputTestBase(FilterTests tests) {
// Data Verify Module
std::map<uint64_t, sp<FilterCallback>>::iterator it;
std::map<uint64_t, sp<FilterCallback>> filterCallbacks = tests.getFilterCallbacks();
for (it = filterCallbacks.begin(); it != filterCallbacks.end(); it++) {
it->second->testFilterDataOutput();
}
return success();
}
class TunerFilterHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
@@ -103,4 +117,34 @@ class TunerFrontendHidlTest : public testing::TestWithParam<std::string> {
};
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFrontendHidlTest);
class TunerBroadcastHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
mService = ITuner::getService(GetParam());
ASSERT_NE(mService, nullptr);
initConfiguration();
mFrontendTests.setService(mService);
mDemuxTests.setService(mService);
mFilterTests.setService(mService);
}
protected:
static void description(const std::string& description) {
RecordProperty("description", description);
}
sp<ITuner> mService;
FrontendTests mFrontendTests;
DemuxTests mDemuxTests;
FilterTests mFilterTests;
AssertionResult filterDataOutputTest();
void mediaFilterUsingSharedMemoryTest(FilterConfig filterConf, FrontendConfig frontendConf);
};
// TODO remove from the allow list once the cf tv target is enabled for testing
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerBroadcastHidlTest);
} // namespace