/** * Copyright 2020, 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 "TunerFrontend" #include "TunerFrontend.h" #include "TunerLnb.h" using ::aidl::android::media::tv::tuner::TunerFrontendAtsc3PlpSettings; using ::aidl::android::media::tv::tuner::TunerFrontendScanAtsc3PlpInfo; using ::aidl::android::media::tv::tuner::TunerFrontendStatusAtsc3PlpInfo; using ::aidl::android::media::tv::tuner::TunerFrontendUnionSettings; using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard; using ::android::hardware::tv::tuner::V1_0::FrontendAnalogType; using ::android::hardware::tv::tuner::V1_0::FrontendAtscModulation; using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Bandwidth; using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3CodeRate; using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3DemodOutputFormat; using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Fec; using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Modulation; using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3TimeInterleaveMode; using ::android::hardware::tv::tuner::V1_0::FrontendDvbcAnnex; using ::android::hardware::tv::tuner::V1_0::FrontendDvbcModulation; using ::android::hardware::tv::tuner::V1_0::FrontendDvbcOuterFec; using ::android::hardware::tv::tuner::V1_0::FrontendDvbcSpectralInversion; using ::android::hardware::tv::tuner::V1_0::FrontendDvbsModulation; using ::android::hardware::tv::tuner::V1_0::FrontendDvbsPilot; using ::android::hardware::tv::tuner::V1_0::FrontendDvbsRolloff; using ::android::hardware::tv::tuner::V1_0::FrontendDvbsSettings; using ::android::hardware::tv::tuner::V1_0::FrontendDvbsStandard; using ::android::hardware::tv::tuner::V1_0::FrontendDvbsVcmMode; using ::android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth; using ::android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate; using ::android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation; using ::android::hardware::tv::tuner::V1_0::FrontendDvbtGuardInterval; using ::android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy; using ::android::hardware::tv::tuner::V1_0::FrontendDvbtPlpMode; using ::android::hardware::tv::tuner::V1_0::FrontendDvbtSettings; using ::android::hardware::tv::tuner::V1_0::FrontendDvbtStandard; using ::android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode; using ::android::hardware::tv::tuner::V1_0::FrontendInnerFec; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Coderate; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Modulation; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Rolloff; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Settings; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsCoderate; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsModulation; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsRolloff; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsSettings; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsStreamIdType; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtBandwidth; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtCoderate; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtGuardInterval; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtMode; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtModulation; using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtSettings; using ::android::hardware::tv::tuner::V1_0::FrontendModulationStatus; using ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo; using ::android::hardware::tv::tuner::V1_0::FrontendScanType; using ::android::hardware::tv::tuner::V1_0::FrontendStatusType; using ::android::hardware::tv::tuner::V1_0::Result; using ::android::hardware::tv::tuner::V1_1::FrontendAnalogAftFlag; using ::android::hardware::tv::tuner::V1_1::FrontendBandwidth; using ::android::hardware::tv::tuner::V1_1::FrontendCableTimeInterleaveMode; using ::android::hardware::tv::tuner::V1_1::FrontendDvbcBandwidth; using ::android::hardware::tv::tuner::V1_1::FrontendDtmbBandwidth; using ::android::hardware::tv::tuner::V1_1::FrontendDtmbCodeRate; using ::android::hardware::tv::tuner::V1_1::FrontendDtmbGuardInterval; using ::android::hardware::tv::tuner::V1_1::FrontendDtmbModulation; using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTimeInterleaveMode; using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTransmissionMode; using ::android::hardware::tv::tuner::V1_1::FrontendDvbsScanType; using ::android::hardware::tv::tuner::V1_1::FrontendGuardInterval; using ::android::hardware::tv::tuner::V1_1::FrontendInterleaveMode; using ::android::hardware::tv::tuner::V1_1::FrontendModulation; using ::android::hardware::tv::tuner::V1_1::FrontendRollOff; using ::android::hardware::tv::tuner::V1_1::FrontendTransmissionMode; using ::android::hardware::tv::tuner::V1_1::FrontendSpectralInversion; using ::android::hardware::tv::tuner::V1_1::FrontendStatusTypeExt1_1; namespace android { TunerFrontend::TunerFrontend(sp frontend, int id) { mFrontend = frontend; mFrontend_1_1 = ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend); mId = id; } TunerFrontend::~TunerFrontend() { mFrontend = NULL; mFrontend_1_1 = NULL; mId = -1; } Status TunerFrontend::setCallback( const shared_ptr& tunerFrontendCallback) { if (mFrontend == NULL) { ALOGE("IFrontend is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } if (tunerFrontendCallback == NULL) { return Status::fromServiceSpecificError(static_cast(Result::INVALID_ARGUMENT)); } sp frontendCallback = new FrontendCallback(tunerFrontendCallback); Result status = mFrontend->setCallback(frontendCallback); if (status == Result::SUCCESS) { return Status::ok(); } return Status::fromServiceSpecificError(static_cast(status)); } Status TunerFrontend::tune(const TunerFrontendSettings& settings) { if (mFrontend == NULL) { ALOGE("IFrontend is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } Result status; FrontendSettings frontendSettings = getHidlFrontendSettings(settings); if (settings.isExtended) { if (mFrontend_1_1 == NULL) { ALOGE("IFrontend_1_1 is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } FrontendSettingsExt1_1 frontendSettingsExt = getHidlFrontendSettingsExt(settings); status = mFrontend_1_1->tune_1_1(frontendSettings, frontendSettingsExt); } else { status = mFrontend->tune(frontendSettings); } if (status == Result::SUCCESS) { return Status::ok(); } return Status::fromServiceSpecificError(static_cast(status)); } Status TunerFrontend::stopTune() { if (mFrontend == NULL) { ALOGD("IFrontend is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } Result status = mFrontend->stopTune(); if (status == Result::SUCCESS) { return Status::ok(); } return Status::fromServiceSpecificError(static_cast(status)); } Status TunerFrontend::scan(const TunerFrontendSettings& settings, int frontendScanType) { if (mFrontend == NULL) { ALOGD("IFrontend is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } Result status; FrontendSettings frontendSettings = getHidlFrontendSettings(settings); if (settings.isExtended) { if (mFrontend_1_1 == NULL) { ALOGE("IFrontend_1_1 is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } FrontendSettingsExt1_1 frontendSettingsExt = getHidlFrontendSettingsExt(settings); status = mFrontend_1_1->scan_1_1(frontendSettings, static_cast(frontendScanType), frontendSettingsExt); } else { status = mFrontend->scan( frontendSettings, static_cast(frontendScanType)); } if (status == Result::SUCCESS) { return Status::ok(); } return Status::fromServiceSpecificError(static_cast(status)); } Status TunerFrontend::stopScan() { if (mFrontend == NULL) { ALOGD("IFrontend is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } Result status = mFrontend->stopScan(); if (status == Result::SUCCESS) { return Status::ok(); } return Status::fromServiceSpecificError(static_cast(status)); } Status TunerFrontend::setLnb(const shared_ptr& lnb) { if (mFrontend == NULL) { ALOGD("IFrontend is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } Result status = mFrontend->setLnb(static_cast(lnb.get())->getId()); if (status == Result::SUCCESS) { return Status::ok(); } return Status::fromServiceSpecificError(static_cast(status)); } Status TunerFrontend::setLna(bool bEnable) { if (mFrontend == NULL) { ALOGD("IFrontend is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } Result status = mFrontend->setLna(bEnable); if (status == Result::SUCCESS) { return Status::ok(); } return Status::fromServiceSpecificError(static_cast(status)); } Status TunerFrontend::linkCiCamToFrontend(int ciCamId, int32_t* _aidl_return) { if (mFrontend_1_1 == NULL) { ALOGD("IFrontend_1_1 is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } int ltsId; Result status; mFrontend_1_1->linkCiCam(static_cast(ciCamId), [&](Result r, uint32_t id) { status = r; ltsId = id; }); if (status == Result::SUCCESS) { *_aidl_return = ltsId; return Status::ok(); } return Status::fromServiceSpecificError(static_cast(status)); } Status TunerFrontend::unlinkCiCamToFrontend(int ciCamId) { if (mFrontend_1_1 == NULL) { ALOGD("IFrontend_1_1 is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } Result status = mFrontend_1_1->unlinkCiCam(ciCamId); if (status == Result::SUCCESS) { return Status::ok(); } return Status::fromServiceSpecificError(static_cast(status)); } Status TunerFrontend::close() { if (mFrontend == NULL) { ALOGD("IFrontend is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } Result status = mFrontend->close(); mFrontend = NULL; mFrontend_1_1 = NULL; if (status != Result::SUCCESS) { return Status::fromServiceSpecificError(static_cast(status)); } return Status::ok(); } Status TunerFrontend::getStatus(const vector& statusTypes, vector* _aidl_return) { if (mFrontend == NULL) { ALOGD("IFrontend is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } Result res; vector status; vector types; for (auto s : statusTypes) { types.push_back(static_cast(s)); } mFrontend->getStatus(types, [&](Result r, const hidl_vec& s) { res = r; status = s; }); if (res != Result::SUCCESS) { return Status::fromServiceSpecificError(static_cast(res)); } getAidlFrontendStatus(status, *_aidl_return); return Status::ok(); } Status TunerFrontend::getStatusExtended_1_1(const vector& statusTypes, vector* _aidl_return) { if (mFrontend_1_1 == NULL) { ALOGD("IFrontend_1_1 is not initialized"); return Status::fromServiceSpecificError(static_cast(Result::UNAVAILABLE)); } Result res; vector status; vector types; for (auto s : statusTypes) { types.push_back(static_cast(s)); } mFrontend_1_1->getStatusExt1_1(types, [&](Result r, const hidl_vec& s) { res = r; status = s; }); if (res != Result::SUCCESS) { return Status::fromServiceSpecificError(static_cast(res)); } getAidlFrontendStatusExt(status, *_aidl_return); return Status::ok(); } Status TunerFrontend::getFrontendId(int* _aidl_return) { *_aidl_return = mId; return Status::ok(); } /////////////// FrontendCallback /////////////////////// Return TunerFrontend::FrontendCallback::onEvent(FrontendEventType frontendEventType) { ALOGD("FrontendCallback::onEvent, type=%d", frontendEventType); mTunerFrontendCallback->onEvent((int)frontendEventType); return Void(); } Return TunerFrontend::FrontendCallback::onScanMessage( FrontendScanMessageType type, const FrontendScanMessage& message) { ALOGD("FrontendCallback::onScanMessage, type=%d", type); TunerFrontendScanMessage scanMessage; switch(type) { case FrontendScanMessageType::LOCKED: { scanMessage.set(message.isLocked()); break; } case FrontendScanMessageType::END: { scanMessage.set(message.isEnd()); break; } case FrontendScanMessageType::PROGRESS_PERCENT: { scanMessage.set(message.progressPercent()); break; } case FrontendScanMessageType::FREQUENCY: { auto f = message.frequencies(); vector frequencies(begin(f), end(f)); scanMessage.set(frequencies); break; } case FrontendScanMessageType::SYMBOL_RATE: { auto s = message.symbolRates(); vector symbolRates(begin(s), end(s)); scanMessage.set(symbolRates); break; } case FrontendScanMessageType::HIERARCHY: { scanMessage.set((int)message.hierarchy()); break; } case FrontendScanMessageType::ANALOG_TYPE: { scanMessage.set((int)message.analogType()); break; } case FrontendScanMessageType::PLP_IDS: { auto p = message.plpIds(); vector plpIds(begin(p), end(p)); scanMessage.set(plpIds); break; } case FrontendScanMessageType::GROUP_IDS: { auto g = message.groupIds(); vector groupIds(begin(g), end(g)); scanMessage.set(groupIds); break; } case FrontendScanMessageType::INPUT_STREAM_IDS: { auto i = message.inputStreamIds(); vector streamIds(begin(i), end(i)); scanMessage.set(streamIds); break; } case FrontendScanMessageType::STANDARD: { FrontendScanMessage::Standard std = message.std(); int standard; if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sStd) { standard = (int) std.sStd(); } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::tStd) { standard = (int) std.tStd(); } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sifStd) { standard = (int) std.sifStd(); } scanMessage.set(standard); break; } case FrontendScanMessageType::ATSC3_PLP_INFO: { vector plpInfos = message.atsc3PlpInfos(); vector tunerPlpInfos; for (int i = 0; i < plpInfos.size(); i++) { auto info = plpInfos[i]; int8_t plpId = (int8_t) info.plpId; bool lls = (bool) info.bLlsFlag; TunerFrontendScanAtsc3PlpInfo plpInfo{ .plpId = plpId, .llsFlag = lls, }; tunerPlpInfos.push_back(plpInfo); } scanMessage.set(tunerPlpInfos); break; } default: break; } mTunerFrontendCallback->onScanMessage((int)type, scanMessage); return Void(); } Return TunerFrontend::FrontendCallback::onScanMessageExt1_1( FrontendScanMessageTypeExt1_1 type, const FrontendScanMessageExt1_1& message) { ALOGD("onScanMessageExt1_1::onScanMessage, type=%d", type); TunerFrontendScanMessage scanMessage; switch(type) { case FrontendScanMessageTypeExt1_1::MODULATION: { FrontendModulation m = message.modulation(); int modulation; switch (m.getDiscriminator()) { case FrontendModulation::hidl_discriminator::dvbc: modulation = (int) m.dvbc(); break; case FrontendModulation::hidl_discriminator::dvbt: modulation = (int) m.dvbt(); break; case FrontendModulation::hidl_discriminator::dvbs: modulation = (int) m.dvbs(); break; case FrontendModulation::hidl_discriminator::isdbs: modulation = (int) m.isdbs(); break; case FrontendModulation::hidl_discriminator::isdbs3: modulation = (int) m.isdbs3(); break; case FrontendModulation::hidl_discriminator::isdbt: modulation = (int) m.isdbt(); break; case FrontendModulation::hidl_discriminator::atsc: modulation = (int) m.atsc(); break; case FrontendModulation::hidl_discriminator::atsc3: modulation = (int) m.atsc3(); break; case FrontendModulation::hidl_discriminator::dtmb: modulation = (int) m.dtmb(); break; } scanMessage.set(modulation); break; } case FrontendScanMessageTypeExt1_1::DVBC_ANNEX: { scanMessage.set((int)message.annex()); break; } case FrontendScanMessageTypeExt1_1::HIGH_PRIORITY: { scanMessage.set(message.isHighPriority()); break; } default: break; } mTunerFrontendCallback->onScanMessage((int)type, scanMessage); return Void(); } /////////////// TunerFrontend Helper Methods /////////////////////// void TunerFrontend::getAidlFrontendStatus( vector& hidlStatus, vector& aidlStatus) { for (FrontendStatus s : hidlStatus) { TunerFrontendStatus status; switch (s.getDiscriminator()) { case FrontendStatus::hidl_discriminator::isDemodLocked: { status.set(s.isDemodLocked()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::snr: { status.set((int)s.snr()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::ber: { status.set((int)s.ber()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::per: { status.set((int)s.per()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::preBer: { status.set((int)s.preBer()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::signalQuality: { status.set((int)s.signalQuality()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::signalStrength: { status.set((int)s.signalStrength()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::symbolRate: { status.set((int)s.symbolRate()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::innerFec: { status.set((long)s.innerFec()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::modulation: { switch (s.modulation().getDiscriminator()) { case FrontendModulationStatus::hidl_discriminator::dvbc: status.set((int)s.modulation().dvbc()); aidlStatus.push_back(status); break; case FrontendModulationStatus::hidl_discriminator::dvbs: status.set((int)s.modulation().dvbs()); aidlStatus.push_back(status); break; case FrontendModulationStatus::hidl_discriminator::isdbs: status.set((int)s.modulation().isdbs()); aidlStatus.push_back(status); break; case FrontendModulationStatus::hidl_discriminator::isdbs3: status.set((int)s.modulation().isdbs3()); aidlStatus.push_back(status); break; case FrontendModulationStatus::hidl_discriminator::isdbt: status.set((int)s.modulation().isdbt()); aidlStatus.push_back(status); break; } break; } case FrontendStatus::hidl_discriminator::inversion: { status.set((int)s.inversion()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::lnbVoltage: { status.set((int)s.lnbVoltage()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::plpId: { status.set((int8_t)s.plpId()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::isEWBS: { status.set(s.isEWBS()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::agc: { status.set((int8_t)s.agc()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::isLnaOn: { status.set(s.isLnaOn()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::isLayerError: { vector e(s.isLayerError().begin(), s.isLayerError().end()); status.set(e); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::mer: { status.set((int)s.mer()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::freqOffset: { status.set((int)s.freqOffset()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::hierarchy: { status.set((int)s.hierarchy()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::isRfLocked: { status.set(s.isRfLocked()); aidlStatus.push_back(status); break; } case FrontendStatus::hidl_discriminator::plpInfo: { vector info; for (auto i : s.plpInfo()) { info.push_back({ .plpId = (int8_t)i.plpId, .isLocked = i.isLocked, .uec = (int)i.uec, }); } status.set(info); aidlStatus.push_back(status); break; } } } } void TunerFrontend::getAidlFrontendStatusExt( vector& hidlStatus, vector& aidlStatus) { for (FrontendStatusExt1_1 s : hidlStatus) { TunerFrontendStatus status; switch (s.getDiscriminator()) { case FrontendStatusExt1_1::hidl_discriminator::modulations: { vector aidlMod; for (auto m : s.modulations()) { switch (m.getDiscriminator()) { case FrontendModulation::hidl_discriminator::dvbc: aidlMod.push_back((int)m.dvbc()); break; case FrontendModulation::hidl_discriminator::dvbs: aidlMod.push_back((int)m.dvbs()); break; case FrontendModulation::hidl_discriminator::dvbt: aidlMod.push_back((int)m.dvbt()); break; case FrontendModulation::hidl_discriminator::isdbs: aidlMod.push_back((int)m.isdbs()); break; case FrontendModulation::hidl_discriminator::isdbs3: aidlMod.push_back((int)m.isdbs3()); break; case FrontendModulation::hidl_discriminator::isdbt: aidlMod.push_back((int)m.isdbt()); break; case FrontendModulation::hidl_discriminator::atsc: aidlMod.push_back((int)m.atsc()); break; case FrontendModulation::hidl_discriminator::atsc3: aidlMod.push_back((int)m.atsc3()); break; case FrontendModulation::hidl_discriminator::dtmb: aidlMod.push_back((int)m.dtmb()); break; } } status.set(aidlMod); aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::bers: { vector b(s.bers().begin(), s.bers().end()); status.set(b); aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::codeRates: { vector codeRates; for (auto c : s.codeRates()) { codeRates.push_back((long)c); } status.set(codeRates); aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::bandwidth: { switch (s.bandwidth().getDiscriminator()) { case FrontendBandwidth::hidl_discriminator::atsc3: status.set((int)s.bandwidth().atsc3()); break; case FrontendBandwidth::hidl_discriminator::dvbc: status.set((int)s.bandwidth().dvbc()); break; case FrontendBandwidth::hidl_discriminator::dvbt: status.set((int)s.bandwidth().dvbt()); break; case FrontendBandwidth::hidl_discriminator::isdbt: status.set((int)s.bandwidth().isdbt()); break; case FrontendBandwidth::hidl_discriminator::dtmb: status.set((int)s.bandwidth().dtmb()); break; } aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::interval: { switch (s.interval().getDiscriminator()) { case FrontendGuardInterval::hidl_discriminator::dvbt: status.set((int)s.interval().dvbt()); break; case FrontendGuardInterval::hidl_discriminator::isdbt: status.set((int)s.interval().isdbt()); break; case FrontendGuardInterval::hidl_discriminator::dtmb: status.set((int)s.interval().dtmb()); break; } aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::transmissionMode: { switch (s.transmissionMode().getDiscriminator()) { case FrontendTransmissionMode::hidl_discriminator::dvbt: status.set( (int)s.transmissionMode().dvbt()); break; case FrontendTransmissionMode::hidl_discriminator::isdbt: status.set( (int)s.transmissionMode().isdbt()); break; case FrontendTransmissionMode::hidl_discriminator::dtmb: status.set( (int)s.transmissionMode().dtmb()); break; } aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::uec: { status.set((int)s.uec()); aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::systemId: { status.set((char16_t)s.systemId()); aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::interleaving: { vector aidlInter; for (auto i : s.interleaving()) { switch (i.getDiscriminator()) { case FrontendInterleaveMode::hidl_discriminator::atsc3: aidlInter.push_back((int)i.atsc3()); break; case FrontendInterleaveMode::hidl_discriminator::dvbc: aidlInter.push_back((int)i.dvbc()); break; case FrontendInterleaveMode::hidl_discriminator::dtmb: aidlInter.push_back((int)i.dtmb()); break; } } status.set(aidlInter); aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::isdbtSegment: { auto seg = s.isdbtSegment(); vector i(seg.begin(), seg.end()); status.set(i); aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::tsDataRate: { vector ts(s.tsDataRate().begin(), s.tsDataRate().end()); status.set(ts); aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::rollOff: { switch (s.rollOff().getDiscriminator()) { case FrontendRollOff::hidl_discriminator::dvbs: status.set((int)s.rollOff().dvbs()); break; case FrontendRollOff::hidl_discriminator::isdbs: status.set((int)s.rollOff().isdbs()); break; case FrontendRollOff::hidl_discriminator::isdbs3: status.set((int)s.rollOff().isdbs3()); break; } aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::isMiso: { status.set(s.isMiso()); aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::isLinear: { status.set(s.isLinear()); aidlStatus.push_back(status); break; } case FrontendStatusExt1_1::hidl_discriminator::isShortFrames: { status.set(s.isShortFrames()); aidlStatus.push_back(status); break; } } } } hidl_vec TunerFrontend::getAtsc3PlpSettings( const TunerFrontendAtsc3Settings& settings) { int len = settings.plpSettings.size(); hidl_vec plps = hidl_vec(len); // parse PLP settings for (int i = 0; i < len; i++) { uint8_t plpId = static_cast(settings.plpSettings[i].plpId); FrontendAtsc3Modulation modulation = static_cast(settings.plpSettings[i].modulation); FrontendAtsc3TimeInterleaveMode interleaveMode = static_cast( settings.plpSettings[i].interleaveMode); FrontendAtsc3CodeRate codeRate = static_cast(settings.plpSettings[i].codeRate); FrontendAtsc3Fec fec = static_cast(settings.plpSettings[i].fec); FrontendAtsc3PlpSettings frontendAtsc3PlpSettings { .plpId = plpId, .modulation = modulation, .interleaveMode = interleaveMode, .codeRate = codeRate, .fec = fec, }; plps[i] = frontendAtsc3PlpSettings; } return plps; } FrontendDvbsCodeRate TunerFrontend::getDvbsCodeRate(const TunerFrontendDvbsCodeRate& codeRate) { FrontendInnerFec innerFec = static_cast(codeRate.fec); bool isLinear = codeRate.isLinear; bool isShortFrames = codeRate.isShortFrames; uint32_t bitsPer1000Symbol = static_cast(codeRate.bitsPer1000Symbol); FrontendDvbsCodeRate coderate { .fec = innerFec, .isLinear = isLinear, .isShortFrames = isShortFrames, .bitsPer1000Symbol = bitsPer1000Symbol, }; return coderate; } FrontendSettings TunerFrontend::getHidlFrontendSettings(const TunerFrontendSettings& aidlSettings) { auto settings = aidlSettings.settings; FrontendSettings frontendSettings; switch (settings.getTag()) { case TunerFrontendUnionSettings::analog: { auto analog = settings.get(); frontendSettings.analog({ .frequency = static_cast(analog.frequency), .type = static_cast(analog.signalType), .sifStandard = static_cast(analog.sifStandard), }); break; } case TunerFrontendUnionSettings::atsc: { auto atsc = settings.get(); frontendSettings.atsc({ .frequency = static_cast(atsc.frequency), .modulation = static_cast(atsc.modulation), }); break; } case TunerFrontendUnionSettings::atsc3: { auto atsc3 = settings.get(); frontendSettings.atsc3({ .frequency = static_cast(atsc3.frequency), .bandwidth = static_cast(atsc3.bandwidth), .demodOutputFormat = static_cast( atsc3.demodOutputFormat), .plpSettings = getAtsc3PlpSettings(atsc3), }); break; } case TunerFrontendUnionSettings::cable: { auto dvbc = settings.get(); frontendSettings.dvbc({ .frequency = static_cast(dvbc.frequency), .modulation = static_cast(dvbc.modulation), .fec = static_cast(dvbc.innerFec), .symbolRate = static_cast(dvbc.symbolRate), .outerFec = static_cast(dvbc.outerFec), .annex = static_cast(dvbc.annex), .spectralInversion = static_cast( dvbc.spectralInversion), }); break; } case TunerFrontendUnionSettings::dvbs: { auto dvbs = settings.get(); frontendSettings.dvbs({ .frequency = static_cast(dvbs.frequency), .modulation = static_cast(dvbs.modulation), .coderate = getDvbsCodeRate(dvbs.codeRate), .symbolRate = static_cast(dvbs.symbolRate), .rolloff = static_cast(dvbs.rolloff), .pilot = static_cast(dvbs.pilot), .inputStreamId = static_cast(dvbs.inputStreamId), .standard = static_cast(dvbs.standard), .vcmMode = static_cast(dvbs.vcm), }); break; } case TunerFrontendUnionSettings::dvbt: { auto dvbt = settings.get(); frontendSettings.dvbt({ .frequency = static_cast(dvbt.frequency), .transmissionMode = static_cast( dvbt.transmissionMode), .bandwidth = static_cast(dvbt.bandwidth), .constellation = static_cast(dvbt.constellation), .hierarchy = static_cast(dvbt.hierarchy), .hpCoderate = static_cast(dvbt.hpCodeRate), .lpCoderate = static_cast(dvbt.lpCodeRate), .guardInterval = static_cast(dvbt.guardInterval), .isHighPriority = dvbt.isHighPriority, .standard = static_cast(dvbt.standard), .isMiso = dvbt.isMiso, .plpMode = static_cast(dvbt.plpMode), .plpId = static_cast(dvbt.plpId), .plpGroupId = static_cast(dvbt.plpGroupId), }); break; } case TunerFrontendUnionSettings::isdbs: { auto isdbs = settings.get(); frontendSettings.isdbs({ .frequency = static_cast(isdbs.frequency), .streamId = static_cast(isdbs.streamId), .streamIdType = static_cast(isdbs.streamIdType), .modulation = static_cast(isdbs.modulation), .coderate = static_cast(isdbs.codeRate), .symbolRate = static_cast(isdbs.symbolRate), .rolloff = static_cast(isdbs.rolloff), }); break; } case TunerFrontendUnionSettings::isdbs3: { auto isdbs3 = settings.get(); frontendSettings.isdbs3({ .frequency = static_cast(isdbs3.frequency), .streamId = static_cast(isdbs3.streamId), .streamIdType = static_cast(isdbs3.streamIdType), .modulation = static_cast(isdbs3.modulation), .coderate = static_cast(isdbs3.codeRate), .symbolRate = static_cast(isdbs3.symbolRate), .rolloff = static_cast(isdbs3.rolloff), }); break; } case TunerFrontendUnionSettings::isdbt: { auto isdbt = settings.get(); frontendSettings.isdbt({ .frequency = static_cast(isdbt.frequency), .modulation = static_cast(isdbt.modulation), .bandwidth = static_cast(isdbt.bandwidth), .mode = static_cast(isdbt.mode), .coderate = static_cast(isdbt.codeRate), .guardInterval = static_cast(isdbt.guardInterval), .serviceAreaId = static_cast(isdbt.serviceAreaId), }); break; } default: break; } return frontendSettings; } FrontendSettingsExt1_1 TunerFrontend::getHidlFrontendSettingsExt( const TunerFrontendSettings& aidlSettings) { FrontendSettingsExt1_1 frontendSettingsExt{ .endFrequency = static_cast(aidlSettings.endFrequency), .inversion = static_cast(aidlSettings.inversion), }; auto settings = aidlSettings.settings; switch (settings.getTag()) { case TunerFrontendUnionSettings::analog: { auto analog = settings.get(); if (analog.isExtended) { frontendSettingsExt.settingExt.analog({ .aftFlag = static_cast(analog.aftFlag), }); } else { frontendSettingsExt.settingExt.noinit(); } break; } case TunerFrontendUnionSettings::cable: { auto dvbc = settings.get(); if (dvbc.isExtended) { frontendSettingsExt.settingExt.dvbc({ .interleaveMode = static_cast( dvbc.interleaveMode), .bandwidth = static_cast( dvbc.bandwidth), }); } else { frontendSettingsExt.settingExt.noinit(); } break; } case TunerFrontendUnionSettings::dvbs: { auto dvbs = settings.get(); if (dvbs.isExtended) { frontendSettingsExt.settingExt.dvbs({ .scanType = static_cast(dvbs.scanType), .isDiseqcRxMessage = dvbs.isDiseqcRxMessage, }); } else { frontendSettingsExt.settingExt.noinit(); } break; } case TunerFrontendUnionSettings::dvbt: { auto dvbt = settings.get(); if (dvbt.isExtended) { frontendSettingsExt.settingExt.dvbt({ .constellation = static_cast( dvbt.constellation), .transmissionMode = static_cast( dvbt.transmissionMode), }); } else { frontendSettingsExt.settingExt.noinit(); } break; } case TunerFrontendUnionSettings::dtmb: { auto dtmb = settings.get(); frontendSettingsExt.settingExt.dtmb({ .frequency = static_cast(dtmb.frequency), .transmissionMode = static_cast( dtmb.transmissionMode), .bandwidth = static_cast(dtmb.bandwidth), .modulation = static_cast(dtmb.modulation), .codeRate = static_cast(dtmb.codeRate), .guardInterval = static_cast(dtmb.guardInterval), .interleaveMode = static_cast(dtmb.interleaveMode), }); break; } default: frontendSettingsExt.settingExt.noinit(); break; } return frontendSettingsExt; } } // namespace android