1 /*
2  * Copyright 2021 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_NDEBUG 0
18 #define LOG_TAG "android.hardware.tv.tuner-service.example-Frontend"
19 
20 #include <aidl/android/hardware/tv/tuner/Result.h>
21 #include <utils/Log.h>
22 
23 #include "Frontend.h"
24 
25 namespace aidl {
26 namespace android {
27 namespace hardware {
28 namespace tv {
29 namespace tuner {
30 
Frontend(FrontendType type,int32_t id)31 Frontend::Frontend(FrontendType type, int32_t id) {
32     mType = type;
33     mId = id;
34     mTuner = nullptr;
35     // Init callback to nullptr
36     mCallback = nullptr;
37     mIptvPluginInterface = nullptr;
38     mIptvPluginStreamer = nullptr;
39 
40     switch (mType) {
41         case FrontendType::ISDBS: {
42             mFrontendCaps.set<FrontendCapabilities::Tag::isdbsCaps>(FrontendIsdbsCapabilities());
43             mFrontendStatusCaps = {
44                     FrontendStatusType::DEMOD_LOCK,
45                     FrontendStatusType::SNR,
46                     FrontendStatusType::FEC,
47                     FrontendStatusType::MODULATION,
48                     FrontendStatusType::MODULATIONS,
49                     FrontendStatusType::ROLL_OFF,
50                     FrontendStatusType::STREAM_ID_LIST,
51             };
52             break;
53         }
54         case FrontendType::ATSC3: {
55             mFrontendCaps.set<FrontendCapabilities::Tag::atsc3Caps>(FrontendAtsc3Capabilities());
56             mFrontendStatusCaps = {
57                     FrontendStatusType::BER,
58                     FrontendStatusType::PER,
59                     FrontendStatusType::ATSC3_PLP_INFO,
60                     FrontendStatusType::MODULATIONS,
61                     FrontendStatusType::BERS,
62                     FrontendStatusType::INTERLEAVINGS,
63                     FrontendStatusType::BANDWIDTH,
64                     FrontendStatusType::ATSC3_ALL_PLP_INFO,
65             };
66             break;
67         }
68         case FrontendType::DVBC: {
69             mFrontendCaps.set<FrontendCapabilities::Tag::dvbcCaps>(FrontendDvbcCapabilities());
70             mFrontendStatusCaps = {
71                     FrontendStatusType::PRE_BER,       FrontendStatusType::SIGNAL_QUALITY,
72                     FrontendStatusType::MODULATION,    FrontendStatusType::SPECTRAL,
73                     FrontendStatusType::MODULATIONS,   FrontendStatusType::CODERATES,
74                     FrontendStatusType::INTERLEAVINGS, FrontendStatusType::BANDWIDTH,
75             };
76             break;
77         }
78         case FrontendType::DVBS: {
79             mFrontendCaps.set<FrontendCapabilities::Tag::dvbsCaps>(FrontendDvbsCapabilities());
80             mFrontendStatusCaps = {
81                     FrontendStatusType::SIGNAL_STRENGTH, FrontendStatusType::SYMBOL_RATE,
82                     FrontendStatusType::MODULATION,      FrontendStatusType::MODULATIONS,
83                     FrontendStatusType::ROLL_OFF,        FrontendStatusType::IS_MISO,
84             };
85             break;
86         }
87         case FrontendType::DVBT: {
88             mFrontendCaps.set<FrontendCapabilities::Tag::dvbtCaps>(FrontendDvbtCapabilities());
89             mFrontendStatusCaps = {
90                     FrontendStatusType::EWBS,
91                     FrontendStatusType::PLP_ID,
92                     FrontendStatusType::HIERARCHY,
93                     FrontendStatusType::MODULATIONS,
94                     FrontendStatusType::BANDWIDTH,
95                     FrontendStatusType::GUARD_INTERVAL,
96                     FrontendStatusType::TRANSMISSION_MODE,
97                     FrontendStatusType::T2_SYSTEM_ID,
98                     FrontendStatusType::DVBT_CELL_IDS,
99             };
100             break;
101         }
102         case FrontendType::ISDBT: {
103             FrontendIsdbtCapabilities isdbtCaps{
104                     .modeCap = (int)FrontendIsdbtMode::MODE_1 | (int)FrontendIsdbtMode::MODE_2,
105                     .bandwidthCap = (int)FrontendIsdbtBandwidth::BANDWIDTH_6MHZ,
106                     .modulationCap = (int)FrontendIsdbtModulation::MOD_16QAM,
107                     .coderateCap = (int)FrontendIsdbtCoderate::CODERATE_4_5 |
108                                    (int)FrontendIsdbtCoderate::CODERATE_6_7,
109                     .guardIntervalCap = (int)FrontendIsdbtGuardInterval::INTERVAL_1_128,
110                     .timeInterleaveCap = (int)FrontendIsdbtTimeInterleaveMode::AUTO |
111                                          (int)FrontendIsdbtTimeInterleaveMode::INTERLEAVE_1_0,
112                     .isSegmentAuto = true,
113                     .isFullSegment = true,
114             };
115             mFrontendCaps.set<FrontendCapabilities::Tag::isdbtCaps>(isdbtCaps);
116             mFrontendStatusCaps = {
117                     FrontendStatusType::AGC,
118                     FrontendStatusType::LNA,
119                     FrontendStatusType::MODULATION,
120                     FrontendStatusType::MODULATIONS,
121                     FrontendStatusType::BANDWIDTH,
122                     FrontendStatusType::GUARD_INTERVAL,
123                     FrontendStatusType::TRANSMISSION_MODE,
124                     FrontendStatusType::ISDBT_SEGMENTS,
125                     FrontendStatusType::ISDBT_MODE,
126                     FrontendStatusType::ISDBT_PARTIAL_RECEPTION_FLAG,
127                     FrontendStatusType::INTERLEAVINGS,
128             };
129             break;
130         }
131         case FrontendType::ANALOG: {
132             mFrontendCaps.set<FrontendCapabilities::Tag::analogCaps>(FrontendAnalogCapabilities());
133             mFrontendStatusCaps = {
134                     FrontendStatusType::LAYER_ERROR,
135                     FrontendStatusType::MER,
136                     FrontendStatusType::UEC,
137                     FrontendStatusType::TS_DATA_RATES,
138             };
139             break;
140         }
141         case FrontendType::ATSC: {
142             mFrontendCaps.set<FrontendCapabilities::Tag::atscCaps>(FrontendAtscCapabilities());
143             mFrontendStatusCaps = {
144                     FrontendStatusType::FREQ_OFFSET,
145                     FrontendStatusType::RF_LOCK,
146                     FrontendStatusType::MODULATIONS,
147                     FrontendStatusType::IS_LINEAR,
148             };
149             break;
150         }
151         case FrontendType::ISDBS3: {
152             mFrontendCaps.set<FrontendCapabilities::Tag::isdbs3Caps>(FrontendIsdbs3Capabilities());
153             mFrontendStatusCaps = {
154                     FrontendStatusType::DEMOD_LOCK,      FrontendStatusType::MODULATION,
155                     FrontendStatusType::MODULATIONS,     FrontendStatusType::ROLL_OFF,
156                     FrontendStatusType::IS_SHORT_FRAMES, FrontendStatusType::STREAM_ID_LIST,
157             };
158             break;
159         }
160         case FrontendType::DTMB: {
161             mFrontendCaps.set<FrontendCapabilities::Tag::dtmbCaps>(FrontendDtmbCapabilities());
162             mFrontendStatusCaps = {
163                     FrontendStatusType::MODULATIONS,       FrontendStatusType::INTERLEAVINGS,
164                     FrontendStatusType::BANDWIDTH,         FrontendStatusType::GUARD_INTERVAL,
165                     FrontendStatusType::TRANSMISSION_MODE,
166             };
167             break;
168         }
169         case FrontendType::IPTV: {
170             mFrontendCaps.set<FrontendCapabilities::Tag::iptvCaps>(FrontendIptvCapabilities());
171             mFrontendStatusCaps = {
172                     FrontendStatusType::IPTV_CONTENT_URL,
173                     FrontendStatusType::IPTV_PACKETS_LOST,
174                     FrontendStatusType::IPTV_PACKETS_RECEIVED,
175                     FrontendStatusType::IPTV_AVERAGE_JITTER_MS,
176                     FrontendStatusType::IPTV_WORST_JITTER_MS,
177             };
178             break;
179         }
180         default: {
181             break;
182         }
183     }
184 }
185 
~Frontend()186 Frontend::~Frontend() {
187     ALOGV("%s", __FUNCTION__);
188     mCallback = nullptr;
189     mIsLocked = false;
190     mTuner = nullptr;
191     if (mTuneByteBuffer != nullptr) {
192         free(mTuneByteBuffer);
193     }
194 }
195 
close()196 ::ndk::ScopedAStatus Frontend::close() {
197     ALOGV("%s", __FUNCTION__);
198     // Reset callback
199     mCallback = nullptr;
200     mIsLocked = false;
201     if (mTuner != nullptr) {
202         mTuner->removeFrontend(mId);
203     }
204     mTuner = nullptr;
205 
206     return ::ndk::ScopedAStatus::ok();
207 }
208 
setCallback(const std::shared_ptr<IFrontendCallback> & in_callback)209 ::ndk::ScopedAStatus Frontend::setCallback(const std::shared_ptr<IFrontendCallback>& in_callback) {
210     ALOGV("%s", __FUNCTION__);
211     if (in_callback == nullptr) {
212         ALOGW("[   WARN   ] Set Frontend callback with nullptr");
213         return ::ndk::ScopedAStatus::fromServiceSpecificError(
214                 static_cast<int32_t>(Result::INVALID_ARGUMENT));
215     }
216 
217     mCallback = in_callback;
218     return ::ndk::ScopedAStatus::ok();
219 }
220 
createIptvPluginInterface()221 dtv_plugin* Frontend::createIptvPluginInterface() {
222     const char* path = "/vendor/lib/iptv_udp_plugin.so";
223     DtvPlugin* plugin = new DtvPlugin(path);
224     bool plugin_loaded = plugin->load();
225     if (!plugin_loaded) {
226         ALOGE("Failed to load plugin");
227         return nullptr;
228     }
229     return plugin->interface();
230 }
231 
createIptvPluginStreamer(dtv_plugin * interface,const char * transport_desc)232 dtv_streamer* Frontend::createIptvPluginStreamer(dtv_plugin* interface,
233                                                  const char* transport_desc) {
234     dtv_streamer* streamer = interface->create_streamer();
235     int open_fd = interface->open_stream(streamer, transport_desc);
236     if (open_fd < 0) {
237         return nullptr;
238     }
239     ALOGI("[   INFO   ] open_stream successful, open_fd=%d", open_fd);
240     return streamer;
241 }
242 
readTuneByte(void * buf)243 void Frontend::readTuneByte(void* buf) {
244     ssize_t bytes_read = mIptvPluginInterface->read_stream(mIptvPluginStreamer, buf,
245                                                            TUNE_BUFFER_SIZE, TUNE_BUFFER_TIMEOUT);
246     if (bytes_read <= 0) {
247         ALOGI("[   ERROR   ] Tune byte couldn't be read.");
248         return;
249     }
250     mCallback->onEvent(FrontendEventType::LOCKED);
251     mIsLocked = true;
252     mTuneByteBuffer = buf;
253 }
254 
tune(const FrontendSettings & in_settings)255 ::ndk::ScopedAStatus Frontend::tune(const FrontendSettings& in_settings) {
256     if (mCallback == nullptr) {
257         ALOGW("[   WARN   ] Frontend callback is not set for tuning");
258         return ::ndk::ScopedAStatus::fromServiceSpecificError(
259                 static_cast<int32_t>(Result::INVALID_STATE));
260     }
261 
262     if (mType != FrontendType::IPTV) {
263         mTuner->frontendStartTune(mId);
264         mCallback->onEvent(FrontendEventType::LOCKED);
265         mIsLocked = true;
266     } else {
267         // This is a reference implementation for IPTV. It uses an additional socket buffer.
268         // Vendors can use hardware memory directly to make the implementation more performant.
269         ALOGI("[   INFO   ] Frontend type is set to IPTV, tag = %d id=%d", in_settings.getTag(),
270               mId);
271 
272         mIptvPluginInterface = createIptvPluginInterface();
273         if (mIptvPluginInterface == nullptr) {
274             ALOGE("[   INFO   ] Failed to load plugin.");
275             return ::ndk::ScopedAStatus::fromServiceSpecificError(
276                     static_cast<int32_t>(Result::INVALID_ARGUMENT));
277         }
278 
279         // validate content_url format
280         std::string content_url = in_settings.get<FrontendSettings::Tag::iptv>()->contentUrl;
281         mIptvTransportDescription = "{ \"uri\": \"" + content_url + "\"}";
282         ALOGI("[   INFO   ] transport_desc: %s", mIptvTransportDescription.c_str());
283         bool is_transport_desc_valid =
284                 mIptvPluginInterface->validate(mIptvTransportDescription.c_str());
285         if (!is_transport_desc_valid) {  // not of format protocol://ip:port
286             ALOGE("[   INFO   ] transport_desc is not valid");
287             return ::ndk::ScopedAStatus::fromServiceSpecificError(
288                     static_cast<int32_t>(Result::INVALID_ARGUMENT));
289         }
290 
291         // create a streamer and open it for reading data
292         mIptvPluginStreamer =
293                 createIptvPluginStreamer(mIptvPluginInterface, mIptvTransportDescription.c_str());
294 
295         void* buf = malloc(sizeof(char) * TUNE_BUFFER_SIZE);
296         if (buf == nullptr) {
297             ALOGE("Failed to allocate 1 byte buffer for tuning.");
298             return ::ndk::ScopedAStatus::fromServiceSpecificError(
299                     static_cast<int32_t>(Result::INVALID_STATE));
300         }
301         mIptvFrontendTuneThread = std::thread(&Frontend::readTuneByte, this, buf);
302         if (mIptvFrontendTuneThread.joinable()) {
303             mIptvFrontendTuneThread.join();
304         }
305     }
306 
307     return ::ndk::ScopedAStatus::ok();
308 }
309 
stopTune()310 ::ndk::ScopedAStatus Frontend::stopTune() {
311     ALOGV("%s", __FUNCTION__);
312 
313     mTuner->frontendStopTune(mId);
314     mIsLocked = false;
315 
316     return ::ndk::ScopedAStatus::ok();
317 }
318 
scan(const FrontendSettings & in_settings,FrontendScanType in_type)319 ::ndk::ScopedAStatus Frontend::scan(const FrontendSettings& in_settings, FrontendScanType in_type) {
320     ALOGV("%s", __FUNCTION__);
321 
322     // If it's in middle of scanning, stop it first.
323     if (mScanThread.joinable()) {
324         mScanThread.join();
325     }
326 
327     mFrontendSettings = in_settings;
328     mFrontendScanType = in_type;
329     mScanThread = std::thread(&Frontend::scanThreadLoop, this);
330 
331     return ::ndk::ScopedAStatus::ok();
332 }
333 
setTunerService(std::shared_ptr<Tuner> tuner)334 void Frontend::setTunerService(std::shared_ptr<Tuner> tuner) {
335     mTuner = tuner;
336 }
337 
scanThreadLoop()338 void Frontend::scanThreadLoop() {
339     if (mIsLocked) {
340         FrontendScanMessage msg;
341         msg.set<FrontendScanMessage::Tag::isEnd>(true);
342         mCallback->onScanMessage(FrontendScanMessageType::END, msg);
343         return;
344     }
345 
346     int64_t frequency = 0;
347     switch (mFrontendSettings.getTag()) {
348         case FrontendSettings::Tag::analog:
349             frequency = mFrontendSettings.get<FrontendSettings::Tag::analog>().frequency;
350             break;
351         case FrontendSettings::Tag::atsc:
352             frequency = mFrontendSettings.get<FrontendSettings::Tag::atsc>().frequency;
353             break;
354         case FrontendSettings::Tag::atsc3:
355             frequency = mFrontendSettings.get<FrontendSettings::Tag::atsc3>().frequency;
356             break;
357         case FrontendSettings::Tag::dvbs:
358             frequency = mFrontendSettings.get<FrontendSettings::Tag::dvbs>().frequency;
359             break;
360         case FrontendSettings::Tag::dvbc:
361             frequency = mFrontendSettings.get<FrontendSettings::Tag::dvbc>().frequency;
362             break;
363         case FrontendSettings::Tag::dvbt:
364             frequency = mFrontendSettings.get<FrontendSettings::Tag::dvbt>().frequency;
365             break;
366         case FrontendSettings::Tag::isdbs:
367             frequency = mFrontendSettings.get<FrontendSettings::Tag::isdbs>().frequency;
368             break;
369         case FrontendSettings::Tag::isdbs3:
370             frequency = mFrontendSettings.get<FrontendSettings::Tag::isdbs3>().frequency;
371             break;
372         case FrontendSettings::Tag::isdbt:
373             frequency = mFrontendSettings.get<FrontendSettings::Tag::isdbt>().frequency;
374             break;
375         default:
376             break;
377     }
378 
379     if (mFrontendScanType == FrontendScanType::SCAN_BLIND) {
380         frequency += 100 * 1000;
381     }
382 
383     {
384         FrontendScanMessage msg;
385         vector<int64_t> frequencies = {frequency};
386         msg.set<FrontendScanMessage::Tag::frequencies>(frequencies);
387         mCallback->onScanMessage(FrontendScanMessageType::FREQUENCY, msg);
388     }
389 
390     {
391         FrontendScanMessage msg;
392         msg.set<FrontendScanMessage::Tag::progressPercent>(20);
393         mCallback->onScanMessage(FrontendScanMessageType::PROGRESS_PERCENT, msg);
394     }
395 
396     {
397         FrontendScanMessage msg;
398         vector<int32_t> symbolRates = {30};
399         msg.set<FrontendScanMessage::Tag::symbolRates>(symbolRates);
400         mCallback->onScanMessage(FrontendScanMessageType::SYMBOL_RATE, msg);
401     }
402 
403     if (mType == FrontendType::DVBT) {
404         FrontendScanMessage msg;
405         msg.set<FrontendScanMessage::Tag::hierarchy>(FrontendDvbtHierarchy::HIERARCHY_NON_NATIVE);
406         mCallback->onScanMessage(FrontendScanMessageType::HIERARCHY, msg);
407     }
408 
409     if (mType == FrontendType::ANALOG) {
410         FrontendScanMessage msg;
411         msg.set<FrontendScanMessage::Tag::analogType>(FrontendAnalogType::PAL);
412         mCallback->onScanMessage(FrontendScanMessageType::ANALOG_TYPE, msg);
413     }
414 
415     {
416         FrontendScanMessage msg;
417         vector<int32_t> plpIds = {2};
418         msg.set<FrontendScanMessage::Tag::plpIds>(plpIds);
419         mCallback->onScanMessage(FrontendScanMessageType::PLP_IDS, msg);
420     }
421 
422     {
423         FrontendScanMessage msg;
424         vector<int32_t> groupIds = {3};
425         msg.set<FrontendScanMessage::Tag::groupIds>(groupIds);
426         mCallback->onScanMessage(FrontendScanMessageType::GROUP_IDS, msg);
427     }
428 
429     {
430         FrontendScanMessage msg;
431         vector<int32_t> inputStreamIds = {1};
432         msg.set<FrontendScanMessage::Tag::inputStreamIds>(inputStreamIds);
433         mCallback->onScanMessage(FrontendScanMessageType::INPUT_STREAM_IDS, msg);
434     }
435 
436     switch (mType) {
437         case FrontendType::DVBT: {
438             FrontendScanMessage msg;
439             FrontendScanMessageStandard std;
440             std.set<FrontendScanMessageStandard::Tag::tStd>(FrontendDvbtStandard::AUTO);
441             msg.set<FrontendScanMessage::Tag::std>(std);
442             mCallback->onScanMessage(FrontendScanMessageType::STANDARD, msg);
443             break;
444         }
445         case FrontendType::DVBS: {
446             FrontendScanMessage msg;
447             FrontendScanMessageStandard std;
448             std.set<FrontendScanMessageStandard::Tag::sStd>(FrontendDvbsStandard::AUTO);
449             msg.set<FrontendScanMessage::Tag::std>(std);
450             mCallback->onScanMessage(FrontendScanMessageType::STANDARD, msg);
451             break;
452         }
453         case FrontendType::ANALOG: {
454             FrontendScanMessage msg;
455             FrontendScanMessageStandard std;
456             std.set<FrontendScanMessageStandard::Tag::sifStd>(FrontendAnalogSifStandard::AUTO);
457             msg.set<FrontendScanMessage::Tag::std>(std);
458             mCallback->onScanMessage(FrontendScanMessageType::STANDARD, msg);
459             break;
460         }
461         default:
462             break;
463     }
464 
465     {
466         FrontendScanMessage msg;
467         FrontendScanAtsc3PlpInfo info;
468         info.plpId = 1;
469         info.bLlsFlag = false;
470         vector<FrontendScanAtsc3PlpInfo> atsc3PlpInfos = {info};
471         msg.set<FrontendScanMessage::Tag::atsc3PlpInfos>(atsc3PlpInfos);
472         mCallback->onScanMessage(FrontendScanMessageType::ATSC3_PLP_INFO, msg);
473     }
474 
475     {
476         FrontendScanMessage msg;
477         FrontendModulation modulation;
478         modulation.set<FrontendModulation::Tag::dvbc>(FrontendDvbcModulation::MOD_16QAM);
479         msg.set<FrontendScanMessage::Tag::modulation>(modulation);
480         mCallback->onScanMessage(FrontendScanMessageType::MODULATION, msg);
481     }
482 
483     {
484         FrontendScanMessage msg;
485         msg.set<FrontendScanMessage::Tag::isHighPriority>(true);
486         mCallback->onScanMessage(FrontendScanMessageType::HIGH_PRIORITY, msg);
487     }
488 
489     if (mType == FrontendType::DVBT) {
490         FrontendScanMessage msg;
491         vector<int32_t> dvbtCellIds = {0, 1};
492         msg.set<FrontendScanMessage::Tag::dvbtCellIds>(dvbtCellIds);
493         mCallback->onScanMessage(FrontendScanMessageType::DVBT_CELL_IDS, msg);
494     }
495 
496     {
497         FrontendScanMessage msg;
498         msg.set<FrontendScanMessage::Tag::isLocked>(false);
499         mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
500         mIsLocked = false;
501     }
502 
503     {
504         FrontendScanMessage msg;
505         msg.set<FrontendScanMessage::Tag::isLocked>(true);
506         mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
507         mIsLocked = true;
508     }
509 }
510 
stopScan()511 ::ndk::ScopedAStatus Frontend::stopScan() {
512     ALOGV("%s", __FUNCTION__);
513 
514     if (mScanThread.joinable()) {
515         mScanThread.join();
516     }
517 
518     mIsLocked = false;
519     return ::ndk::ScopedAStatus::ok();
520 }
521 
getStatus(const std::vector<FrontendStatusType> & in_statusTypes,std::vector<FrontendStatus> * _aidl_return)522 ::ndk::ScopedAStatus Frontend::getStatus(const std::vector<FrontendStatusType>& in_statusTypes,
523                                          std::vector<FrontendStatus>* _aidl_return) {
524     ALOGV("%s", __FUNCTION__);
525 
526     for (int i = 0; i < in_statusTypes.size(); i++) {
527         FrontendStatusType type = in_statusTypes[i];
528         FrontendStatus status;
529         // assign randomly selected values for testing.
530         switch (type) {
531             case FrontendStatusType::DEMOD_LOCK: {
532                 status.set<FrontendStatus::isDemodLocked>(true);
533                 break;
534             }
535             case FrontendStatusType::SNR: {
536                 status.set<FrontendStatus::snr>(221);
537                 break;
538             }
539             case FrontendStatusType::BER: {
540                 status.set<FrontendStatus::ber>(1);
541                 break;
542             }
543             case FrontendStatusType::PER: {
544                 status.set<FrontendStatus::per>(2);
545                 break;
546             }
547             case FrontendStatusType::PRE_BER: {
548                 status.set<FrontendStatus::preBer>(3);
549                 break;
550             }
551             case FrontendStatusType::SIGNAL_QUALITY: {
552                 status.set<FrontendStatus::signalQuality>(4);
553                 break;
554             }
555             case FrontendStatusType::SIGNAL_STRENGTH: {
556                 status.set<FrontendStatus::signalStrength>(5);
557                 break;
558             }
559             case FrontendStatusType::SYMBOL_RATE: {
560                 status.set<FrontendStatus::symbolRate>(6);
561                 break;
562             }
563             case FrontendStatusType::FEC: {
564                 status.set<FrontendStatus::innerFec>(FrontendInnerFec::FEC_2_9);  // value = 1 << 7
565                 break;
566             }
567             case FrontendStatusType::MODULATION: {
568                 switch (mType) {
569                     case FrontendType::ISDBS: {
570                         FrontendModulationStatus modulationStatus;
571                         modulationStatus.set<FrontendModulationStatus::Tag::isdbs>(
572                                 FrontendIsdbsModulation::MOD_BPSK);  // value = 1 << 1
573                         status.set<FrontendStatus::modulationStatus>(modulationStatus);
574                         break;
575                     }
576                     case FrontendType::DVBC: {
577                         FrontendModulationStatus modulationStatus;
578                         modulationStatus.set<FrontendModulationStatus::Tag::dvbc>(
579                                 FrontendDvbcModulation::MOD_16QAM);  // value = 1 << 1
580                         status.set<FrontendStatus::modulationStatus>(modulationStatus);
581                         break;
582                     }
583                     case FrontendType::DVBS: {
584                         FrontendModulationStatus modulationStatus;
585                         modulationStatus.set<FrontendModulationStatus::Tag::dvbs>(
586                                 FrontendDvbsModulation::MOD_QPSK);  // value = 1 << 1
587                         status.set<FrontendStatus::modulationStatus>(modulationStatus);
588                         break;
589                     }
590                     case FrontendType::ISDBS3: {
591                         FrontendModulationStatus modulationStatus;
592                         modulationStatus.set<FrontendModulationStatus::Tag::isdbs3>(
593                                 FrontendIsdbs3Modulation::MOD_BPSK);  // value = 1 << 1
594                         status.set<FrontendStatus::modulationStatus>(modulationStatus);
595                         break;
596                     }
597                     case FrontendType::ISDBT: {
598                         FrontendModulationStatus modulationStatus;
599                         modulationStatus.set<FrontendModulationStatus::Tag::isdbt>(
600                                 FrontendIsdbtModulation::MOD_DQPSK);  // value = 1 << 1
601                         status.set<FrontendStatus::modulationStatus>(modulationStatus);
602                         break;
603                     }
604                     default:
605                         break;
606                 }
607                 break;
608             }
609             case FrontendStatusType::SPECTRAL: {
610                 status.set<FrontendStatus::inversion>(FrontendSpectralInversion::NORMAL);
611                 break;
612             }
613             case FrontendStatusType::LNB_VOLTAGE: {
614                 status.set<FrontendStatus::lnbVoltage>(LnbVoltage::VOLTAGE_5V);
615                 break;
616             }
617             case FrontendStatusType::PLP_ID: {
618                 status.set<FrontendStatus::plpId>(101);
619                 break;
620             }
621             case FrontendStatusType::EWBS: {
622                 status.set<FrontendStatus::isEWBS>(false);
623                 break;
624             }
625             case FrontendStatusType::AGC: {
626                 status.set<FrontendStatus::agc>(7);
627                 break;
628             }
629             case FrontendStatusType::LNA: {
630                 status.set<FrontendStatus::isLnaOn>(false);
631                 break;
632             }
633             case FrontendStatusType::LAYER_ERROR: {
634                 vector<bool> v = {false, true, true};
635                 status.set<FrontendStatus::isLayerError>(v);
636                 break;
637             }
638             case FrontendStatusType::MER: {
639                 status.set<FrontendStatus::mer>(8);
640                 break;
641             }
642             case FrontendStatusType::FREQ_OFFSET: {
643                 status.set<FrontendStatus::freqOffset>(9);
644                 break;
645             }
646             case FrontendStatusType::HIERARCHY: {
647                 status.set<FrontendStatus::hierarchy>(FrontendDvbtHierarchy::HIERARCHY_1_NATIVE);
648                 break;
649             }
650             case FrontendStatusType::RF_LOCK: {
651                 status.set<FrontendStatus::isRfLocked>(false);
652                 break;
653             }
654             case FrontendStatusType::ATSC3_PLP_INFO: {
655                 FrontendStatusAtsc3PlpInfo info1;
656                 info1.plpId = 3;
657                 info1.isLocked = false;
658                 info1.uec = 313;
659                 FrontendStatusAtsc3PlpInfo info2;
660                 info2.plpId = 5;
661                 info2.isLocked = true;
662                 info2.uec = 515;
663                 vector<FrontendStatusAtsc3PlpInfo> infos = {info1, info2};
664                 status.set<FrontendStatus::plpInfo>(infos);
665                 break;
666             }
667             case FrontendStatusType::MODULATIONS: {
668                 FrontendModulation modulation;
669                 vector<FrontendModulation> modulations;
670                 switch (mType) {
671                     case FrontendType::ISDBS: {
672                         modulation.set<FrontendModulation::Tag::isdbs>(
673                                 FrontendIsdbsModulation::MOD_BPSK);  // value = 1 << 1
674                         modulations.push_back(modulation);
675                         status.set<FrontendStatus::modulations>(modulations);
676                         break;
677                     }
678                     case FrontendType::DVBC: {
679                         modulation.set<FrontendModulation::Tag::dvbc>(
680                                 FrontendDvbcModulation::MOD_16QAM);  // value = 1 << 1
681                         modulations.push_back(modulation);
682                         status.set<FrontendStatus::modulations>(modulations);
683                         break;
684                     }
685                     case FrontendType::DVBS: {
686                         modulation.set<FrontendModulation::Tag::dvbs>(
687                                 FrontendDvbsModulation::MOD_QPSK);  // value = 1 << 1
688                         modulations.push_back(modulation);
689                         status.set<FrontendStatus::modulations>(modulations);
690                         break;
691                     }
692                     case FrontendType::DVBT: {
693                         modulation.set<FrontendModulation::Tag::dvbt>(
694                                 FrontendDvbtConstellation::CONSTELLATION_16QAM_R);  // value = 1 <<
695                                                                                     // 16
696                         modulations.push_back(modulation);
697                         status.set<FrontendStatus::modulations>(modulations);
698                         break;
699                     }
700                     case FrontendType::ISDBS3: {
701                         modulation.set<FrontendModulation::Tag::isdbs3>(
702                                 FrontendIsdbs3Modulation::MOD_BPSK);  //  value = 1 << 1
703                         modulations.push_back(modulation);
704                         status.set<FrontendStatus::modulations>(modulations);
705                         break;
706                     }
707                     case FrontendType::ISDBT: {
708                         modulation.set<FrontendModulation::Tag::isdbt>(
709                                 FrontendIsdbtModulation::MOD_DQPSK);  // value = 1 << 1
710                         modulations.push_back(modulation);
711                         status.set<FrontendStatus::modulations>(modulations);
712                         break;
713                     }
714                     case FrontendType::ATSC: {
715                         modulation.set<FrontendModulation::Tag::atsc>(
716                                 FrontendAtscModulation::MOD_8VSB);  // value = 1 << 2
717                         modulations.push_back(modulation);
718                         status.set<FrontendStatus::modulations>(modulations);
719                         break;
720                     }
721                     case FrontendType::ATSC3: {
722                         modulation.set<FrontendModulation::Tag::atsc3>(
723                                 FrontendAtsc3Modulation::MOD_QPSK);  // value = 1 << 1
724                         modulations.push_back(modulation);
725                         status.set<FrontendStatus::modulations>(modulations);
726                         break;
727                     }
728                     case FrontendType::DTMB: {
729                         modulation.set<FrontendModulation::Tag::dtmb>(
730                                 FrontendDtmbModulation::CONSTELLATION_4QAM);  // value = 1 << 1
731                         modulations.push_back(modulation);
732                         status.set<FrontendStatus::modulations>(modulations);
733                         break;
734                     }
735                     default:
736                         break;
737                 }
738                 break;
739             }
740             case FrontendStatusType::BERS: {
741                 vector<int32_t> bers = {1};
742                 status.set<FrontendStatus::bers>(bers);
743                 break;
744             }
745             case FrontendStatusType::CODERATES: {
746                 vector<FrontendInnerFec> rates;
747                 rates.push_back(FrontendInnerFec::FEC_6_15);  // value = 1 << 39
748                 status.set<FrontendStatus::codeRates>(rates);
749                 break;
750             }
751             case FrontendStatusType::BANDWIDTH: {
752                 FrontendBandwidth bandwidth;
753                 switch (mType) {
754                     case FrontendType::DVBC: {
755                         bandwidth.set<FrontendBandwidth::Tag::dvbc>(
756                                 FrontendDvbcBandwidth::BANDWIDTH_6MHZ);  // value = 1 << 1
757                         status.set<FrontendStatus::bandwidth>(bandwidth);
758                         break;
759                     }
760                     case FrontendType::DVBT: {
761                         bandwidth.set<FrontendBandwidth::Tag::dvbt>(
762                                 FrontendDvbtBandwidth::BANDWIDTH_8MHZ);  // value = 1 << 1
763                         status.set<FrontendStatus::bandwidth>(bandwidth);
764                         break;
765                     }
766                     case FrontendType::ISDBT: {
767                         bandwidth.set<FrontendBandwidth::Tag::isdbt>(
768                                 FrontendIsdbtBandwidth::BANDWIDTH_8MHZ);  // value = 1 << 1
769                         status.set<FrontendStatus::bandwidth>(bandwidth);
770                         break;
771                     }
772                     case FrontendType::ATSC3: {
773                         bandwidth.set<FrontendBandwidth::Tag::atsc3>(
774                                 FrontendAtsc3Bandwidth::BANDWIDTH_6MHZ);  // value = 1 << 1
775                         status.set<FrontendStatus::bandwidth>(bandwidth);
776                         break;
777                     }
778                     case FrontendType::DTMB: {
779                         bandwidth.set<FrontendBandwidth::Tag::dtmb>(
780                                 FrontendDtmbBandwidth::BANDWIDTH_8MHZ);  // value = 1 << 1
781                         status.set<FrontendStatus::bandwidth>(bandwidth);
782                         break;
783                     }
784                     default:
785                         break;
786                 }
787                 break;
788             }
789             case FrontendStatusType::GUARD_INTERVAL: {
790                 FrontendGuardInterval interval;
791                 switch (mType) {
792                     case FrontendType::DVBT: {
793                         interval.set<FrontendGuardInterval::Tag::dvbt>(
794                                 FrontendDvbtGuardInterval::INTERVAL_1_32);  // value = 1 << 1
795                         status.set<FrontendStatus::interval>(interval);
796                         break;
797                     }
798                     case FrontendType::ISDBT: {
799                         interval.set<FrontendGuardInterval::Tag::isdbt>(
800                                 FrontendIsdbtGuardInterval::INTERVAL_1_32);  // value = 1 << 1
801                         status.set<FrontendStatus::interval>(interval);
802                         break;
803                     }
804                     case FrontendType::DTMB: {
805                         interval.set<FrontendGuardInterval::Tag::dtmb>(
806                                 FrontendDtmbGuardInterval::PN_420_VARIOUS);  // value = 1 << 1
807                         status.set<FrontendStatus::interval>(interval);
808                         break;
809                     }
810                     default:
811                         break;
812                 }
813                 break;
814             }
815             case FrontendStatusType::TRANSMISSION_MODE: {
816                 FrontendTransmissionMode transMode;
817                 switch (mType) {
818                     case FrontendType::DVBT: {
819                         transMode.set<FrontendTransmissionMode::Tag::dvbt>(
820                                 FrontendDvbtTransmissionMode::MODE_16K_E);  // value = 1 << 8
821                         status.set<FrontendStatus::transmissionMode>(transMode);
822                         break;
823                     }
824                     case FrontendType::ISDBT: {
825                         transMode.set<FrontendTransmissionMode::Tag::isdbt>(
826                                 FrontendIsdbtMode::MODE_1);  // value = 1 << 1
827                         status.set<FrontendStatus::transmissionMode>(transMode);
828                         break;
829                     }
830                     case FrontendType::DTMB: {
831                         transMode.set<FrontendTransmissionMode::Tag::dtmb>(
832                                 FrontendDtmbTransmissionMode::C1);  // value = 1 << 1
833                         status.set<FrontendStatus::transmissionMode>(transMode);
834                         break;
835                     }
836                     default:
837                         break;
838                 }
839                 break;
840             }
841             case FrontendStatusType::UEC: {
842                 status.set<FrontendStatus::uec>(4);
843                 break;
844             }
845             case FrontendStatusType::T2_SYSTEM_ID: {
846                 status.set<FrontendStatus::systemId>(5);
847                 break;
848             }
849             case FrontendStatusType::INTERLEAVINGS: {
850                 FrontendInterleaveMode interleave;
851                 vector<FrontendInterleaveMode> interleaves;
852                 switch (mType) {
853                     case FrontendType::DVBC: {
854                         // value = 1 << 1
855                         interleave.set<FrontendInterleaveMode::Tag::dvbc>(
856                                 FrontendCableTimeInterleaveMode::INTERLEAVING_128_1_0);
857                         interleaves.push_back(interleave);
858                         status.set<FrontendStatus::interleaving>(interleaves);
859                         break;
860                     }
861                     case FrontendType::ATSC3: {
862                         interleave.set<FrontendInterleaveMode::Tag::atsc3>(
863                                 FrontendAtsc3TimeInterleaveMode::CTI);  // value = 1 << 1
864                         interleaves.push_back(interleave);
865                         status.set<FrontendStatus::interleaving>(interleaves);
866                         break;
867                     }
868                     case FrontendType::DTMB: {
869                         interleave.set<FrontendInterleaveMode::Tag::dtmb>(
870                                 FrontendDtmbTimeInterleaveMode::TIMER_INT_240);  // value = 1 << 1
871                         interleaves.push_back(interleave);
872                         status.set<FrontendStatus::interleaving>(interleaves);
873                         break;
874                     }
875                     case FrontendType::ISDBT: {
876                         interleave.set<FrontendInterleaveMode::Tag::isdbt>(
877                                 FrontendIsdbtTimeInterleaveMode::INTERLEAVE_1_0); // value = 1 << 1
878                         interleaves.push_back(interleave);
879                         status.set<FrontendStatus::interleaving>(interleaves);
880                         break;
881                     }
882                     default:
883                         break;
884                 }
885                 break;
886             }
887             case FrontendStatusType::ISDBT_SEGMENTS: {
888                 vector<int32_t> segments = {2, 3};
889                 status.set<FrontendStatus::isdbtSegment>(segments);
890                 break;
891             }
892             case FrontendStatusType::TS_DATA_RATES: {
893                 vector<int32_t> dataRates = {4, 5};
894                 status.set<FrontendStatus::tsDataRate>(dataRates);
895                 break;
896             }
897             case FrontendStatusType::ROLL_OFF: {
898                 FrontendRollOff rollOff;
899                 switch (mType) {
900                     case FrontendType::DVBS: {
901                         rollOff.set<FrontendRollOff::Tag::dvbs>(
902                                 FrontendDvbsRolloff::ROLLOFF_0_35);  // value = 1
903                         status.set<FrontendStatus::rollOff>(rollOff);
904                         break;
905                     }
906                     case FrontendType::ISDBS: {
907                         rollOff.set<FrontendRollOff::Tag::isdbs>(
908                                 FrontendIsdbsRolloff::ROLLOFF_0_35);  // value = 1
909                         status.set<FrontendStatus::rollOff>(rollOff);
910                         break;
911                     }
912                     case FrontendType::ISDBS3: {
913                         rollOff.set<FrontendRollOff::Tag::isdbs3>(
914                                 FrontendIsdbs3Rolloff::ROLLOFF_0_03);  // value = 1
915                         status.set<FrontendStatus::rollOff>(rollOff);
916                         break;
917                     }
918                     default:
919                         break;
920                 }
921                 break;
922             }
923             case FrontendStatusType::IS_MISO: {
924                 status.set<FrontendStatus::isMiso>(true);
925                 break;
926             }
927             case FrontendStatusType::IS_LINEAR: {
928                 status.set<FrontendStatus::isLinear>(true);
929                 break;
930             }
931             case FrontendStatusType::IS_SHORT_FRAMES: {
932                 status.set<FrontendStatus::isShortFrames>(true);
933                 break;
934             }
935             case FrontendStatusType::ISDBT_MODE: {
936                 status.set<FrontendStatus::isdbtMode>(FrontendIsdbtMode::AUTO);
937                 break;
938             }
939             case FrontendStatusType::ISDBT_PARTIAL_RECEPTION_FLAG: {
940                 status.set<FrontendStatus::partialReceptionFlag>(
941                         FrontendIsdbtPartialReceptionFlag::AUTO);
942                 break;
943             }
944             case FrontendStatusType::STREAM_ID_LIST: {
945                 vector<int32_t> streamIds = {0, 1};
946                 status.set<FrontendStatus::streamIdList>(streamIds);
947                 break;
948             }
949             case FrontendStatusType::DVBT_CELL_IDS: {
950                 vector<int32_t> dvbtCellIds = {0, 1};
951                 status.set<FrontendStatus::dvbtCellIds>(dvbtCellIds);
952                 break;
953             }
954             case FrontendStatusType::ATSC3_ALL_PLP_INFO: {
955                 FrontendScanAtsc3PlpInfo info1;
956                 info1.plpId = 1;
957                 info1.bLlsFlag = false;
958                 FrontendScanAtsc3PlpInfo info2;
959                 info2.plpId = 2;
960                 info2.bLlsFlag = true;
961                 FrontendScanAtsc3PlpInfo info3;
962                 info3.plpId = 3;
963                 info3.bLlsFlag = false;
964                 vector<FrontendScanAtsc3PlpInfo> infos = {info1, info2, info3};
965                 status.set<FrontendStatus::allPlpInfo>(infos);
966                 break;
967             }
968             case FrontendStatusType::IPTV_CONTENT_URL: {
969                 status.set<FrontendStatus::iptvContentUrl>("");
970                 break;
971             }
972             case FrontendStatusType::IPTV_PACKETS_LOST: {
973                 status.set<FrontendStatus::iptvPacketsLost>(5);
974                 break;
975             }
976             case FrontendStatusType::IPTV_PACKETS_RECEIVED: {
977                 status.set<FrontendStatus::iptvPacketsReceived>(5);
978                 break;
979             }
980             case FrontendStatusType::IPTV_WORST_JITTER_MS: {
981                 status.set<FrontendStatus::iptvWorstJitterMs>(5);
982                 break;
983             }
984             case FrontendStatusType::IPTV_AVERAGE_JITTER_MS: {
985                 status.set<FrontendStatus::iptvAverageJitterMs>(5);
986                 break;
987             }
988             default: {
989                 continue;
990             }
991         }
992         _aidl_return->push_back(status);
993     }
994 
995     return ::ndk::ScopedAStatus::ok();
996 }
997 
setLnb(int32_t)998 ::ndk::ScopedAStatus Frontend::setLnb(int32_t /* in_lnbId */) {
999     ALOGV("%s", __FUNCTION__);
1000     if (!supportsSatellite()) {
1001         return ::ndk::ScopedAStatus::fromServiceSpecificError(
1002                 static_cast<int32_t>(Result::INVALID_STATE));
1003     }
1004     return ::ndk::ScopedAStatus::ok();
1005 }
1006 
linkCiCam(int32_t in_ciCamId,int32_t * _aidl_return)1007 ::ndk::ScopedAStatus Frontend::linkCiCam(int32_t in_ciCamId, int32_t* _aidl_return) {
1008     ALOGV("%s", __FUNCTION__);
1009 
1010     mCiCamId = in_ciCamId;
1011     *_aidl_return = 0;
1012 
1013     return ::ndk::ScopedAStatus::ok();
1014 }
1015 
unlinkCiCam(int32_t)1016 ::ndk::ScopedAStatus Frontend::unlinkCiCam(int32_t /* in_ciCamId */) {
1017     ALOGV("%s", __FUNCTION__);
1018 
1019     mCiCamId = -1;
1020 
1021     return ::ndk::ScopedAStatus::ok();
1022 }
1023 
dump(int fd,const char **,uint32_t)1024 binder_status_t Frontend::dump(int fd, const char** /* args */, uint32_t /* numArgs */) {
1025     dprintf(fd, "  Frontend %d\n", mId);
1026     dprintf(fd, "    mType: %d\n", mType);
1027     dprintf(fd, "    mIsLocked: %d\n", mIsLocked);
1028     dprintf(fd, "    mCiCamId: %d\n", mCiCamId);
1029     dprintf(fd, "    mFrontendStatusCaps:");
1030     for (int i = 0; i < mFrontendStatusCaps.size(); i++) {
1031         dprintf(fd, "        %d\n", mFrontendStatusCaps[i]);
1032     }
1033     return STATUS_OK;
1034 }
1035 
getHardwareInfo(std::string * _aidl_return)1036 ::ndk::ScopedAStatus Frontend::getHardwareInfo(std::string* _aidl_return) {
1037     ALOGV("%s", __FUNCTION__);
1038 
1039     *_aidl_return = "Sample Frontend";
1040     return ::ndk::ScopedAStatus::ok();
1041 }
1042 
removeOutputPid(int32_t)1043 ::ndk::ScopedAStatus Frontend::removeOutputPid(int32_t /* in_pid */) {
1044     ALOGV("%s", __FUNCTION__);
1045 
1046     return ::ndk::ScopedAStatus::fromServiceSpecificError(
1047             static_cast<int32_t>(Result::UNAVAILABLE));
1048 }
1049 
getFrontendStatusReadiness(const std::vector<FrontendStatusType> & in_statusTypes,std::vector<FrontendStatusReadiness> * _aidl_return)1050 ::ndk::ScopedAStatus Frontend::getFrontendStatusReadiness(
1051         const std::vector<FrontendStatusType>& in_statusTypes,
1052         std::vector<FrontendStatusReadiness>* _aidl_return) {
1053     ALOGV("%s", __FUNCTION__);
1054 
1055     _aidl_return->resize(in_statusTypes.size());
1056     for (int i = 0; i < in_statusTypes.size(); i++) {
1057         int j = 0;
1058         while (j < mFrontendStatusCaps.size()) {
1059             if (in_statusTypes[i] == mFrontendStatusCaps[j]) {
1060                 (*_aidl_return)[i] = FrontendStatusReadiness::STABLE;
1061                 break;
1062             }
1063             j++;
1064         }
1065         if (j >= mFrontendStatusCaps.size()) {
1066             (*_aidl_return)[i] = FrontendStatusReadiness::UNSUPPORTED;
1067         }
1068     }
1069 
1070     return ::ndk::ScopedAStatus::ok();
1071 }
1072 
getFrontendType()1073 FrontendType Frontend::getFrontendType() {
1074     return mType;
1075 }
1076 
getFrontendId()1077 int32_t Frontend::getFrontendId() {
1078     return mId;
1079 }
1080 
getIptvPluginInterface()1081 dtv_plugin* Frontend::getIptvPluginInterface() {
1082     return mIptvPluginInterface;
1083 }
1084 
getIptvTransportDescription()1085 string Frontend::getIptvTransportDescription() {
1086     return mIptvTransportDescription;
1087 }
1088 
getIptvPluginStreamer()1089 dtv_streamer* Frontend::getIptvPluginStreamer() {
1090     return mIptvPluginStreamer;
1091 }
1092 
supportsSatellite()1093 bool Frontend::supportsSatellite() {
1094     return mType == FrontendType::DVBS || mType == FrontendType::ISDBS ||
1095            mType == FrontendType::ISDBS3;
1096 }
1097 
isLocked()1098 bool Frontend::isLocked() {
1099     return mIsLocked;
1100 }
1101 
getFrontendInfo(FrontendInfo * _aidl_return)1102 void Frontend::getFrontendInfo(FrontendInfo* _aidl_return) {
1103     // assign randomly selected values for testing.
1104     *_aidl_return = {
1105             .type = mType,
1106             .minFrequency = 139000000,
1107             .maxFrequency = 1139000000,
1108             .minSymbolRate = 45,
1109             .maxSymbolRate = 1145,
1110             .acquireRange = 30,
1111             .exclusiveGroupId = 57,
1112             .statusCaps = mFrontendStatusCaps,
1113             .frontendCaps = mFrontendCaps,
1114     };
1115 }
1116 
1117 }  // namespace tuner
1118 }  // namespace tv
1119 }  // namespace hardware
1120 }  // namespace android
1121 }  // namespace aidl
1122