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