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