| /* |
| * 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 |