Tuner HAL Filter APIs default implementation
Bug: 135709325
Test: manual
Change-Id: If10acac560d3130105079121602be576eb0b225a
Merged-In: If10acac560d3130105079121602be576eb0b225a
diff --git a/tv/tuner/1.0/default/Android.bp b/tv/tuner/1.0/default/Android.bp
index 1636537..b211dd2 100644
--- a/tv/tuner/1.0/default/Android.bp
+++ b/tv/tuner/1.0/default/Android.bp
@@ -16,6 +16,8 @@
shared_libs: [
"android.hardware.tv.tuner@1.0",
"android.hidl.memory@1.0",
+ "libcutils",
+ "libfmq",
"libhidlbase",
"libhidlmemory",
"liblog",
diff --git a/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp
index 6f7c68b..4016c5a 100644
--- a/tv/tuner/1.0/default/Demux.cpp
+++ b/tv/tuner/1.0/default/Demux.cpp
@@ -26,12 +26,81 @@
namespace V1_0 {
namespace implementation {
+#define WAIT_TIMEOUT 3000000000
+
+const std::vector<uint8_t> fakeDataInputBuffer{
+ 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
+ 0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
+ 0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
+ 0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
+ 0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
+ 0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
+ 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
+ 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
+ 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
+ 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x2d, 0x20,
+ 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x62, 0x61, 0x63, 0x3d,
+ 0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x65, 0x3d,
+ 0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68, 0x65,
+ 0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
+ 0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e,
+ 0x30, 0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20,
+ 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72,
+ 0x6f, 0x6d, 0x61, 0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69,
+ 0x73, 0x3d, 0x31, 0x20, 0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71,
+ 0x6d, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31,
+ 0x2c, 0x31, 0x31, 0x20, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d,
+ 0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66,
+ 0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d,
+ 0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x68,
+ 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x5f,
+ 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e, 0x72, 0x3d, 0x30, 0x20,
+ 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72, 0x61, 0x79,
+ 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
+ 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
+ 0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30,
+ 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20,
+ 0x73, 0x63, 0x65, 0x6e, 0x65,
+};
+
Demux::Demux(uint32_t demuxId) {
mDemuxId = demuxId;
}
Demux::~Demux() {}
+bool Demux::createAndSaveMQ(uint32_t bufferSize, uint32_t filterId) {
+ ALOGV("%s", __FUNCTION__);
+
+ // Create a synchronized FMQ that supports blocking read/write
+ std::unique_ptr<FilterMQ> tmpFilterMQ =
+ std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
+ if (!tmpFilterMQ->isValid()) {
+ ALOGW("Failed to create FMQ of filter with id: %d", filterId);
+ return false;
+ }
+
+ mFilterMQs.resize(filterId + 1);
+ mFilterMQs[filterId] = std::move(tmpFilterMQ);
+
+ EventFlag* mFilterEventFlag;
+ if (EventFlag::createEventFlag(mFilterMQs[filterId]->getEventFlagWord(), &mFilterEventFlag) !=
+ OK) {
+ return false;
+ }
+ mFilterEventFlags.resize(filterId + 1);
+ mFilterEventFlags[filterId] = mFilterEventFlag;
+ mFilterWriteCount.resize(filterId + 1);
+ mFilterWriteCount[filterId] = 0;
+ mThreadRunning.resize(filterId + 1);
+
+ return true;
+}
+
Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
ALOGV("%s", __FUNCTION__);
@@ -40,11 +109,292 @@
return Result::SUCCESS;
}
+Return<void> Demux::addFilter(DemuxFilterType type, uint32_t bufferSize,
+ const sp<IDemuxCallback>& cb, addFilter_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ uint32_t filterId = mLastUsedFilterId + 1;
+ mLastUsedFilterId += 1;
+
+ if ((type != DemuxFilterType::PCR || type != DemuxFilterType::TS) && cb == nullptr) {
+ ALOGW("callback can't be null");
+ _hidl_cb(Result::INVALID_ARGUMENT, filterId);
+ return Void();
+ }
+ // Add callback
+ mDemuxCallbacks.resize(filterId + 1);
+ mDemuxCallbacks[filterId] = cb;
+
+ // Mapping from the filter ID to the filter type
+ mFilterTypes.resize(filterId + 1);
+ mFilterTypes[filterId] = type;
+
+ if (!createAndSaveMQ(bufferSize, filterId)) {
+ _hidl_cb(Result::UNKNOWN_ERROR, -1);
+ return Void();
+ }
+
+ _hidl_cb(Result::SUCCESS, filterId);
+ return Void();
+}
+
+Return<void> Demux::getFilterQueueDesc(uint32_t filterId, getFilterQueueDesc_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ if (filterId < 0 || filterId > mLastUsedFilterId) {
+ ALOGW("No filter with id: %d exists", filterId);
+ _hidl_cb(Result::INVALID_ARGUMENT, FilterMQ::Descriptor());
+ return Void();
+ }
+
+ _hidl_cb(Result::SUCCESS, *mFilterMQs[filterId]->getDesc());
+ return Void();
+}
+
+Return<Result> Demux::configureFilter(uint32_t /* filterId */,
+ const DemuxFilterSettings& /* settings */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+Return<Result> Demux::startFilter(uint32_t filterId) {
+ ALOGV("%s", __FUNCTION__);
+
+ if (filterId < 0 || filterId > mLastUsedFilterId) {
+ ALOGW("No filter with id: %d exists", filterId);
+ return Result::INVALID_ARGUMENT;
+ }
+
+ DemuxFilterType filterType = mFilterTypes[filterId];
+ Result result;
+ DemuxFilterEvent event{
+ .filterId = filterId,
+ .filterType = filterType,
+ };
+
+ switch (filterType) {
+ case DemuxFilterType::SECTION:
+ result = startSectionFilterHandler(event);
+ break;
+ case DemuxFilterType::PES:
+ result = startPesFilterHandler(event);
+ break;
+ case DemuxFilterType::TS:
+ result = startTsFilterHandler();
+ return Result::SUCCESS;
+ case DemuxFilterType::AUDIO:
+ case DemuxFilterType::VIDEO:
+ result = startMediaFilterHandler(event);
+ break;
+ case DemuxFilterType::RECORD:
+ result = startRecordFilterHandler(event);
+ break;
+ case DemuxFilterType::PCR:
+ result = startPcrFilterHandler();
+ return Result::SUCCESS;
+ default:
+ return Result::UNKNOWN_ERROR;
+ }
+
+ return result;
+}
+
+Return<Result> Demux::stopFilter(uint32_t /* filterId */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+Return<Result> Demux::flushFilter(uint32_t /* filterId */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+Return<Result> Demux::removeFilter(uint32_t /* filterId */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+Return<void> Demux::getAvSyncHwId(uint32_t /* filterId */, getAvSyncHwId_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ AvSyncHwId avSyncHwId = 0;
+
+ _hidl_cb(Result::SUCCESS, avSyncHwId);
+ return Void();
+}
+
+Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ uint64_t avSyncTime = 0;
+
+ _hidl_cb(Result::SUCCESS, avSyncTime);
+ return Void();
+}
+
Return<Result> Demux::close() {
ALOGV("%s", __FUNCTION__);
return Result::SUCCESS;
- ;
+}
+
+bool Demux::writeSectionsAndCreateEvent(DemuxFilterEvent& event, uint32_t sectionNum) {
+ event.events.resize(sectionNum);
+ for (int i = 0; i < sectionNum; i++) {
+ DemuxFilterSectionEvent secEvent;
+ secEvent = {
+ // temp dump meta data
+ .tableId = 0,
+ .version = 1,
+ .sectionNum = 1,
+ .dataLength = 530,
+ };
+ event.events[i].section(secEvent);
+ if (!writeDataToFilterMQ(fakeDataInputBuffer, event.filterId)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Demux::writeDataToFilterMQ(const std::vector<uint8_t>& data, uint32_t filterId) {
+ std::lock_guard<std::mutex> lock(mWriteLock);
+ if (mFilterMQs[filterId]->write(data.data(), data.size())) {
+ return true;
+ }
+ return false;
+}
+
+Result Demux::startSectionFilterHandler(DemuxFilterEvent event) {
+ struct ThreadArgs* threadArgs = (struct ThreadArgs*)malloc(sizeof(struct ThreadArgs));
+ threadArgs->user = this;
+ threadArgs->event = &event;
+
+ pthread_create(&mThreadId, NULL, __threadLoop, (void*)threadArgs);
+ pthread_setname_np(mThreadId, "demux_filter_waiting_loop");
+
+ return Result::SUCCESS;
+}
+
+Result Demux::startPesFilterHandler(DemuxFilterEvent& event) {
+ // TODO generate multiple events in one event callback
+ DemuxFilterPesEvent pesEvent;
+ pesEvent = {
+ // temp dump meta data
+ .streamId = 0,
+ .dataLength = 530,
+ };
+ event.events.resize(1);
+ event.events[0].pes(pesEvent);
+ /*pthread_create(&mThreadId, NULL, __threadLoop, this);
+ pthread_setname_np(mThreadId, "demux_section_filter_waiting_loop");*/
+ if (!writeDataToFilterMQ(fakeDataInputBuffer, event.filterId)) {
+ return Result::INVALID_STATE;
+ }
+
+ if (mDemuxCallbacks[event.filterId] == nullptr) {
+ return Result::NOT_INITIALIZED;
+ }
+
+ mDemuxCallbacks[event.filterId]->onFilterEvent(event);
+ return Result::SUCCESS;
+}
+
+Result Demux::startTsFilterHandler() {
+ // TODO handle starting TS filter
+ return Result::SUCCESS;
+}
+
+Result Demux::startMediaFilterHandler(DemuxFilterEvent& event) {
+ DemuxFilterMediaEvent mediaEvent;
+ mediaEvent = {
+ // temp dump meta data
+ .pts = 0,
+ .dataLength = 530,
+ .secureMemory = nullptr,
+ };
+ event.events.resize(1);
+ event.events[0].media() = mediaEvent;
+ // TODO handle write FQM for media stream
+ return Result::SUCCESS;
+}
+
+Result Demux::startRecordFilterHandler(DemuxFilterEvent& event) {
+ DemuxFilterRecordEvent recordEvent;
+ recordEvent = {
+ // temp dump meta data
+ .tpid = 0,
+ .packetNum = 0,
+ };
+ recordEvent.indexMask.tsIndexMask() = 0x01;
+ event.events.resize(1);
+ event.events[0].ts() = recordEvent;
+ return Result::SUCCESS;
+}
+
+Result Demux::startPcrFilterHandler() {
+ // TODO handle starting PCR filter
+ return Result::SUCCESS;
+}
+
+void* Demux::__threadLoop(void* threadArg) {
+ Demux* const self = static_cast<Demux*>(((struct ThreadArgs*)threadArg)->user);
+ self->filterThreadLoop(((struct ThreadArgs*)threadArg)->event);
+ return 0;
+}
+
+void Demux::filterThreadLoop(DemuxFilterEvent* event) {
+ uint32_t filterId = event->filterId;
+ ALOGD("[Demux] filter %d threadLoop start.", filterId);
+ mThreadRunning[filterId] = true;
+
+ while (mThreadRunning[filterId]) {
+ uint32_t efState = 0;
+ // We do not wait for the last round of writen 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++) {
+ DemuxFilterEvent filterEvent{
+ .filterId = filterId,
+ .filterType = event->filterType,
+ };
+ if (!writeSectionsAndCreateEvent(filterEvent, 2)) {
+ ALOGD("[Demux] filter %d fails to write into FMQ. Ending thread", filterId);
+ break;
+ }
+ mFilterWriteCount[filterId]++;
+ if (mDemuxCallbacks[filterId] == nullptr) {
+ ALOGD("[Demux] filter %d does not hava callback. Ending thread", filterId);
+ break;
+ }
+ // After successfully write, send a callback and wait for the read to be done
+ mDemuxCallbacks[filterId]->onFilterEvent(filterEvent);
+ // We do not wait for the last read to be done
+ // VTS can verify the read result itself.
+ if (i == SECTION_WRITE_COUNT - 1) {
+ ALOGD("[Demux] filter %d writing done. Ending thread", filterId);
+ break;
+ }
+ while (mThreadRunning[filterId]) {
+ status_t status = mFilterEventFlags[filterId]->wait(
+ static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
+ WAIT_TIMEOUT, true /* retry on spurious wake */);
+ if (status != OK) {
+ ALOGD("[Demux] wait for data consumed");
+ continue;
+ }
+ break;
+ }
+ }
+
+ mFilterWriteCount[filterId] = 0;
+ mThreadRunning[filterId] = false;
+ }
+
+ ALOGD("[Demux] filter thread ended.");
}
} // namespace implementation
diff --git a/tv/tuner/1.0/default/Demux.h b/tv/tuner/1.0/default/Demux.h
index 52f3933..8b00266 100644
--- a/tv/tuner/1.0/default/Demux.h
+++ b/tv/tuner/1.0/default/Demux.h
@@ -18,6 +18,7 @@
#define ANDROID_HARDWARE_TV_TUNER_V1_0_DEMUX_H_
#include <android/hardware/tv/tuner/1.0/IDemux.h>
+#include <fmq/MessageQueue.h>
using namespace std;
@@ -28,9 +29,16 @@
namespace V1_0 {
namespace implementation {
+using ::android::hardware::EventFlag;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
using ::android::hardware::tv::tuner::V1_0::IDemux;
+using ::android::hardware::tv::tuner::V1_0::IDemuxCallback;
using ::android::hardware::tv::tuner::V1_0::Result;
+using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
class Demux : public IDemux {
public:
Demux(uint32_t demuxId);
@@ -39,10 +47,90 @@
virtual Return<Result> close() override;
+ virtual Return<void> addFilter(DemuxFilterType type, uint32_t bufferSize,
+ const sp<IDemuxCallback>& cb, addFilter_cb _hidl_cb) override;
+
+ virtual Return<void> getFilterQueueDesc(uint32_t filterId,
+ getFilterQueueDesc_cb _hidl_cb) override;
+
+ virtual Return<Result> configureFilter(uint32_t filterId,
+ const DemuxFilterSettings& settings) override;
+
+ virtual Return<Result> startFilter(uint32_t filterId) override;
+
+ virtual Return<Result> stopFilter(uint32_t filterId) override;
+
+ virtual Return<Result> flushFilter(uint32_t filterId) override;
+
+ virtual Return<Result> removeFilter(uint32_t filterId) override;
+
+ virtual Return<void> getAvSyncHwId(uint32_t filterId, getAvSyncHwId_cb _hidl_cb) override;
+
+ virtual Return<void> getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) override;
+
private:
virtual ~Demux();
+ /**
+ * To create a FilterMQ with the the next available Filter ID.
+ * Creating Event Flag at the same time.
+ * Add the successfully created/saved FilterMQ into the local list.
+ *
+ * Return false is any of the above processes fails.
+ */
+ bool createAndSaveMQ(uint32_t bufferSize, uint32_t filterId);
+ void deleteEventFlag();
+ bool writeDataToFilterMQ(const std::vector<uint8_t>& data, uint32_t filterId);
+ Result startSectionFilterHandler(DemuxFilterEvent event);
+ Result startPesFilterHandler(DemuxFilterEvent& event);
+ Result startTsFilterHandler();
+ Result startMediaFilterHandler(DemuxFilterEvent& event);
+ Result startRecordFilterHandler(DemuxFilterEvent& event);
+ Result startPcrFilterHandler();
+ bool writeSectionsAndCreateEvent(DemuxFilterEvent& event, uint32_t sectionNum);
+ void filterThreadLoop(DemuxFilterEvent* event);
+ static void* __threadLoop(void* data);
+
uint32_t mDemuxId;
uint32_t mSourceFrontendId;
+ /**
+ * Record the last used filer id. Initial value is -1.
+ * Filter Id starts with 0.
+ */
+ uint32_t mLastUsedFilterId = -1;
+ /**
+ * A list of created FilterMQ ptrs.
+ * The array number is the filter ID.
+ */
+ vector<unique_ptr<FilterMQ>> mFilterMQs;
+ vector<DemuxFilterType> mFilterTypes;
+ vector<EventFlag*> mFilterEventFlags;
+ /**
+ * Demux callbacks used on filter events or IO buffer status
+ */
+ vector<sp<IDemuxCallback>> mDemuxCallbacks;
+ /**
+ * How many times a specific filter has written since started
+ */
+ vector<uint16_t> mFilterWriteCount;
+ pthread_t mThreadId = 0;
+ /**
+ * If a specific filter's writing loop is still running
+ */
+ vector<bool> mThreadRunning;
+ /**
+ * Lock to protect writes to the FMQs
+ */
+ std::mutex mWriteLock;
+ /**
+ * How many times a filter should write
+ * TODO make this dynamic/random/can take as a parameter
+ */
+ const uint16_t SECTION_WRITE_COUNT = 10;
+ // A struct that passes the arguments to a newly created filter thread
+ struct ThreadArgs {
+ Demux* user;
+ DemuxFilterEvent* event;
+ };
};
} // namespace implementation
diff --git a/tv/tuner/1.0/default/Descrambler.cpp b/tv/tuner/1.0/default/Descrambler.cpp
index 1af1a2c..085f2c8 100644
--- a/tv/tuner/1.0/default/Descrambler.cpp
+++ b/tv/tuner/1.0/default/Descrambler.cpp
@@ -44,6 +44,24 @@
return Result::SUCCESS;
}
+Return<Result> Descrambler::setKeyToken(const hidl_vec<uint8_t>& /* keyToken */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::addPid(uint16_t /* pid */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::removePid(uint16_t /* pid */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
Return<Result> Descrambler::close() {
ALOGV("%s", __FUNCTION__);
mDemuxSet = false;
diff --git a/tv/tuner/1.0/default/Descrambler.h b/tv/tuner/1.0/default/Descrambler.h
index 2ec8412..436adcf 100644
--- a/tv/tuner/1.0/default/Descrambler.h
+++ b/tv/tuner/1.0/default/Descrambler.h
@@ -38,6 +38,12 @@
virtual Return<Result> setDemuxSource(uint32_t demuxId) override;
+ virtual Return<Result> setKeyToken(const hidl_vec<uint8_t>& keyToken) override;
+
+ virtual Return<Result> addPid(uint16_t pid) override;
+
+ virtual Return<Result> removePid(uint16_t pid) override;
+
virtual Return<Result> close() override;
private: