mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-02 06:22:53 +00:00
Merge changes from topics "ion", "scan" into rvc-dev
* changes: Align Tuner VTS scan tests with the latest scan mechanism Copy filtered av data to ion buffer to test on cuttlefish
This commit is contained in:
committed by
Android (Google) Code Review
commit
aeaaeaabb1
@@ -24,6 +24,7 @@ cc_defaults {
|
||||
"libfmq",
|
||||
"libhidlbase",
|
||||
"libhidlmemory",
|
||||
"libion",
|
||||
"liblog",
|
||||
"libstagefright_foundation",
|
||||
"libutils",
|
||||
|
||||
@@ -60,6 +60,8 @@ Return<Result> Filter::setDataSource(const sp<IFilter>& filter) {
|
||||
Return<void> Filter::getQueueDesc(getQueueDesc_cb _hidl_cb) {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
|
||||
mIsUsingFMQ = true;
|
||||
|
||||
_hidl_cb(Result::SUCCESS, *mFilterMQ->getDesc());
|
||||
return Void();
|
||||
}
|
||||
@@ -120,9 +122,13 @@ 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 (mDataId2Avfd.find(avDataId) == mDataId2Avfd.end()) {
|
||||
return Result::INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
::close(mDataId2Avfd[avDataId]);
|
||||
return Result::SUCCESS;
|
||||
}
|
||||
|
||||
@@ -174,14 +180,21 @@ void Filter::filterThreadLoop() {
|
||||
// Event Callback without waiting for the DATA_CONSUMED to init the process.
|
||||
while (mFilterThreadRunning) {
|
||||
if (mFilterEvent.events.size() == 0) {
|
||||
ALOGD("[Filter] wait for filter data output.");
|
||||
if (DEBUG_FILTER) {
|
||||
ALOGD("[Filter] wait for filter data output.");
|
||||
}
|
||||
usleep(1000 * 1000);
|
||||
continue;
|
||||
}
|
||||
// After successfully write, send a callback and wait for the read to be done
|
||||
mCallback->onFilterEvent(mFilterEvent);
|
||||
freeAvHandle();
|
||||
mFilterEvent.events.resize(0);
|
||||
mFilterStatus = DemuxFilterStatus::DATA_READY;
|
||||
if (mCallback == nullptr) {
|
||||
ALOGD("[Filter] filter %d does not hava callback. Ending thread", mFilterId);
|
||||
break;
|
||||
}
|
||||
mCallback->onFilterStatus(mFilterStatus);
|
||||
break;
|
||||
}
|
||||
@@ -191,7 +204,7 @@ void Filter::filterThreadLoop() {
|
||||
// We do not wait for the last round of written data to be read to finish the thread
|
||||
// because the VTS can verify the reading itself.
|
||||
for (int i = 0; i < SECTION_WRITE_COUNT; i++) {
|
||||
while (mFilterThreadRunning) {
|
||||
while (mFilterThreadRunning && mIsUsingFMQ) {
|
||||
status_t status = mFilterEventFlag->wait(
|
||||
static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
|
||||
WAIT_TIMEOUT, true /* retry on spurious wake */);
|
||||
@@ -202,11 +215,6 @@ void Filter::filterThreadLoop() {
|
||||
break;
|
||||
}
|
||||
|
||||
if (mCallback == nullptr) {
|
||||
ALOGD("[Filter] filter %d does not hava callback. Ending thread", mFilterId);
|
||||
break;
|
||||
}
|
||||
|
||||
maySendFilterStatusCallback();
|
||||
|
||||
while (mFilterThreadRunning) {
|
||||
@@ -232,7 +240,22 @@ void Filter::filterThreadLoop() {
|
||||
ALOGD("[Filter] filter thread ended.");
|
||||
}
|
||||
|
||||
void Filter::freeAvHandle() {
|
||||
if (mType.mainType != DemuxFilterMainType::TS ||
|
||||
(mType.subType.tsFilterType() == DemuxTsFilterType::AUDIO &&
|
||||
mType.subType.tsFilterType() == DemuxTsFilterType::VIDEO)) {
|
||||
return;
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
void Filter::maySendFilterStatusCallback() {
|
||||
if (!mIsUsingFMQ) {
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(mFilterStatusLock);
|
||||
int availableToRead = mFilterMQ->availableToRead();
|
||||
int availableToWrite = mFilterMQ->availableToWrite();
|
||||
@@ -409,19 +432,88 @@ Result Filter::startTsFilterHandler() {
|
||||
}
|
||||
|
||||
Result Filter::startMediaFilterHandler() {
|
||||
DemuxFilterMediaEvent mediaEvent;
|
||||
mediaEvent = {
|
||||
// temp dump meta data
|
||||
.pts = 0,
|
||||
.dataLength = 530,
|
||||
.avMemory = nullptr,
|
||||
.isSecureMemory = false,
|
||||
};
|
||||
mFilterEvent.events.resize(1);
|
||||
mFilterEvent.events[0].media(mediaEvent);
|
||||
std::lock_guard<std::mutex> lock(mFilterEventLock);
|
||||
if (mFilterOutput.empty()) {
|
||||
return Result::SUCCESS;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mFilterOutput.size(); i += 188) {
|
||||
if (mPesSizeLeft == 0) {
|
||||
uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) |
|
||||
mFilterOutput[i + 6];
|
||||
if (DEBUG_FILTER) {
|
||||
ALOGD("[Filter] prefix %d", prefix);
|
||||
}
|
||||
if (prefix == 0x000001) {
|
||||
// TODO handle mulptiple Pes filters
|
||||
mPesSizeLeft = (mFilterOutput[i + 8] << 8) | mFilterOutput[i + 9];
|
||||
mPesSizeLeft += 6;
|
||||
if (DEBUG_FILTER) {
|
||||
ALOGD("[Filter] pes data length %d", mPesSizeLeft);
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
int endPoint = min(184, mPesSizeLeft);
|
||||
// append data and check size
|
||||
vector<uint8_t>::const_iterator first = mFilterOutput.begin() + i + 4;
|
||||
vector<uint8_t>::const_iterator last = mFilterOutput.begin() + i + 4 + endPoint;
|
||||
mPesOutput.insert(mPesOutput.end(), first, last);
|
||||
// size does not match then continue
|
||||
mPesSizeLeft -= endPoint;
|
||||
if (DEBUG_FILTER) {
|
||||
ALOGD("[Filter] pes data left %d", mPesSizeLeft);
|
||||
}
|
||||
if (mPesSizeLeft > 0 || mAvBufferCopyCount++ < 10) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int av_fd = createAvIonFd(mPesOutput.size());
|
||||
if (av_fd == -1) {
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
// copy the filtered data to the buffer
|
||||
uint8_t* avBuffer = getIonBuffer(av_fd, mPesOutput.size());
|
||||
if (avBuffer == NULL) {
|
||||
return Result::UNKNOWN_ERROR;
|
||||
}
|
||||
memcpy(avBuffer, mPesOutput.data(), mPesOutput.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>(mPesOutput.size()),
|
||||
.avDataId = dataId,
|
||||
};
|
||||
int size = mFilterEvent.events.size();
|
||||
mFilterEvent.events.resize(size + 1);
|
||||
mFilterEvent.events[size].media(mediaEvent);
|
||||
|
||||
// Clear and log
|
||||
mPesOutput.clear();
|
||||
mAvBufferCopyCount = 0;
|
||||
::close(av_fd);
|
||||
if (DEBUG_FILTER) {
|
||||
ALOGD("[Filter] assembled av data length %d", mediaEvent.dataLength);
|
||||
}
|
||||
}
|
||||
|
||||
mFilterOutput.clear();
|
||||
// TODO handle write FQM for media stream
|
||||
|
||||
return Result::SUCCESS;
|
||||
}
|
||||
|
||||
@@ -493,6 +585,42 @@ void Filter::detachFilterFromRecord() {
|
||||
mDvr = nullptr;
|
||||
}
|
||||
|
||||
int Filter::createAvIonFd(int size) {
|
||||
// Create an ion fd and allocate an av fd mapped to a buffer to it.
|
||||
int ion_fd = ion_open();
|
||||
if (ion_fd == -1) {
|
||||
ALOGE("[Filter] Failed to open ion fd %d", errno);
|
||||
return -1;
|
||||
}
|
||||
int av_fd = -1;
|
||||
ion_alloc_fd(dup(ion_fd), size, 0 /*align*/, ION_HEAP_SYSTEM_MASK, 0 /*flags*/, &av_fd);
|
||||
if (av_fd == -1) {
|
||||
ALOGE("[Filter] Failed to create av fd %d", errno);
|
||||
return -1;
|
||||
}
|
||||
return av_fd;
|
||||
}
|
||||
|
||||
uint8_t* Filter::getIonBuffer(int fd, int size) {
|
||||
uint8_t* avBuf = static_cast<uint8_t*>(
|
||||
mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 /*offset*/));
|
||||
if (avBuf == MAP_FAILED) {
|
||||
ALOGE("[Filter] fail to allocate buffer %d", errno);
|
||||
return NULL;
|
||||
}
|
||||
return avBuf;
|
||||
}
|
||||
|
||||
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);
|
||||
if (nativeHandle == NULL) {
|
||||
ALOGE("[Filter] Failed to create native_handle %d", errno);
|
||||
return NULL;
|
||||
}
|
||||
nativeHandle->data[0] = dup(fd);
|
||||
return nativeHandle;
|
||||
}
|
||||
} // namespace implementation
|
||||
} // namespace V1_0
|
||||
} // namespace tuner
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <android/hardware/tv/tuner/1.0/IFilter.h>
|
||||
#include <fmq/MessageQueue.h>
|
||||
#include <ion/ion.h>
|
||||
#include <math.h>
|
||||
#include <set>
|
||||
#include "Demux.h"
|
||||
@@ -87,6 +88,7 @@ class Filter : public IFilter {
|
||||
Result startRecordFilterHandler();
|
||||
void attachFilterToRecord(const sp<Dvr> dvr);
|
||||
void detachFilterFromRecord();
|
||||
void freeAvHandle();
|
||||
|
||||
private:
|
||||
// Tuner service
|
||||
@@ -109,6 +111,7 @@ class Filter : public IFilter {
|
||||
vector<uint8_t> mFilterOutput;
|
||||
vector<uint8_t> mRecordFilterOutput;
|
||||
unique_ptr<FilterMQ> mFilterMQ;
|
||||
bool mIsUsingFMQ = false;
|
||||
EventFlag* mFilterEventFlag;
|
||||
DemuxFilterEvent mFilterEvent;
|
||||
|
||||
@@ -160,6 +163,10 @@ class Filter : public IFilter {
|
||||
static void* __threadLoopFilter(void* user);
|
||||
void filterThreadLoop();
|
||||
|
||||
int createAvIonFd(int size);
|
||||
uint8_t* getIonBuffer(int fd, int size);
|
||||
native_handle_t* createNativeHandle(int fd);
|
||||
|
||||
/**
|
||||
* Lock to protect writes to the FMQs
|
||||
*/
|
||||
@@ -181,6 +188,11 @@ class Filter : public IFilter {
|
||||
// TODO handle mulptiple Pes filters
|
||||
int mPesSizeLeft = 0;
|
||||
vector<uint8_t> mPesOutput;
|
||||
|
||||
// A map from data id to ion handle
|
||||
std::map<uint64_t, int> mDataId2Avfd;
|
||||
uint64_t mLastUsedDataId = 1;
|
||||
int mAvBufferCopyCount = 0;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
@@ -63,9 +63,6 @@ Return<Result> Frontend::tune(const FrontendSettings& /* settings */) {
|
||||
return Result::INVALID_STATE;
|
||||
}
|
||||
|
||||
// TODO dynamically allocate file to the source file
|
||||
mSourceStreamFile = FRONTEND_STREAM_FILE;
|
||||
|
||||
mCallback->onEvent(FrontendEventType::LOCKED);
|
||||
return Result::SUCCESS;
|
||||
}
|
||||
@@ -180,7 +177,7 @@ FrontendId Frontend::getFrontendId() {
|
||||
}
|
||||
|
||||
string Frontend::getSourceFile() {
|
||||
return mSourceStreamFile;
|
||||
return FRONTEND_STREAM_FILE;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
@@ -76,7 +76,6 @@ class Frontend : public IFrontend {
|
||||
FrontendId mId = 0;
|
||||
|
||||
const string FRONTEND_STREAM_FILE = "/vendor/etc/dumpTs3.ts";
|
||||
string mSourceStreamFile;
|
||||
std::ifstream mFrontendData;
|
||||
};
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ Return<void> Tuner::openDescrambler(openDescrambler_cb _hidl_cb) {
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> Tuner::getFrontendInfo(FrontendId /* frontendId */, getFrontendInfo_cb _hidl_cb) {
|
||||
Return<void> Tuner::getFrontendInfo(FrontendId /*frontendId*/, getFrontendInfo_cb _hidl_cb) {
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
|
||||
vector<FrontendStatusType> statusCaps = {
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
#include "VtsHalTvTunerV1_0TestConfigurations.h"
|
||||
|
||||
#define WAIT_TIMEOUT 3000000000
|
||||
#define WAIT_TIMEOUT_data_ready 3000000000 * 4
|
||||
|
||||
using android::Condition;
|
||||
using android::IMemory;
|
||||
@@ -57,6 +56,7 @@ using android::Mutex;
|
||||
using android::sp;
|
||||
using android::hardware::EventFlag;
|
||||
using android::hardware::fromHeap;
|
||||
using android::hardware::hidl_handle;
|
||||
using android::hardware::hidl_string;
|
||||
using android::hardware::hidl_vec;
|
||||
using android::hardware::HidlMemory;
|
||||
@@ -68,6 +68,7 @@ using android::hardware::Void;
|
||||
using android::hardware::tv::tuner::V1_0::DataFormat;
|
||||
using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
|
||||
using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
|
||||
using android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent;
|
||||
using android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
|
||||
using android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent;
|
||||
using android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings;
|
||||
@@ -156,7 +157,6 @@ const std::vector<uint8_t> goldenDataOutputBuffer{
|
||||
// const uint16_t FMQ_SIZE_4K = 0x1000;
|
||||
const uint32_t FMQ_SIZE_1M = 0x100000;
|
||||
const uint32_t FMQ_SIZE_16M = 0x1000000;
|
||||
const uint8_t FRONTEND_EVENT_CALLBACK_WAIT_COUNT = 4;
|
||||
|
||||
enum FilterEventType : uint8_t {
|
||||
UNDEFINED,
|
||||
@@ -179,52 +179,65 @@ class FrontendCallback : public IFrontendCallback {
|
||||
public:
|
||||
virtual Return<void> onEvent(FrontendEventType frontendEventType) override {
|
||||
android::Mutex::Autolock autoLock(mMsgLock);
|
||||
ALOGD("[vts] frontend event received. Type: %d", frontendEventType);
|
||||
mEventReceived = true;
|
||||
mEventType = frontendEventType;
|
||||
mMsgCondition.signal();
|
||||
return Void();
|
||||
switch (frontendEventType) {
|
||||
case FrontendEventType::LOCKED:
|
||||
mLockMsgReceived = true;
|
||||
mLockMsgCondition.signal();
|
||||
return Void();
|
||||
default:
|
||||
// do nothing
|
||||
return Void();
|
||||
}
|
||||
}
|
||||
|
||||
virtual Return<void> onScanMessage(FrontendScanMessageType type,
|
||||
const FrontendScanMessage& message) override {
|
||||
android::Mutex::Autolock autoLock(mMsgLock);
|
||||
ALOGD("[vts] scan message. Type: %d", mScanMessageType);
|
||||
while (!mScanMsgProcessed) {
|
||||
mMsgCondition.wait(mMsgLock);
|
||||
}
|
||||
ALOGD("[vts] frontend scan message. Type: %d", type);
|
||||
mScanMessageReceived = true;
|
||||
mScanMsgProcessed = false;
|
||||
mScanMessageType = type;
|
||||
mScanLockMessageReceived =
|
||||
mScanLockMessageReceived | (type == FrontendScanMessageType::LOCKED);
|
||||
mScanMessage = message;
|
||||
mMsgCondition.signal();
|
||||
return Void();
|
||||
};
|
||||
}
|
||||
|
||||
void tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings);
|
||||
void tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings);
|
||||
void scanTestOnMessageLock(sp<IFrontend>& frontend, FrontendSettings settings,
|
||||
FrontendScanType type);
|
||||
void scanTest(sp<IFrontend>& frontend, FrontendConfig config, FrontendScanType type);
|
||||
|
||||
// Helper methods
|
||||
uint32_t getTargetFrequency(FrontendSettings settings, FrontendType type);
|
||||
void resetBlindScanStartingFrequency(FrontendConfig config, uint32_t resetingFreq);
|
||||
|
||||
private:
|
||||
bool mEventReceived = false;
|
||||
bool mScanMessageReceived = false;
|
||||
bool mScanLockMessageReceived = false;
|
||||
FrontendEventType mEventType;
|
||||
bool mLockMsgReceived = false;
|
||||
bool mScanMsgProcessed = true;
|
||||
FrontendScanMessageType mScanMessageType;
|
||||
FrontendScanMessage mScanMessage;
|
||||
hidl_vec<uint8_t> mEventMessage;
|
||||
android::Mutex mMsgLock;
|
||||
android::Condition mMsgCondition;
|
||||
uint8_t mOnEvenRetry = 0;
|
||||
android::Condition mLockMsgCondition;
|
||||
};
|
||||
|
||||
void FrontendCallback::tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings) {
|
||||
Result result = frontend->tune(settings);
|
||||
|
||||
EXPECT_TRUE(result == Result::SUCCESS);
|
||||
|
||||
android::Mutex::Autolock autoLock(mMsgLock);
|
||||
while (!mEventReceived) {
|
||||
if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
|
||||
EXPECT_TRUE(false) << "event not received within timeout";
|
||||
EXPECT_TRUE(false) << "Event not received within timeout";
|
||||
mLockMsgReceived = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -233,61 +246,134 @@ void FrontendCallback::tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendS
|
||||
|
||||
void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings) {
|
||||
Result result = frontend->tune(settings);
|
||||
|
||||
EXPECT_TRUE(result == Result::SUCCESS);
|
||||
|
||||
android::Mutex::Autolock autoLock(mMsgLock);
|
||||
wait:
|
||||
while (!mEventReceived) {
|
||||
if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
|
||||
EXPECT_TRUE(false) << "event not received within timeout";
|
||||
while (!mLockMsgReceived) {
|
||||
if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
|
||||
EXPECT_TRUE(false) << "Event LOCKED not received within timeout";
|
||||
mLockMsgReceived = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mEventType != FrontendEventType::LOCKED) {
|
||||
ALOGD("[vts] frontend callback event received. Type: %d", mEventType);
|
||||
mEventReceived = false;
|
||||
if (mOnEvenRetry++ < FRONTEND_EVENT_CALLBACK_WAIT_COUNT) {
|
||||
goto wait;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(mEventType == FrontendEventType::LOCKED) << "LOCK event not received";
|
||||
mEventReceived = false;
|
||||
mOnEvenRetry = 0;
|
||||
mLockMsgReceived = false;
|
||||
}
|
||||
|
||||
void FrontendCallback::scanTestOnMessageLock(sp<IFrontend>& frontend, FrontendSettings settings,
|
||||
FrontendScanType type) {
|
||||
Result result = frontend->scan(settings, type);
|
||||
EXPECT_TRUE(result == Result::SUCCESS);
|
||||
android::Mutex::Autolock autoLock(mMsgLock);
|
||||
int messagesCount = 0;
|
||||
void FrontendCallback::scanTest(sp<IFrontend>& frontend, FrontendConfig config,
|
||||
FrontendScanType type) {
|
||||
uint32_t targetFrequency = getTargetFrequency(config.settings, config.type);
|
||||
if (type == FrontendScanType::SCAN_BLIND) {
|
||||
// reset the frequency in the scan configuration to test blind scan. The settings param of
|
||||
// passed in means the real input config on the transponder connected to the DUT.
|
||||
// We want the blind the test to start from lower frequency than this to check the blind
|
||||
// scan implementation.
|
||||
resetBlindScanStartingFrequency(config, targetFrequency - 100);
|
||||
}
|
||||
|
||||
Result result = frontend->scan(config.settings, type);
|
||||
EXPECT_TRUE(result == Result::SUCCESS);
|
||||
|
||||
bool scanMsgLockedReceived = false;
|
||||
bool targetFrequencyReceived = false;
|
||||
|
||||
android::Mutex::Autolock autoLock(mMsgLock);
|
||||
wait:
|
||||
int count = 0;
|
||||
while (!mScanMessageReceived) {
|
||||
if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
|
||||
ALOGD("[vts] waiting for scan message callback...");
|
||||
if (count++ > 10) {
|
||||
EXPECT_TRUE(false) << "WAITING TOO LONG!!";
|
||||
return;
|
||||
}
|
||||
EXPECT_TRUE(false) << "Scan message not received within timeout";
|
||||
mScanMessageReceived = false;
|
||||
mScanMsgProcessed = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mScanMessageType != FrontendScanMessageType::END) {
|
||||
ALOGD("[vts] frontend scan message received. Type: %d", mScanMessageType);
|
||||
mScanMessageReceived = false;
|
||||
if (messagesCount++ > 3) {
|
||||
EXPECT_TRUE(false) << "WAITING ON TOO MANY MSGS!!";
|
||||
return;
|
||||
if (mScanMessageType == FrontendScanMessageType::LOCKED) {
|
||||
scanMsgLockedReceived = true;
|
||||
Result result = frontend->scan(config.settings, type);
|
||||
EXPECT_TRUE(result == Result::SUCCESS);
|
||||
}
|
||||
|
||||
if (mScanMessageType == FrontendScanMessageType::FREQUENCY) {
|
||||
targetFrequencyReceived = mScanMessage.frequencies().size() > 0 &&
|
||||
mScanMessage.frequencies()[0] == targetFrequency;
|
||||
}
|
||||
|
||||
if (mScanMessageType == FrontendScanMessageType::PROGRESS_PERCENT) {
|
||||
ALOGD("[vts] Scan in progress...[%d%%]", mScanMessage.progressPercent());
|
||||
}
|
||||
|
||||
mScanMessageReceived = false;
|
||||
mScanMsgProcessed = true;
|
||||
mMsgCondition.signal();
|
||||
goto wait;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(mScanLockMessageReceived) << "scan lock message not received before scan ended";
|
||||
EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END";
|
||||
EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
|
||||
mScanMessageReceived = false;
|
||||
mScanLockMessageReceived = false;
|
||||
mScanMsgProcessed = true;
|
||||
}
|
||||
|
||||
uint32_t FrontendCallback::getTargetFrequency(FrontendSettings settings, FrontendType type) {
|
||||
switch (type) {
|
||||
case FrontendType::ANALOG:
|
||||
return settings.analog().frequency;
|
||||
case FrontendType::ATSC:
|
||||
return settings.atsc().frequency;
|
||||
case FrontendType::ATSC3:
|
||||
return settings.atsc3().frequency;
|
||||
case FrontendType::DVBC:
|
||||
return settings.dvbc().frequency;
|
||||
case FrontendType::DVBS:
|
||||
return settings.dvbs().frequency;
|
||||
case FrontendType::DVBT:
|
||||
return settings.dvbt().frequency;
|
||||
case FrontendType::ISDBS:
|
||||
return settings.isdbs().frequency;
|
||||
case FrontendType::ISDBS3:
|
||||
return settings.isdbs3().frequency;
|
||||
case FrontendType::ISDBT:
|
||||
return settings.isdbt().frequency;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig config,
|
||||
uint32_t resetingFreq) {
|
||||
switch (config.type) {
|
||||
case FrontendType::ANALOG:
|
||||
config.settings.analog().frequency = resetingFreq;
|
||||
break;
|
||||
case FrontendType::ATSC:
|
||||
config.settings.atsc().frequency = resetingFreq;
|
||||
break;
|
||||
case FrontendType::ATSC3:
|
||||
config.settings.atsc3().frequency = resetingFreq;
|
||||
break;
|
||||
case FrontendType::DVBC:
|
||||
config.settings.dvbc().frequency = resetingFreq;
|
||||
break;
|
||||
case FrontendType::DVBS:
|
||||
config.settings.dvbs().frequency = resetingFreq;
|
||||
break;
|
||||
case FrontendType::DVBT:
|
||||
config.settings.dvbt().frequency = resetingFreq;
|
||||
break;
|
||||
case FrontendType::ISDBS:
|
||||
config.settings.isdbs().frequency = resetingFreq;
|
||||
break;
|
||||
case FrontendType::ISDBS3:
|
||||
config.settings.isdbs3().frequency = resetingFreq;
|
||||
break;
|
||||
case FrontendType::ISDBT:
|
||||
config.settings.isdbt().frequency = resetingFreq;
|
||||
break;
|
||||
default:
|
||||
// do nothing
|
||||
return;
|
||||
}
|
||||
}
|
||||
/******************************** End FrontendCallback **********************************/
|
||||
|
||||
@@ -313,6 +399,7 @@ 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 testFilterDataOutput();
|
||||
@@ -324,6 +411,7 @@ class FilterCallback : public IFilterCallback {
|
||||
void updateFilterMQ(MQDesc& filterMQDescriptor);
|
||||
void updateGoldenOutputMap(string goldenOutputFile);
|
||||
bool readFilterEventData();
|
||||
bool dumpAvData(DemuxFilterMediaEvent event);
|
||||
|
||||
private:
|
||||
struct FilterThreadArgs {
|
||||
@@ -336,6 +424,7 @@ class FilterCallback : public IFilterCallback {
|
||||
string mFilterIdToGoldenOutput;
|
||||
|
||||
uint32_t mFilterId;
|
||||
sp<IFilter> mFilter;
|
||||
FilterEventType mFilterEventType;
|
||||
std::unique_ptr<FilterMQ> mFilterMQ;
|
||||
EventFlag* mFilterMQEventFlag;
|
||||
@@ -407,7 +496,7 @@ void FilterCallback::filterThreadLoop(DemuxFilterEvent& /* event */) {
|
||||
bool FilterCallback::readFilterEventData() {
|
||||
bool result = false;
|
||||
DemuxFilterEvent filterEvent = mFilterEvent;
|
||||
ALOGW("[vts] reading from filter FMQ %d", mFilterId);
|
||||
ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
|
||||
// todo separate filter handlers
|
||||
for (int i = 0; i < filterEvent.events.size(); i++) {
|
||||
switch (mFilterEventType) {
|
||||
@@ -418,8 +507,7 @@ bool FilterCallback::readFilterEventData() {
|
||||
mDataLength = filterEvent.events[i].pes().dataLength;
|
||||
break;
|
||||
case FilterEventType::MEDIA:
|
||||
mDataLength = filterEvent.events[i].media().dataLength;
|
||||
break;
|
||||
return dumpAvData(filterEvent.events[i].media());
|
||||
case FilterEventType::RECORD:
|
||||
break;
|
||||
case FilterEventType::MMTPRECORD:
|
||||
@@ -443,6 +531,26 @@ bool FilterCallback::readFilterEventData() {
|
||||
mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
|
||||
uint32_t length = event.dataLength;
|
||||
uint64_t dataId = event.avDataId;
|
||||
// read data from buffer pointed by a handle
|
||||
hidl_handle handle = event.avMemory;
|
||||
|
||||
int av_fd = handle.getNativeHandle()->data[0];
|
||||
uint8_t* buffer = static_cast<uint8_t*>(
|
||||
mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0 /*offset*/));
|
||||
if (buffer == MAP_FAILED) {
|
||||
ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
|
||||
return false;
|
||||
}
|
||||
uint8_t output[length + 1];
|
||||
memcpy(output, buffer, length);
|
||||
// print buffer and check with golden output.
|
||||
EXPECT_TRUE(mFilter->releaseAvHandle(handle, dataId) == Result::SUCCESS);
|
||||
return true;
|
||||
}
|
||||
/******************************** End FilterCallback **********************************/
|
||||
|
||||
/******************************** Start DvrCallback **********************************/
|
||||
@@ -731,6 +839,7 @@ class TunerHidlTest : public testing::TestWithParam<std::string> {
|
||||
sp<IFilter> mFilter;
|
||||
std::map<uint32_t, sp<IFilter>> mFilters;
|
||||
std::map<uint32_t, sp<FilterCallback>> mFilterCallbacks;
|
||||
|
||||
sp<FilterCallback> mFilterCallback;
|
||||
sp<DvrCallback> mDvrCallback;
|
||||
MQDesc mFilterMQDescriptor;
|
||||
@@ -826,7 +935,7 @@ AssertionResult TunerHidlTest::scanFrontend(FrontendConfig config, FrontendScanT
|
||||
EXPECT_TRUE(mFrontendInfo.type == config.type)
|
||||
<< "FrontendConfig does not match the frontend info of the given id.";
|
||||
|
||||
mFrontendCallback->scanTestOnMessageLock(mFrontend, config.settings, type);
|
||||
mFrontendCallback->scanTest(mFrontend, config, type);
|
||||
return AssertionResult(true);
|
||||
}
|
||||
|
||||
@@ -926,13 +1035,14 @@ AssertionResult TunerHidlTest::getNewlyOpenedFilterId(uint32_t& filterId) {
|
||||
|
||||
if (status == Result::SUCCESS) {
|
||||
mFilterCallback->setFilterId(mFilterId);
|
||||
mFilterCallback->setFilterInterface(mFilter);
|
||||
mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
|
||||
mFilters[mFilterId] = mFilter;
|
||||
mFilterCallbacks[mFilterId] = mFilterCallback;
|
||||
filterId = mFilterId;
|
||||
}
|
||||
|
||||
return AssertionResult(status == Result::SUCCESS || status == Result::UNAVAILABLE);
|
||||
return AssertionResult(status == Result::SUCCESS);
|
||||
}
|
||||
|
||||
AssertionResult TunerHidlTest::configFilter(DemuxFilterSettings setting, uint32_t filterId) {
|
||||
@@ -1300,7 +1410,6 @@ TEST_P(TunerHidlTest, TuneFrontend) {
|
||||
}
|
||||
ASSERT_TRUE(openFrontend(mFeIds[i]));
|
||||
ASSERT_TRUE(setFrontendCallback());
|
||||
ASSERT_TRUE(stopTuneFrontend());
|
||||
ASSERT_TRUE(tuneFrontend(frontendArray[0]));
|
||||
ASSERT_TRUE(stopTuneFrontend());
|
||||
ASSERT_TRUE(closeFrontend());
|
||||
@@ -1320,13 +1429,31 @@ TEST_P(TunerHidlTest, AutoScanFrontend) {
|
||||
}
|
||||
ASSERT_TRUE(openFrontend(mFeIds[i]));
|
||||
ASSERT_TRUE(setFrontendCallback());
|
||||
ASSERT_TRUE(stopScanFrontend());
|
||||
ASSERT_TRUE(scanFrontend(frontendScanArray[0], FrontendScanType::SCAN_AUTO));
|
||||
ASSERT_TRUE(stopScanFrontend());
|
||||
ASSERT_TRUE(closeFrontend());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(TunerHidlTest, BlindScanFrontend) {
|
||||
description("Run an blind frontend scan with specific setting and check lock scanMessage");
|
||||
ASSERT_TRUE(getFrontendIds());
|
||||
ASSERT_TRUE(mFeIds.size() > 0);
|
||||
|
||||
for (size_t i = 0; i < mFeIds.size(); i++) {
|
||||
ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
|
||||
if (mFrontendInfo.type != frontendArray[0].type) {
|
||||
continue;
|
||||
}
|
||||
ASSERT_TRUE(openFrontend(mFeIds[i]));
|
||||
ASSERT_TRUE(setFrontendCallback());
|
||||
ASSERT_TRUE(scanFrontend(frontendScanArray[0], FrontendScanType::SCAN_BLIND));
|
||||
ASSERT_TRUE(stopScanFrontend());
|
||||
ASSERT_TRUE(closeFrontend());
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*=============================== End Frontend Tests ===============================*/
|
||||
|
||||
/*============================ Start Demux/Filter Tests ============================*/
|
||||
@@ -1535,6 +1662,39 @@ TEST_P(TunerHidlTest, RecordDataFlowWithTsRecordFilterTest) {
|
||||
|
||||
ASSERT_TRUE(recordDataFlowTest(filterConf, recordSetting, goldenOutputFiles));
|
||||
}*/
|
||||
|
||||
TEST_P(TunerHidlTest, AvBufferTest) {
|
||||
description("Test the av filter data bufferring.");
|
||||
|
||||
ASSERT_TRUE(getFrontendIds());
|
||||
ASSERT_TRUE(mFeIds.size() > 0);
|
||||
|
||||
for (size_t i = 0; i < mFeIds.size(); i++) {
|
||||
ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
|
||||
if (mFrontendInfo.type != frontendArray[1].type) {
|
||||
continue;
|
||||
}
|
||||
ASSERT_TRUE(openFrontend(mFeIds[i]));
|
||||
ASSERT_TRUE(setFrontendCallback());
|
||||
ASSERT_TRUE(openDemux());
|
||||
ASSERT_TRUE(openFilterInDemux(filterArray[0].type));
|
||||
uint32_t filterId;
|
||||
ASSERT_TRUE(getNewlyOpenedFilterId(filterId));
|
||||
ASSERT_TRUE(configFilter(filterArray[0].setting, filterId));
|
||||
ASSERT_TRUE(startFilter(filterId));
|
||||
ASSERT_TRUE(setDemuxFrontendDataSource(mFeIds[i]));
|
||||
// tune test
|
||||
ASSERT_TRUE(tuneFrontend(frontendArray[1]));
|
||||
// broadcast data flow test
|
||||
ASSERT_TRUE(broadcastDataFlowTest(goldenOutputFiles));
|
||||
ASSERT_TRUE(stopTuneFrontend());
|
||||
ASSERT_TRUE(stopFilter(filterId));
|
||||
ASSERT_TRUE(closeFilter(filterId));
|
||||
ASSERT_TRUE(closeDemux());
|
||||
ASSERT_TRUE(closeFrontend());
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*============================== End Data Flow Tests ==============================*/
|
||||
/******************************** End Test Entry **********************************/
|
||||
} // namespace
|
||||
|
||||
@@ -64,7 +64,7 @@ using android::hardware::tv::tuner::V1_0::FrontendType;
|
||||
|
||||
namespace {
|
||||
|
||||
#define frontend_transponders_count 1
|
||||
#define frontend_transponders_count 2
|
||||
#define channels_count 1
|
||||
#define frontend_scan_count 1
|
||||
#define filter_count 2
|
||||
@@ -108,13 +108,24 @@ inline void initFrontendConfig() {
|
||||
.standard = FrontendDvbtStandard::T,
|
||||
};
|
||||
frontendArray[0].type = FrontendType::DVBT, frontendArray[0].settings.dvbt(dvbtSettings);
|
||||
frontendArray[1].type = FrontendType::DVBS;
|
||||
};
|
||||
|
||||
/** Configuration array for the frontend scan test */
|
||||
inline void initFrontendScanConfig() {
|
||||
frontendScanArray[0].type = FrontendType::DVBT, frontendScanArray[0].settings.dvbt({
|
||||
.frequency = 577000,
|
||||
});
|
||||
frontendScanArray[0].type = FrontendType::DVBT;
|
||||
frontendScanArray[0].settings.dvbt({
|
||||
.frequency = 578000,
|
||||
.transmissionMode = FrontendDvbtTransmissionMode::MODE_8K,
|
||||
.bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
|
||||
.constellation = FrontendDvbtConstellation::AUTO,
|
||||
.hierarchy = FrontendDvbtHierarchy::AUTO,
|
||||
.hpCoderate = FrontendDvbtCoderate::AUTO,
|
||||
.lpCoderate = FrontendDvbtCoderate::AUTO,
|
||||
.guardInterval = FrontendDvbtGuardInterval::AUTO,
|
||||
.isHighPriority = true,
|
||||
.standard = FrontendDvbtStandard::T,
|
||||
});
|
||||
};
|
||||
|
||||
/** Configuration array for the filter test */
|
||||
@@ -122,7 +133,7 @@ inline void initFilterConfig() {
|
||||
// TS Video filter setting
|
||||
filterArray[0].type.mainType = DemuxFilterMainType::TS;
|
||||
filterArray[0].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
|
||||
filterArray[0].setting.ts().tpid = 49;
|
||||
filterArray[0].setting.ts().tpid = 119;
|
||||
filterArray[0].setting.ts().filterSettings.av({.isPassthrough = false});
|
||||
// TS PES filter setting
|
||||
filterArray[1].type.mainType = DemuxFilterMainType::TS;
|
||||
@@ -134,4 +145,4 @@ inline void initFilterConfig() {
|
||||
});
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user