/** * Copyright (c) 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_NDEBUG 0 #define LOG_TAG "TunerHidlService" #include "TunerHidlService.h" #include #include #include #include #include #include #include "TunerHelper.h" #include "TunerHidlDemux.h" #include "TunerHidlDescrambler.h" #include "TunerHidlFrontend.h" #include "TunerHidlLnb.h" using ::aidl::android::hardware::tv::tuner::FrontendAnalogCapabilities; using ::aidl::android::hardware::tv::tuner::FrontendAtsc3Capabilities; using ::aidl::android::hardware::tv::tuner::FrontendAtscCapabilities; using ::aidl::android::hardware::tv::tuner::FrontendCapabilities; using ::aidl::android::hardware::tv::tuner::FrontendDtmbCapabilities; using ::aidl::android::hardware::tv::tuner::FrontendDvbcCapabilities; using ::aidl::android::hardware::tv::tuner::FrontendDvbsCapabilities; using ::aidl::android::hardware::tv::tuner::FrontendDvbtCapabilities; using ::aidl::android::hardware::tv::tuner::FrontendIsdbs3Capabilities; using ::aidl::android::hardware::tv::tuner::FrontendIsdbsCapabilities; using ::aidl::android::hardware::tv::tuner::FrontendIsdbtCapabilities; using ::aidl::android::hardware::tv::tuner::FrontendIsdbtTimeInterleaveMode; using ::aidl::android::hardware::tv::tuner::FrontendType; using ::aidl::android::hardware::tv::tuner::Result; using ::aidl::android::media::tv::tunerresourcemanager::TunerFrontendInfo; using ::android::IPCThreadState; using ::android::PermissionCache; using ::android::hardware::hidl_vec; using HidlFrontendId = ::android::hardware::tv::tuner::V1_0::FrontendId; using HidlLnbId = ::android::hardware::tv::tuner::V1_0::LnbId; using HidlFrontendType = ::android::hardware::tv::tuner::V1_1::FrontendType; using namespace std; namespace aidl { namespace android { namespace media { namespace tv { namespace tuner { shared_ptr TunerHidlService::sTunerService = nullptr; TunerHidlService::TunerHidlService() { if (!TunerHelper::checkTunerFeature()) { ALOGD("Device doesn't have tuner hardware."); return; } updateTunerResources(); } TunerHidlService::~TunerHidlService() { mOpenedFrontends.clear(); mLnaStatus = -1; } binder_status_t TunerHidlService::instantiate() { if (HidlITuner::getService() == nullptr) { ALOGD("Failed to get ITuner HIDL HAL"); return STATUS_NAME_NOT_FOUND; } sTunerService = ::ndk::SharedRefBase::make(); return AServiceManager_addService(sTunerService->asBinder().get(), getServiceName()); } shared_ptr TunerHidlService::getTunerService() { return sTunerService; } bool TunerHidlService::hasITuner() { ALOGV("hasITuner"); if (mTuner != nullptr) { return true; } mTuner = HidlITuner::getService(); if (mTuner == nullptr) { ALOGE("Failed to get ITuner service"); return false; } mTunerVersion = TUNER_HAL_VERSION_1_0; mTuner_1_1 = ::android::hardware::tv::tuner::V1_1::ITuner::castFrom(mTuner); if (mTuner_1_1 != nullptr) { mTunerVersion = TUNER_HAL_VERSION_1_1; } else { ALOGD("Failed to get ITuner_1_1 service"); } return true; } bool TunerHidlService::hasITuner_1_1() { ALOGV("hasITuner_1_1"); hasITuner(); return (mTunerVersion == TUNER_HAL_VERSION_1_1); } ::ndk::ScopedAStatus TunerHidlService::openDemux(int32_t /* in_demuxHandle */, shared_ptr* _aidl_return) { ALOGV("openDemux"); if (!hasITuner()) { return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } HidlResult res; uint32_t id; sp demuxSp = nullptr; mTuner->openDemux([&](HidlResult r, uint32_t demuxId, const sp& demux) { demuxSp = demux; id = demuxId; res = r; ALOGD("open demux, id = %d", demuxId); }); if (res == HidlResult::SUCCESS) { *_aidl_return = ::ndk::SharedRefBase::make(demuxSp, id); return ::ndk::ScopedAStatus::ok(); } ALOGW("open demux failed, res = %d", res); return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast(res)); } ::ndk::ScopedAStatus TunerHidlService::getDemuxCaps(DemuxCapabilities* _aidl_return) { ALOGV("getDemuxCaps"); if (!hasITuner()) { return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } HidlResult res; HidlDemuxCapabilities caps; mTuner->getDemuxCaps([&](HidlResult r, const HidlDemuxCapabilities& demuxCaps) { caps = demuxCaps; res = r; }); if (res == HidlResult::SUCCESS) { *_aidl_return = getAidlDemuxCaps(caps); return ::ndk::ScopedAStatus::ok(); } ALOGW("Get demux caps failed, res = %d", res); return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast(res)); } ::ndk::ScopedAStatus TunerHidlService::getFrontendIds(vector* ids) { if (!hasITuner()) { return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } hidl_vec feIds; HidlResult res = getHidlFrontendIds(feIds); if (res != HidlResult::SUCCESS) { return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast(res)); } ids->resize(feIds.size()); copy(feIds.begin(), feIds.end(), ids->begin()); return ::ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus TunerHidlService::getFrontendInfo(int32_t id, FrontendInfo* _aidl_return) { if (!hasITuner()) { ALOGE("ITuner service is not init."); return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } HidlFrontendInfo info; HidlResult res = getHidlFrontendInfo(id, info); if (res != HidlResult::SUCCESS) { return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast(res)); } HidlFrontendDtmbCapabilities dtmbCaps; if (static_cast(info.type) == HidlFrontendType::DTMB) { if (!hasITuner_1_1()) { ALOGE("ITuner_1_1 service is not init."); return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } mTuner_1_1->getFrontendDtmbCapabilities( id, [&](HidlResult r, const HidlFrontendDtmbCapabilities& caps) { dtmbCaps = caps; res = r; }); if (res != HidlResult::SUCCESS) { return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast(res)); } } *_aidl_return = getAidlFrontendInfo(info, dtmbCaps); return ::ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus TunerHidlService::openFrontend(int32_t frontendHandle, shared_ptr* _aidl_return) { if (!hasITuner()) { ALOGE("ITuner service is not init."); return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } HidlResult status; sp frontend; int id = TunerHelper::getResourceIdFromHandle(frontendHandle, FRONTEND); mTuner->openFrontendById(id, [&](HidlResult result, const sp& fe) { frontend = fe; status = result; }); if (status != HidlResult::SUCCESS) { return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast(status)); } shared_ptr tunerFrontend = ::ndk::SharedRefBase::make(frontend, id); if (mLnaStatus != -1) { tunerFrontend->setLna(mLnaStatus == 1); } { Mutex::Autolock _l(mOpenedFrontendsLock); mOpenedFrontends.insert(tunerFrontend); } *_aidl_return = tunerFrontend; return ::ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus TunerHidlService::openLnb(int lnbHandle, shared_ptr* _aidl_return) { if (!hasITuner()) { ALOGD("get ITuner failed"); return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } HidlResult status; sp lnb; int id = TunerHelper::getResourceIdFromHandle(lnbHandle, LNB); mTuner->openLnbById(id, [&](HidlResult result, const sp& lnbSp) { lnb = lnbSp; status = result; }); if (status != HidlResult::SUCCESS) { return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast(status)); } *_aidl_return = ::ndk::SharedRefBase::make(lnb, id); return ::ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus TunerHidlService::openLnbByName(const string& lnbName, shared_ptr* _aidl_return) { if (!hasITuner()) { ALOGE("get ITuner failed"); return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } int lnbId; HidlResult status; sp lnb; mTuner->openLnbByName(lnbName, [&](HidlResult r, HidlLnbId id, const sp& lnbSp) { status = r; lnb = lnbSp; lnbId = static_cast(id); }); if (status != HidlResult::SUCCESS) { return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast(status)); } *_aidl_return = ::ndk::SharedRefBase::make(lnb, lnbId); return ::ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus TunerHidlService::openDescrambler( int32_t /*descramblerHandle*/, shared_ptr* _aidl_return) { if (!hasITuner()) { ALOGD("get ITuner failed"); return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } HidlResult status; sp descrambler; //int id = TunerHelper::getResourceIdFromHandle(descramblerHandle, DESCRAMBLER); mTuner->openDescrambler([&](HidlResult r, const sp& descramblerSp) { status = r; descrambler = descramblerSp; }); if (status != HidlResult::SUCCESS) { return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast(status)); } *_aidl_return = ::ndk::SharedRefBase::make(descrambler); return ::ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus TunerHidlService::getTunerHalVersion(int* _aidl_return) { hasITuner(); *_aidl_return = mTunerVersion; return ::ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus TunerHidlService::openSharedFilter( const string& in_filterToken, const shared_ptr& in_cb, shared_ptr* _aidl_return) { if (!hasITuner()) { ALOGE("get ITuner failed"); return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } if (!PermissionCache::checkCallingPermission(sSharedFilterPermission)) { ALOGE("Request requires android.permission.ACCESS_TV_SHARED_FILTER"); return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } Mutex::Autolock _l(mSharedFiltersLock); if (mSharedFilters.find(in_filterToken) == mSharedFilters.end()) { *_aidl_return = nullptr; ALOGD("fail to find %s", in_filterToken.c_str()); return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::INVALID_STATE)); } shared_ptr filter = mSharedFilters.at(in_filterToken); IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); if (!filter->isSharedFilterAllowed(pid)) { *_aidl_return = nullptr; ALOGD("shared filter %s is opened in the same process", in_filterToken.c_str()); return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::INVALID_STATE)); } filter->attachSharedFilterCallback(in_cb); *_aidl_return = filter; return ::ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus TunerHidlService::setLna(bool bEnable) { if (!hasITuner()) { ALOGE("get ITuner failed"); return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } mLnaStatus = bEnable ? 1 : 0; { Mutex::Autolock _l(mOpenedFrontendsLock); for (auto it = mOpenedFrontends.begin(); it != mOpenedFrontends.end(); ++it) { (*it)->setLna(mLnaStatus == 1); } } return ::ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus TunerHidlService::setMaxNumberOfFrontends(FrontendType /* in_frontendType */, int32_t /* in_maxNumber */) { return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } ::ndk::ScopedAStatus TunerHidlService::getMaxNumberOfFrontends(FrontendType /* in_frontendType */, int32_t* _aidl_return) { *_aidl_return = -1; return ::ndk::ScopedAStatus::fromServiceSpecificError( static_cast(Result::UNAVAILABLE)); } string TunerHidlService::addFilterToShared(const shared_ptr& sharedFilter) { Mutex::Autolock _l(mSharedFiltersLock); // Use sharedFilter address as token. string token = to_string(reinterpret_cast(sharedFilter.get())); mSharedFilters[token] = sharedFilter; return token; } void TunerHidlService::removeSharedFilter(const shared_ptr& sharedFilter) { Mutex::Autolock _l(mSharedFiltersLock); // Use sharedFilter address as token. mSharedFilters.erase(to_string(reinterpret_cast(sharedFilter.get()))); } void TunerHidlService::removeFrontend(const shared_ptr& frontend) { Mutex::Autolock _l(mOpenedFrontendsLock); for (auto it = mOpenedFrontends.begin(); it != mOpenedFrontends.end(); ++it) { if (it->get() == frontend.get()) { mOpenedFrontends.erase(it); break; } } } void TunerHidlService::updateTunerResources() { if (!hasITuner()) { ALOGE("Failed to updateTunerResources"); return; } TunerHelper::updateTunerResources(getTRMFrontendInfos(), getTRMLnbHandles()); } vector TunerHidlService::getTRMFrontendInfos() { vector infos; hidl_vec ids; HidlResult res = getHidlFrontendIds(ids); if (res != HidlResult::SUCCESS) { return infos; } for (int i = 0; i < ids.size(); i++) { HidlFrontendInfo frontendInfo; HidlResult res = getHidlFrontendInfo(static_cast(ids[i]), frontendInfo); if (res != HidlResult::SUCCESS) { continue; } TunerFrontendInfo tunerFrontendInfo{ .handle = TunerHelper::getResourceHandleFromId(static_cast(ids[i]), FRONTEND), .type = static_cast(frontendInfo.type), .exclusiveGroupId = static_cast(frontendInfo.exclusiveGroupId), }; infos.push_back(tunerFrontendInfo); } return infos; } vector TunerHidlService::getTRMLnbHandles() { vector lnbHandles; if (mTuner != nullptr) { HidlResult res; vector lnbIds; mTuner->getLnbIds([&](HidlResult r, const hidl_vec& ids) { lnbIds = ids; res = r; }); if (res == HidlResult::SUCCESS && lnbIds.size() > 0) { for (int i = 0; i < lnbIds.size(); i++) { lnbHandles.push_back( TunerHelper::getResourceHandleFromId(static_cast(lnbIds[i]), LNB)); } } } return lnbHandles; } HidlResult TunerHidlService::getHidlFrontendIds(hidl_vec& ids) { if (mTuner == nullptr) { return HidlResult::NOT_INITIALIZED; } HidlResult res; mTuner->getFrontendIds([&](HidlResult r, const hidl_vec& frontendIds) { ids = frontendIds; res = r; }); return res; } HidlResult TunerHidlService::getHidlFrontendInfo(const int id, HidlFrontendInfo& info) { if (mTuner == nullptr) { return HidlResult::NOT_INITIALIZED; } HidlResult res; mTuner->getFrontendInfo(id, [&](HidlResult r, const HidlFrontendInfo& feInfo) { info = feInfo; res = r; }); return res; } DemuxCapabilities TunerHidlService::getAidlDemuxCaps(const HidlDemuxCapabilities& caps) { DemuxCapabilities aidlCaps{ .numDemux = static_cast(caps.numDemux), .numRecord = static_cast(caps.numRecord), .numPlayback = static_cast(caps.numPlayback), .numTsFilter = static_cast(caps.numTsFilter), .numSectionFilter = static_cast(caps.numSectionFilter), .numAudioFilter = static_cast(caps.numAudioFilter), .numVideoFilter = static_cast(caps.numVideoFilter), .numPesFilter = static_cast(caps.numPesFilter), .numPcrFilter = static_cast(caps.numPcrFilter), .numBytesInSectionFilter = static_cast(caps.numBytesInSectionFilter), .filterCaps = static_cast(caps.filterCaps), .bTimeFilter = caps.bTimeFilter, }; aidlCaps.linkCaps.resize(caps.linkCaps.size()); copy(caps.linkCaps.begin(), caps.linkCaps.end(), aidlCaps.linkCaps.begin()); return aidlCaps; } FrontendInfo TunerHidlService::getAidlFrontendInfo( const HidlFrontendInfo& halInfo, const HidlFrontendDtmbCapabilities& halDtmbCaps) { FrontendInfo info{ .type = static_cast(halInfo.type), .minFrequency = static_cast(halInfo.minFrequency), .maxFrequency = static_cast(halInfo.maxFrequency), .minSymbolRate = static_cast(halInfo.minSymbolRate), .maxSymbolRate = static_cast(halInfo.maxSymbolRate), .acquireRange = static_cast(halInfo.acquireRange), .exclusiveGroupId = static_cast(halInfo.exclusiveGroupId), }; for (int i = 0; i < halInfo.statusCaps.size(); i++) { info.statusCaps.push_back(static_cast(halInfo.statusCaps[i])); } FrontendCapabilities caps; switch (halInfo.type) { case ::android::hardware::tv::tuner::V1_0::FrontendType::ANALOG: { if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::analogCaps == halInfo.frontendCaps.getDiscriminator()) { FrontendAnalogCapabilities analogCaps{ .typeCap = static_cast(halInfo.frontendCaps.analogCaps().typeCap), .sifStandardCap = static_cast(halInfo.frontendCaps.analogCaps().sifStandardCap), }; caps.set(analogCaps); } break; } case ::android::hardware::tv::tuner::V1_0::FrontendType::ATSC: { if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::atscCaps == halInfo.frontendCaps.getDiscriminator()) { FrontendAtscCapabilities atscCaps{ .modulationCap = static_cast(halInfo.frontendCaps.atscCaps().modulationCap), }; caps.set(atscCaps); } break; } case ::android::hardware::tv::tuner::V1_0::FrontendType::ATSC3: { if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::atsc3Caps == halInfo.frontendCaps.getDiscriminator()) { FrontendAtsc3Capabilities atsc3Caps{ .bandwidthCap = static_cast(halInfo.frontendCaps.atsc3Caps().bandwidthCap), .modulationCap = static_cast(halInfo.frontendCaps.atsc3Caps().modulationCap), .timeInterleaveModeCap = static_cast( halInfo.frontendCaps.atsc3Caps().timeInterleaveModeCap), .codeRateCap = static_cast(halInfo.frontendCaps.atsc3Caps().codeRateCap), .demodOutputFormatCap = static_cast( halInfo.frontendCaps.atsc3Caps().demodOutputFormatCap), .fecCap = static_cast(halInfo.frontendCaps.atsc3Caps().fecCap), }; caps.set(atsc3Caps); } break; } case ::android::hardware::tv::tuner::V1_0::FrontendType::DVBC: { if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::dvbcCaps == halInfo.frontendCaps.getDiscriminator()) { FrontendDvbcCapabilities dvbcCaps{ .modulationCap = static_cast(halInfo.frontendCaps.dvbcCaps().modulationCap), .fecCap = static_cast(halInfo.frontendCaps.dvbcCaps().fecCap), .annexCap = static_cast(halInfo.frontendCaps.dvbcCaps().annexCap), }; caps.set(dvbcCaps); } break; } case ::android::hardware::tv::tuner::V1_0::FrontendType::DVBS: { if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::dvbsCaps == halInfo.frontendCaps.getDiscriminator()) { FrontendDvbsCapabilities dvbsCaps{ .modulationCap = static_cast(halInfo.frontendCaps.dvbsCaps().modulationCap), .innerfecCap = static_cast(halInfo.frontendCaps.dvbsCaps().innerfecCap), .standard = static_cast(halInfo.frontendCaps.dvbsCaps().standard), }; caps.set(dvbsCaps); } break; } case ::android::hardware::tv::tuner::V1_0::FrontendType::DVBT: { if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::dvbtCaps == halInfo.frontendCaps.getDiscriminator()) { FrontendDvbtCapabilities dvbtCaps{ .transmissionModeCap = static_cast( halInfo.frontendCaps.dvbtCaps().transmissionModeCap), .bandwidthCap = static_cast(halInfo.frontendCaps.dvbtCaps().bandwidthCap), .constellationCap = static_cast(halInfo.frontendCaps.dvbtCaps().constellationCap), .coderateCap = static_cast(halInfo.frontendCaps.dvbtCaps().coderateCap), .hierarchyCap = static_cast(halInfo.frontendCaps.dvbtCaps().hierarchyCap), .guardIntervalCap = static_cast(halInfo.frontendCaps.dvbtCaps().guardIntervalCap), .isT2Supported = halInfo.frontendCaps.dvbtCaps().isT2Supported, .isMisoSupported = halInfo.frontendCaps.dvbtCaps().isMisoSupported, }; caps.set(dvbtCaps); } break; } case ::android::hardware::tv::tuner::V1_0::FrontendType::ISDBS: { if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::isdbsCaps == halInfo.frontendCaps.getDiscriminator()) { FrontendIsdbsCapabilities isdbsCaps{ .modulationCap = static_cast(halInfo.frontendCaps.isdbsCaps().modulationCap), .coderateCap = static_cast(halInfo.frontendCaps.isdbsCaps().coderateCap), }; caps.set(isdbsCaps); } break; } case ::android::hardware::tv::tuner::V1_0::FrontendType::ISDBS3: { if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::isdbs3Caps == halInfo.frontendCaps.getDiscriminator()) { FrontendIsdbs3Capabilities isdbs3Caps{ .modulationCap = static_cast(halInfo.frontendCaps.isdbs3Caps().modulationCap), .coderateCap = static_cast(halInfo.frontendCaps.isdbs3Caps().coderateCap), }; caps.set(isdbs3Caps); } break; } case ::android::hardware::tv::tuner::V1_0::FrontendType::ISDBT: { if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::isdbtCaps == halInfo.frontendCaps.getDiscriminator()) { FrontendIsdbtCapabilities isdbtCaps{ .modeCap = static_cast(halInfo.frontendCaps.isdbtCaps().modeCap), .bandwidthCap = static_cast(halInfo.frontendCaps.isdbtCaps().bandwidthCap), .modulationCap = static_cast(halInfo.frontendCaps.isdbtCaps().modulationCap), .coderateCap = static_cast(halInfo.frontendCaps.isdbtCaps().coderateCap), .guardIntervalCap = static_cast(halInfo.frontendCaps.isdbtCaps().guardIntervalCap), .timeInterleaveCap = static_cast(FrontendIsdbtTimeInterleaveMode::UNDEFINED), .isSegmentAuto = false, .isFullSegment = false, }; caps.set(isdbtCaps); } break; } default: { if (static_cast(info.type) == HidlFrontendType::DTMB) { FrontendDtmbCapabilities dtmbCaps{ .transmissionModeCap = static_cast(halDtmbCaps.transmissionModeCap), .bandwidthCap = static_cast(halDtmbCaps.bandwidthCap), .modulationCap = static_cast(halDtmbCaps.modulationCap), .codeRateCap = static_cast(halDtmbCaps.codeRateCap), .guardIntervalCap = static_cast(halDtmbCaps.guardIntervalCap), .interleaveModeCap = static_cast(halDtmbCaps.interleaveModeCap), }; caps.set(dtmbCaps); } break; } } info.frontendCaps = caps; return info; } } // namespace tuner } // namespace tv } // namespace media } // namespace android } // namespace aidl