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