blob: bd960e704ca530765a3037fc233e232e5415225b [file] [log] [blame]
/*
* Copyright 2021 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.
*/
#define LOG_TAG "FilterClient"
#include "FilterClient.h"
#include <aidl/android/hardware/tv/tuner/DemuxFilterMainType.h>
#include <aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.h>
#include <aidlcommonsupport/NativeHandle.h>
#include <android-base/logging.h>
#include <utils/Log.h>
using ::aidl::android::hardware::common::NativeHandle;
using ::aidl::android::hardware::tv::tuner::DemuxFilterMainType;
using ::aidl::android::hardware::tv::tuner::DemuxFilterSubType;
using ::aidl::android::hardware::tv::tuner::DemuxMmtpFilterSettingsFilterSettings;
using ::aidl::android::hardware::tv::tuner::DemuxMmtpFilterType;
using ::aidl::android::hardware::tv::tuner::DemuxQueueNotifyBits;
using ::aidl::android::hardware::tv::tuner::DemuxTsFilterSettingsFilterSettings;
using ::aidl::android::hardware::tv::tuner::DemuxTsFilterType;
using ::aidl::android::hardware::tv::tuner::ScramblingStatus;
namespace android {
/////////////// FilterClient ///////////////////////
FilterClient::FilterClient(DemuxFilterType type, shared_ptr<ITunerFilter> tunerFilter) {
mTunerFilter = tunerFilter;
mAvSharedHandle = nullptr;
checkIsMediaFilter(type);
}
FilterClient::~FilterClient() {
Mutex::Autolock _l(mLock);
mTunerFilter = nullptr;
mAvSharedHandle = nullptr;
mAvSharedMemSize = 0;
mIsMediaFilter = false;
mIsPassthroughFilter = false;
mFilterMQ = nullptr;
mFilterMQEventFlag = nullptr;
}
int64_t FilterClient::read(int8_t* buffer, int64_t size) {
Result res = getFilterMq();
if (res != Result::SUCCESS) {
return -1;
}
return copyData(buffer, size);
}
SharedHandleInfo FilterClient::getAvSharedHandleInfo() {
handleAvShareMemory();
SharedHandleInfo info{
.sharedHandle = (mIsMediaFilter && !mIsPassthroughFilter) ? mAvSharedHandle : nullptr,
.size = mAvSharedMemSize,
};
return info;
}
Result FilterClient::configure(DemuxFilterSettings configure) {
Result res;
checkIsPassthroughFilter(configure);
Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->configure(configure);
res = ClientHelper::getServiceSpecificErrorCode(s);
if (res == Result::SUCCESS) {
getAvSharedHandleInfo();
}
return res;
}
return Result::INVALID_STATE;
}
Result FilterClient::configureMonitorEvent(int32_t monitorEventType) {
Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->configureMonitorEvent(monitorEventType);
return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
Result FilterClient::configureIpFilterContextId(int32_t cid) {
Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->configureIpFilterContextId(cid);
return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
Result FilterClient::configureAvStreamType(AvStreamType avStreamType) {
Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->configureAvStreamType(avStreamType);
return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
Result FilterClient::start() {
Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->start();
return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
Result FilterClient::stop() {
Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->stop();
return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
Result FilterClient::flush() {
Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->flush();
return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
Result FilterClient::getId(int32_t& id) {
Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->getId(&id);
return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
Result FilterClient::getId64Bit(int64_t& id) {
Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->getId64Bit(&id);
return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
Result FilterClient::releaseAvHandle(native_handle_t* handle, uint64_t avDataId) {
Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->releaseAvHandle(dupToAidl(handle), avDataId);
return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
Result FilterClient::setDataSource(sp<FilterClient> filterClient){
Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->setDataSource(filterClient->getAidlFilter());
return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
Result FilterClient::close() {
Mutex::Autolock _l(mLock);
if (mFilterMQEventFlag != nullptr) {
EventFlag::deleteEventFlag(&mFilterMQEventFlag);
mFilterMQEventFlag = nullptr;
}
if (mFilterMQ != nullptr) {
delete mFilterMQ;
mFilterMQ = nullptr;
}
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->close();
closeAvSharedMemory();
mTunerFilter = nullptr;
return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
string FilterClient::acquireSharedFilterToken() {
Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
string filterToken;
if (mTunerFilter->acquireSharedFilterToken(&filterToken).isOk()) {
return filterToken;
}
}
return "";
}
Result FilterClient::freeSharedFilterToken(const string& filterToken) {
Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->freeSharedFilterToken(filterToken);
return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
/////////////// TunerFilterCallback ///////////////////////
TunerFilterCallback::TunerFilterCallback(sp<FilterClientCallback> filterClientCallback)
: mFilterClientCallback(filterClientCallback) {}
Status TunerFilterCallback::onFilterStatus(DemuxFilterStatus status) {
if (mFilterClientCallback != nullptr) {
mFilterClientCallback->onFilterStatus(status);
return Status::ok();
}
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
}
Status TunerFilterCallback::onFilterEvent(const vector<DemuxFilterEvent>& filterEvents) {
if (mFilterClientCallback != nullptr) {
mFilterClientCallback->onFilterEvent(filterEvents);
return Status::ok();
}
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
}
Result FilterClient::getFilterMq() {
Mutex::Autolock _l(mLock);
if (mFilterMQ != nullptr) {
return Result::SUCCESS;
}
AidlMQDesc aidlMqDesc;
Result res = Result::UNAVAILABLE;
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->getQueueDesc(&aidlMqDesc);
res = ClientHelper::getServiceSpecificErrorCode(s);
if (s.isOk()) {
mFilterMQ = new (nothrow) AidlMQ(aidlMqDesc, false/*resetPointer*/);
EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterMQEventFlag);
}
}
return res;
}
int64_t FilterClient::copyData(int8_t* buffer, int64_t size) {
if (mFilterMQ == nullptr || mFilterMQEventFlag == nullptr) {
return -1;
}
int64_t available = mFilterMQ->availableToRead();
size = min(size, available);
if (mFilterMQ->read(buffer, size)) {
mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
} else {
return -1;
}
return size;
}
void FilterClient::checkIsMediaFilter(DemuxFilterType type) {
if (type.mainType == DemuxFilterMainType::MMTP) {
if (type.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>() ==
DemuxMmtpFilterType::AUDIO ||
type.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>() ==
DemuxMmtpFilterType::VIDEO) {
mIsMediaFilter = true;
return;
}
}
if (type.mainType == DemuxFilterMainType::TS) {
if (type.subType.get<DemuxFilterSubType::Tag::tsFilterType>() == DemuxTsFilterType::AUDIO ||
type.subType.get<DemuxFilterSubType::Tag::tsFilterType>() == DemuxTsFilterType::VIDEO) {
mIsMediaFilter = true;
return;
}
}
mIsMediaFilter = false;
}
void FilterClient::checkIsPassthroughFilter(DemuxFilterSettings configure) {
if (!mIsMediaFilter) {
mIsPassthroughFilter = false;
return;
}
if (configure.getTag() == DemuxFilterSettings::Tag::ts) {
if (configure.get<DemuxFilterSettings::Tag::ts>()
.filterSettings.get<DemuxTsFilterSettingsFilterSettings::Tag::av>()
.isPassthrough) {
mIsPassthroughFilter = true;
return;
}
}
if (configure.getTag() == DemuxFilterSettings::Tag::mmtp) {
if (configure.get<DemuxFilterSettings::Tag::mmtp>()
.filterSettings.get<DemuxMmtpFilterSettingsFilterSettings::Tag::av>()
.isPassthrough) {
mIsPassthroughFilter = true;
return;
}
}
mIsPassthroughFilter = false;
}
void FilterClient::handleAvShareMemory() {
if (mAvSharedHandle != nullptr) {
return;
}
if (mTunerFilter != nullptr && mIsMediaFilter && !mIsPassthroughFilter) {
int64_t size;
NativeHandle avMemory;
Status s = mTunerFilter->getAvSharedHandle(&avMemory, &size);
if (s.isOk()) {
mAvSharedHandle = dupFromAidl(avMemory);
mAvSharedMemSize = size;
}
}
}
void FilterClient::closeAvSharedMemory() {
if (mAvSharedHandle == nullptr) {
mAvSharedMemSize = 0;
return;
}
native_handle_close(mAvSharedHandle);
native_handle_delete(mAvSharedHandle);
mAvSharedMemSize = 0;
mAvSharedHandle = nullptr;
}
Result FilterClient::setDelayHint(const FilterDelayHint& hint) {
if (mTunerFilter) {
Status s = mTunerFilter->setDelayHint(hint);
return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
} // namespace android