• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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