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