1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "android.hardware.tv.tuner@1.1-Frontend"
18 
19 #include "Frontend.h"
20 #include <android/hardware/tv/tuner/1.1/IFrontendCallback.h>
21 #include <utils/Log.h>
22 
23 namespace android {
24 namespace hardware {
25 namespace tv {
26 namespace tuner {
27 namespace V1_0 {
28 namespace implementation {
29 
Frontend(FrontendType type,FrontendId id,sp<Tuner> tuner)30 Frontend::Frontend(FrontendType type, FrontendId id, sp<Tuner> tuner) {
31     mType = type;
32     mId = id;
33     mTunerService = tuner;
34     // Init callback to nullptr
35     mCallback = nullptr;
36 }
37 
~Frontend()38 Frontend::~Frontend() {}
39 
close()40 Return<Result> Frontend::close() {
41     ALOGV("%s", __FUNCTION__);
42     // Reset callback
43     mCallback = nullptr;
44     mIsLocked = false;
45     mTunerService->removeFrontend(mId);
46 
47     return Result::SUCCESS;
48 }
49 
setCallback(const sp<IFrontendCallback> & callback)50 Return<Result> Frontend::setCallback(const sp<IFrontendCallback>& callback) {
51     ALOGV("%s", __FUNCTION__);
52     if (callback == nullptr) {
53         ALOGW("[   WARN   ] Set Frontend callback with nullptr");
54         return Result::INVALID_ARGUMENT;
55     }
56 
57     mCallback = callback;
58     return Result::SUCCESS;
59 }
60 
tune(const FrontendSettings &)61 Return<Result> Frontend::tune(const FrontendSettings& /* settings */) {
62     ALOGV("%s", __FUNCTION__);
63     if (mCallback == nullptr) {
64         ALOGW("[   WARN   ] Frontend callback is not set when tune");
65         return Result::INVALID_STATE;
66     }
67 
68     mTunerService->frontendStartTune(mId);
69     mCallback->onEvent(FrontendEventType::LOCKED);
70     mIsLocked = true;
71     return Result::SUCCESS;
72 }
73 
tune_1_1(const FrontendSettings & settings,const V1_1::FrontendSettingsExt1_1 &)74 Return<Result> Frontend::tune_1_1(const FrontendSettings& settings,
75                                   const V1_1::FrontendSettingsExt1_1& /*settingsExt1_1*/) {
76     ALOGV("%s", __FUNCTION__);
77     return tune(settings);
78 }
79 
stopTune()80 Return<Result> Frontend::stopTune() {
81     ALOGV("%s", __FUNCTION__);
82 
83     mTunerService->frontendStopTune(mId);
84     mIsLocked = false;
85 
86     return Result::SUCCESS;
87 }
88 
scan(const FrontendSettings & settings,FrontendScanType type)89 Return<Result> Frontend::scan(const FrontendSettings& settings, FrontendScanType type) {
90     ALOGV("%s", __FUNCTION__);
91 
92     // If it's in middle of scanning, stop it first.
93     if (mScanThread.joinable()) {
94         mScanThread.join();
95     }
96 
97     mFrontendSettings = settings;
98     mFrontendScanType = type;
99     mScanThread = std::thread(&Frontend::scanThreadLoop, this);
100 
101     return Result::SUCCESS;
102 }
103 
scanThreadLoop()104 void Frontend::scanThreadLoop() {
105     FrontendScanMessage msg;
106 
107     if (mIsLocked) {
108         msg.isEnd(true);
109         mCallback->onScanMessage(FrontendScanMessageType::END, msg);
110         return;
111     }
112 
113     uint32_t frequency;
114     switch (mFrontendSettings.getDiscriminator()) {
115         case FrontendSettings::hidl_discriminator::analog:
116             frequency = mFrontendSettings.analog().frequency;
117             break;
118         case FrontendSettings::hidl_discriminator::atsc:
119             frequency = mFrontendSettings.atsc().frequency;
120             break;
121         case FrontendSettings::hidl_discriminator::atsc3:
122             frequency = mFrontendSettings.atsc3().frequency;
123             break;
124         case FrontendSettings::hidl_discriminator::dvbs:
125             frequency = mFrontendSettings.dvbs().frequency;
126             break;
127         case FrontendSettings::hidl_discriminator::dvbc:
128             frequency = mFrontendSettings.dvbc().frequency;
129             break;
130         case FrontendSettings::hidl_discriminator::dvbt:
131             frequency = mFrontendSettings.dvbt().frequency;
132             break;
133         case FrontendSettings::hidl_discriminator::isdbs:
134             frequency = mFrontendSettings.isdbs().frequency;
135             break;
136         case FrontendSettings::hidl_discriminator::isdbs3:
137             frequency = mFrontendSettings.isdbs3().frequency;
138             break;
139         case FrontendSettings::hidl_discriminator::isdbt:
140             frequency = mFrontendSettings.isdbt().frequency;
141             break;
142     }
143 
144     if (mFrontendScanType == FrontendScanType::SCAN_BLIND) {
145         frequency += 100 * 1000;
146     }
147 
148     msg.frequencies({frequency});
149     mCallback->onScanMessage(FrontendScanMessageType::FREQUENCY, msg);
150 
151     msg.progressPercent(20);
152     mCallback->onScanMessage(FrontendScanMessageType::PROGRESS_PERCENT, msg);
153 
154     msg.symbolRates({30});
155     mCallback->onScanMessage(FrontendScanMessageType::SYMBOL_RATE, msg);
156 
157     if (mType == FrontendType::DVBT) {
158         msg.hierarchy(FrontendDvbtHierarchy::HIERARCHY_NON_NATIVE);
159         mCallback->onScanMessage(FrontendScanMessageType::HIERARCHY, msg);
160     }
161 
162     if (mType == FrontendType::ANALOG) {
163         msg.analogType(FrontendAnalogType::PAL);
164         mCallback->onScanMessage(FrontendScanMessageType::ANALOG_TYPE, msg);
165     }
166 
167     msg.plpIds({3});
168     mCallback->onScanMessage(FrontendScanMessageType::PLP_IDS, msg);
169 
170     msg.groupIds({2});
171     mCallback->onScanMessage(FrontendScanMessageType::GROUP_IDS, msg);
172 
173     msg.inputStreamIds({1});
174     mCallback->onScanMessage(FrontendScanMessageType::INPUT_STREAM_IDS, msg);
175 
176     FrontendScanMessage::Standard s;
177     switch (mType) {
178         case FrontendType::DVBT:
179             s.tStd(FrontendDvbtStandard::AUTO);
180             msg.std(s);
181             mCallback->onScanMessage(FrontendScanMessageType::STANDARD, msg);
182             break;
183         case FrontendType::DVBS:
184             s.sStd(FrontendDvbsStandard::AUTO);
185             msg.std(s);
186             mCallback->onScanMessage(FrontendScanMessageType::STANDARD, msg);
187             break;
188         case FrontendType::ANALOG:
189             s.sifStd(FrontendAnalogSifStandard::AUTO);
190             msg.std(s);
191             mCallback->onScanMessage(FrontendScanMessageType::STANDARD, msg);
192             break;
193         default:
194             break;
195     }
196 
197     FrontendScanAtsc3PlpInfo info{
198             .plpId = 1,
199             .bLlsFlag = false,
200     };
201     msg.atsc3PlpInfos({info});
202     mCallback->onScanMessage(FrontendScanMessageType::ATSC3_PLP_INFO, msg);
203 
204     sp<V1_1::IFrontendCallback> frontendCallback_v1_1 =
205             V1_1::IFrontendCallback::castFrom(mCallback);
206     if (frontendCallback_v1_1 != NULL) {
207         V1_1::FrontendScanMessageExt1_1 msg;
208         msg.modulation().dvbc(FrontendDvbcModulation::MOD_16QAM);
209         frontendCallback_v1_1->onScanMessageExt1_1(V1_1::FrontendScanMessageTypeExt1_1::MODULATION,
210                                                    msg);
211         msg.isHighPriority(true);
212         frontendCallback_v1_1->onScanMessageExt1_1(
213                 V1_1::FrontendScanMessageTypeExt1_1::HIGH_PRIORITY, msg);
214     } else {
215         ALOGD("[Frontend] Couldn't cast to V1_1 IFrontendCallback");
216     }
217 
218     msg.isLocked(true);
219     mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
220     mIsLocked = true;
221 }
222 
scan_1_1(const FrontendSettings & settings,FrontendScanType type,const V1_1::FrontendSettingsExt1_1 & settingsExt1_1)223 Return<Result> Frontend::scan_1_1(const FrontendSettings& settings, FrontendScanType type,
224                                   const V1_1::FrontendSettingsExt1_1& settingsExt1_1) {
225     ALOGV("%s", __FUNCTION__);
226     ALOGD("[Frontend] scan_1_1 end frequency %d", settingsExt1_1.endFrequency);
227     return scan(settings, type);
228 }
229 
stopScan()230 Return<Result> Frontend::stopScan() {
231     ALOGV("%s", __FUNCTION__);
232 
233     if (mScanThread.joinable()) {
234         mScanThread.join();
235     }
236 
237     mIsLocked = false;
238     return Result::SUCCESS;
239 }
240 
getStatus(const hidl_vec<FrontendStatusType> & statusTypes,getStatus_cb _hidl_cb)241 Return<void> Frontend::getStatus(const hidl_vec<FrontendStatusType>& statusTypes,
242                                  getStatus_cb _hidl_cb) {
243     ALOGV("%s", __FUNCTION__);
244 
245     vector<FrontendStatus> statuses;
246     for (int i = 0; i < statusTypes.size(); i++) {
247         FrontendStatusType type = statusTypes[i];
248         FrontendStatus status;
249         // assign randomly selected values for testing.
250         switch (type) {
251             case FrontendStatusType::DEMOD_LOCK: {
252                 status.isDemodLocked(true);
253                 break;
254             }
255             case FrontendStatusType::SNR: {
256                 status.snr(221);
257                 break;
258             }
259             case FrontendStatusType::BER: {
260                 status.ber(1);
261                 break;
262             }
263             case FrontendStatusType::PER: {
264                 status.per(2);
265                 break;
266             }
267             case FrontendStatusType::PRE_BER: {
268                 status.preBer(3);
269                 break;
270             }
271             case FrontendStatusType::SIGNAL_QUALITY: {
272                 status.signalQuality(4);
273                 break;
274             }
275             case FrontendStatusType::SIGNAL_STRENGTH: {
276                 status.signalStrength(5);
277                 break;
278             }
279             case FrontendStatusType::SYMBOL_RATE: {
280                 status.symbolRate(6);
281                 break;
282             }
283             case FrontendStatusType::FEC: {
284                 status.innerFec(FrontendInnerFec::FEC_2_9);  // value = 1 << 7
285                 break;
286             }
287             case FrontendStatusType::MODULATION: {
288                 FrontendModulationStatus modulationStatus;
289                 switch (mType) {
290                     case FrontendType::ISDBS: {
291                         modulationStatus.isdbs(
292                                 FrontendIsdbsModulation::MOD_BPSK);  // value = 1 << 1
293                         status.modulation(modulationStatus);
294                         break;
295                     }
296                     case FrontendType::DVBC: {
297                         modulationStatus.dvbc(FrontendDvbcModulation::MOD_16QAM);  // value = 1 << 1
298                         status.modulation(modulationStatus);
299                         break;
300                     }
301                     case FrontendType::DVBS: {
302                         modulationStatus.dvbs(FrontendDvbsModulation::MOD_QPSK);  // value = 1 << 1
303                         status.modulation(modulationStatus);
304                         break;
305                     }
306                     case FrontendType::ISDBS3: {
307                         modulationStatus.isdbs3(
308                                 FrontendIsdbs3Modulation::MOD_BPSK);  // value = 1 << 1
309                         status.modulation(modulationStatus);
310                         break;
311                     }
312                     case FrontendType::ISDBT: {
313                         modulationStatus.isdbt(
314                                 FrontendIsdbtModulation::MOD_DQPSK);  // value = 1 << 1
315                         status.modulation(modulationStatus);
316                         break;
317                     }
318                     default:
319                         break;
320                 }
321                 break;
322             }
323             case FrontendStatusType::SPECTRAL: {
324                 status.inversion(FrontendDvbcSpectralInversion::NORMAL);
325                 break;
326             }
327             case FrontendStatusType::LNB_VOLTAGE: {
328                 status.lnbVoltage(LnbVoltage::VOLTAGE_5V);
329                 break;
330             }
331             case FrontendStatusType::PLP_ID: {
332                 status.plpId(101);  // type uint8_t
333                 break;
334             }
335             case FrontendStatusType::EWBS: {
336                 status.isEWBS(false);
337                 break;
338             }
339             case FrontendStatusType::AGC: {
340                 status.agc(7);
341                 break;
342             }
343             case FrontendStatusType::LNA: {
344                 status.isLnaOn(false);
345                 break;
346             }
347             case FrontendStatusType::LAYER_ERROR: {
348                 vector<bool> v = {false, true, true};
349                 status.isLayerError(v);
350                 break;
351             }
352             case FrontendStatusType::MER: {
353                 status.mer(8);
354                 break;
355             }
356             case FrontendStatusType::FREQ_OFFSET: {
357                 status.freqOffset(9);
358                 break;
359             }
360             case FrontendStatusType::HIERARCHY: {
361                 status.hierarchy(FrontendDvbtHierarchy::HIERARCHY_1_NATIVE);
362                 break;
363             }
364             case FrontendStatusType::RF_LOCK: {
365                 status.isRfLocked(false);
366                 break;
367             }
368             case FrontendStatusType::ATSC3_PLP_INFO: {
369                 vector<FrontendStatusAtsc3PlpInfo> v;
370                 FrontendStatusAtsc3PlpInfo info1{
371                         .plpId = 3,
372                         .isLocked = false,
373                         .uec = 313,
374                 };
375                 FrontendStatusAtsc3PlpInfo info2{
376                         .plpId = 5,
377                         .isLocked = true,
378                         .uec = 515,
379                 };
380                 v.push_back(info1);
381                 v.push_back(info2);
382                 status.plpInfo(v);
383                 break;
384             }
385             default: {
386                 continue;
387             }
388         }
389         statuses.push_back(status);
390     }
391     _hidl_cb(Result::SUCCESS, statuses);
392 
393     return Void();
394 }
395 
getStatusExt1_1(const hidl_vec<V1_1::FrontendStatusTypeExt1_1> & statusTypes,V1_1::IFrontend::getStatusExt1_1_cb _hidl_cb)396 Return<void> Frontend::getStatusExt1_1(const hidl_vec<V1_1::FrontendStatusTypeExt1_1>& statusTypes,
397                                        V1_1::IFrontend::getStatusExt1_1_cb _hidl_cb) {
398     ALOGV("%s", __FUNCTION__);
399 
400     vector<V1_1::FrontendStatusExt1_1> statuses;
401     for (int i = 0; i < statusTypes.size(); i++) {
402         V1_1::FrontendStatusTypeExt1_1 type = statusTypes[i];
403         V1_1::FrontendStatusExt1_1 status;
404 
405         switch (type) {
406             case V1_1::FrontendStatusTypeExt1_1::MODULATIONS: {
407                 vector<V1_1::FrontendModulation> modulations;
408                 V1_1::FrontendModulation modulation;
409                 switch ((int)mType) {
410                     case (int)FrontendType::ISDBS: {
411                         modulation.isdbs(FrontendIsdbsModulation::MOD_BPSK);  // value = 1 << 1
412                         modulations.push_back(modulation);
413                         status.modulations(modulations);
414                         break;
415                     }
416                     case (int)FrontendType::DVBC: {
417                         modulation.dvbc(FrontendDvbcModulation::MOD_16QAM);  // value = 1 << 1
418                         modulations.push_back(modulation);
419                         status.modulations(modulations);
420                         break;
421                     }
422                     case (int)FrontendType::DVBS: {
423                         modulation.dvbs(FrontendDvbsModulation::MOD_QPSK);  // value = 1 << 1
424                         modulations.push_back(modulation);
425                         status.modulations(modulations);
426                         break;
427                     }
428                     case (int)FrontendType::DVBT: {
429                         // value = 1 << 16
430                         modulation.dvbt(V1_1::FrontendDvbtConstellation::CONSTELLATION_16QAM_R);
431                         modulations.push_back(modulation);
432                         status.modulations(modulations);
433                         break;
434                     }
435                     case (int)FrontendType::ISDBS3: {
436                         modulation.isdbs3(FrontendIsdbs3Modulation::MOD_BPSK);  //  value = 1 << 1
437                         modulations.push_back(modulation);
438                         status.modulations(modulations);
439                         break;
440                     }
441                     case (int)FrontendType::ISDBT: {
442                         modulation.isdbt(FrontendIsdbtModulation::MOD_DQPSK);  // value = 1 << 1
443                         modulations.push_back(modulation);
444                         status.modulations(modulations);
445                         break;
446                     }
447                     case (int)FrontendType::ATSC: {
448                         modulation.atsc(FrontendAtscModulation::MOD_8VSB);  // value = 1 << 2
449                         modulations.push_back(modulation);
450                         status.modulations(modulations);
451                         break;
452                     }
453                     case (int)FrontendType::ATSC3: {
454                         modulation.atsc3(FrontendAtsc3Modulation::MOD_QPSK);  // value = 1 << 1
455                         modulations.push_back(modulation);
456                         status.modulations(modulations);
457                         break;
458                     }
459                     case (int)V1_1::FrontendType::DTMB: {
460                         // value = 1 << 1
461                         modulation.dtmb(V1_1::FrontendDtmbModulation::CONSTELLATION_4QAM);
462                         modulations.push_back(modulation);
463                         status.modulations(modulations);
464                         break;
465                     }
466                     default:
467                         break;
468                 }
469                 break;
470             }
471             case V1_1::FrontendStatusTypeExt1_1::BERS: {
472                 vector<uint32_t> bers = {1};
473                 status.bers(bers);
474                 break;
475             }
476             case V1_1::FrontendStatusTypeExt1_1::CODERATES: {
477                 // value = 1 << 39
478                 vector<V1_1::FrontendInnerFec> codeRates = {V1_1::FrontendInnerFec::FEC_6_15};
479                 status.codeRates(codeRates);
480                 break;
481             }
482             case V1_1::FrontendStatusTypeExt1_1::BANDWIDTH: {
483                 V1_1::FrontendBandwidth bandwidth;
484                 switch ((int)mType) {
485                     case (int)FrontendType::DVBC: {
486                         // value = 1 << 1
487                         bandwidth.dvbc(V1_1::FrontendDvbcBandwidth::BANDWIDTH_6MHZ);
488                         status.bandwidth(bandwidth);
489                         break;
490                     }
491                     case (int)FrontendType::DVBT: {
492                         // value = 1 << 1
493                         bandwidth.dvbt(FrontendDvbtBandwidth::BANDWIDTH_8MHZ);
494                         status.bandwidth(bandwidth);
495                         break;
496                     }
497                     case (int)FrontendType::ISDBT: {
498                         bandwidth.isdbt(FrontendIsdbtBandwidth::BANDWIDTH_8MHZ);  // value = 1 << 1
499                         status.bandwidth(bandwidth);
500                         break;
501                     }
502                     case (int)FrontendType::ATSC3: {
503                         bandwidth.atsc3(FrontendAtsc3Bandwidth::BANDWIDTH_6MHZ);  // value = 1 << 1
504                         status.bandwidth(bandwidth);
505                         break;
506                     }
507                     case (int)V1_1::FrontendType::DTMB: {
508                         // value = 1 << 1
509                         bandwidth.dtmb(V1_1::FrontendDtmbBandwidth::BANDWIDTH_8MHZ);
510                         status.bandwidth(bandwidth);
511                         break;
512                     }
513                     default:
514                         break;
515                 }
516                 break;
517             }
518             case V1_1::FrontendStatusTypeExt1_1::GUARD_INTERVAL: {
519                 V1_1::FrontendGuardInterval interval;
520                 switch ((int)mType) {
521                     case (int)FrontendType::DVBT: {
522                         interval.dvbt(FrontendDvbtGuardInterval::INTERVAL_1_32);  // value = 1 << 1
523                         status.interval(interval);
524                         break;
525                     }
526                     case (int)FrontendType::ISDBT: {
527                         interval.isdbt(FrontendDvbtGuardInterval::INTERVAL_1_32);  // value = 1 << 1
528                         status.interval(interval);
529                         break;
530                     }
531                     case (int)V1_1::FrontendType::DTMB: {
532                         // value = 1 << 1
533                         interval.dtmb(V1_1::FrontendDtmbGuardInterval::PN_420_VARIOUS);
534                         status.interval(interval);
535                         break;
536                     }
537                     default:
538                         break;
539                 }
540                 break;
541             }
542             case V1_1::FrontendStatusTypeExt1_1::TRANSMISSION_MODE: {
543                 V1_1::FrontendTransmissionMode transMode;
544                 switch ((int)mType) {
545                     case (int)FrontendType::DVBT: {
546                         // value = 1 << 8
547                         transMode.dvbt(V1_1::FrontendDvbtTransmissionMode::MODE_16K_E);
548                         status.transmissionMode(transMode);
549                         break;
550                     }
551                     case (int)FrontendType::ISDBT: {
552                         transMode.isdbt(FrontendIsdbtMode::MODE_1);  // value = 1 << 1
553                         status.transmissionMode(transMode);
554                         break;
555                     }
556                     case (int)V1_1::FrontendType::DTMB: {
557                         transMode.dtmb(V1_1::FrontendDtmbTransmissionMode::C1);  // value = 1 << 1
558                         status.transmissionMode(transMode);
559                         break;
560                     }
561                     default:
562                         break;
563                 }
564                 break;
565             }
566             case V1_1::FrontendStatusTypeExt1_1::UEC: {
567                 status.uec(4);
568                 break;
569             }
570             case V1_1::FrontendStatusTypeExt1_1::T2_SYSTEM_ID: {
571                 status.systemId(5);
572                 break;
573             }
574             case V1_1::FrontendStatusTypeExt1_1::INTERLEAVINGS: {
575                 V1_1::FrontendInterleaveMode interleave;
576                 switch ((int)mType) {
577                     case (int)FrontendType::DVBC: {
578                         // value = 1 << 1
579                         interleave.dvbc(
580                                 V1_1::FrontendCableTimeInterleaveMode::INTERLEAVING_128_1_0);
581                         vector<V1_1::FrontendInterleaveMode> interleaving = {interleave};
582                         status.interleaving(interleaving);
583                         break;
584                     }
585                     case (int)FrontendType::ATSC3: {
586                         // value = 1 << 1
587                         interleave.atsc3(FrontendAtsc3TimeInterleaveMode::CTI);
588                         vector<V1_1::FrontendInterleaveMode> interleaving = {interleave};
589                         status.interleaving(interleaving);
590                         break;
591                     }
592                     case (int)V1_1::FrontendType::DTMB: {
593                         // value = 1 << 1
594                         interleave.dtmb(V1_1::FrontendDtmbTimeInterleaveMode::TIMER_INT_240);
595                         vector<V1_1::FrontendInterleaveMode> interleaving = {interleave};
596                         status.interleaving(interleaving);
597                         break;
598                     }
599                     default:
600                         break;
601                 }
602                 break;
603             }
604             case V1_1::FrontendStatusTypeExt1_1::ISDBT_SEGMENTS: {
605                 vector<uint8_t> segments = {2, 3};
606                 status.isdbtSegment(segments);
607                 break;
608             }
609             case V1_1::FrontendStatusTypeExt1_1::TS_DATA_RATES: {
610                 vector<uint32_t> dataRates = {4, 5};
611                 status.tsDataRate(dataRates);
612                 break;
613             }
614             case V1_1::FrontendStatusTypeExt1_1::ROLL_OFF: {
615                 V1_1::FrontendRollOff rollOff;
616                 switch (mType) {
617                     case FrontendType::DVBS: {
618                         // value = 1
619                         rollOff.dvbs(FrontendDvbsRolloff::ROLLOFF_0_35);
620                         status.rollOff(rollOff);
621                         break;
622                     }
623                     case FrontendType::ISDBS: {
624                         // value = 1
625                         rollOff.isdbs(FrontendIsdbsRolloff::ROLLOFF_0_35);
626                         status.rollOff(rollOff);
627                         break;
628                     }
629                     case FrontendType::ISDBS3: {
630                         // value = 1
631                         rollOff.isdbs3(FrontendIsdbs3Rolloff::ROLLOFF_0_03);
632                         status.rollOff(rollOff);
633                         break;
634                     }
635                     default:
636                         break;
637                 }
638                 break;
639             }
640             case V1_1::FrontendStatusTypeExt1_1::IS_MISO: {
641                 status.isMiso(true);
642                 break;
643             }
644             case V1_1::FrontendStatusTypeExt1_1::IS_LINEAR: {
645                 status.isLinear(true);
646                 break;
647             }
648             case V1_1::FrontendStatusTypeExt1_1::IS_SHORT_FRAMES: {
649                 status.isShortFrames(true);
650                 break;
651             }
652             default: {
653                 continue;
654             }
655         }
656         statuses.push_back(status);
657     }
658     _hidl_cb(Result::SUCCESS, statuses);
659 
660     return Void();
661 }
662 
setLna(bool)663 Return<Result> Frontend::setLna(bool /* bEnable */) {
664     ALOGV("%s", __FUNCTION__);
665 
666     return Result::SUCCESS;
667 }
668 
setLnb(uint32_t)669 Return<Result> Frontend::setLnb(uint32_t /* lnb */) {
670     ALOGV("%s", __FUNCTION__);
671     if (!supportsSatellite()) {
672         return Result::INVALID_STATE;
673     }
674     return Result::SUCCESS;
675 }
676 
linkCiCam(uint32_t ciCamId,linkCiCam_cb _hidl_cb)677 Return<void> Frontend::linkCiCam(uint32_t ciCamId, linkCiCam_cb _hidl_cb) {
678     ALOGV("%s", __FUNCTION__);
679 
680     mCiCamId = ciCamId;
681     _hidl_cb(Result::SUCCESS, 0 /*ltsId*/);
682 
683     return Void();
684 }
685 
unlinkCiCam(uint32_t)686 Return<Result> Frontend::unlinkCiCam(uint32_t /*ciCamId*/) {
687     ALOGV("%s", __FUNCTION__);
688 
689     mCiCamId = -1;
690 
691     return Result::SUCCESS;
692 }
693 
getFrontendType()694 FrontendType Frontend::getFrontendType() {
695     return mType;
696 }
697 
getFrontendId()698 FrontendId Frontend::getFrontendId() {
699     return mId;
700 }
701 
supportsSatellite()702 bool Frontend::supportsSatellite() {
703     return mType == FrontendType::DVBS || mType == FrontendType::ISDBS ||
704            mType == FrontendType::ISDBS3;
705 }
706 
isLocked()707 bool Frontend::isLocked() {
708     return mIsLocked;
709 }
710 }  // namespace implementation
711 }  // namespace V1_0
712 }  // namespace tuner
713 }  // namespace tv
714 }  // namespace hardware
715 }  // namespace android
716