1 /**
2 * Copyright (c) 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 "TunerHidlService"
19
20 #include "TunerHidlService.h"
21
22 #include <aidl/android/hardware/tv/tuner/FrontendIsdbtTimeInterleaveMode.h>
23 #include <aidl/android/hardware/tv/tuner/Result.h>
24 #include <android/binder_manager.h>
25 #include <binder/IPCThreadState.h>
26 #include <binder/PermissionCache.h>
27 #include <cutils/properties.h>
28 #include <utils/Log.h>
29
30 #include "TunerHelper.h"
31 #include "TunerHidlDemux.h"
32 #include "TunerHidlDescrambler.h"
33 #include "TunerHidlFrontend.h"
34 #include "TunerHidlLnb.h"
35
36 using ::aidl::android::hardware::tv::tuner::FrontendAnalogCapabilities;
37 using ::aidl::android::hardware::tv::tuner::FrontendAtsc3Capabilities;
38 using ::aidl::android::hardware::tv::tuner::FrontendAtscCapabilities;
39 using ::aidl::android::hardware::tv::tuner::FrontendCapabilities;
40 using ::aidl::android::hardware::tv::tuner::FrontendDtmbCapabilities;
41 using ::aidl::android::hardware::tv::tuner::FrontendDvbcCapabilities;
42 using ::aidl::android::hardware::tv::tuner::FrontendDvbsCapabilities;
43 using ::aidl::android::hardware::tv::tuner::FrontendDvbtCapabilities;
44 using ::aidl::android::hardware::tv::tuner::FrontendIsdbs3Capabilities;
45 using ::aidl::android::hardware::tv::tuner::FrontendIsdbsCapabilities;
46 using ::aidl::android::hardware::tv::tuner::FrontendIsdbtCapabilities;
47 using ::aidl::android::hardware::tv::tuner::FrontendIsdbtTimeInterleaveMode;
48 using ::aidl::android::hardware::tv::tuner::FrontendType;
49 using ::aidl::android::hardware::tv::tuner::Result;
50 using ::android::IPCThreadState;
51 using ::android::PermissionCache;
52 using ::android::hardware::hidl_vec;
53
54 using HidlFrontendId = ::android::hardware::tv::tuner::V1_0::FrontendId;
55 using HidlLnbId = ::android::hardware::tv::tuner::V1_0::LnbId;
56 using HidlFrontendType = ::android::hardware::tv::tuner::V1_1::FrontendType;
57
58 using namespace std;
59
60 namespace aidl {
61 namespace android {
62 namespace media {
63 namespace tv {
64 namespace tuner {
65
TunerHidlService()66 TunerHidlService::TunerHidlService() {
67 mTuner = HidlITuner::getService();
68 ALOGE_IF(mTuner == nullptr, "Failed to get ITuner service");
69 mTunerVersion = TUNER_HAL_VERSION_1_0;
70
71 mTuner_1_1 = ::android::hardware::tv::tuner::V1_1::ITuner::castFrom(mTuner);
72 if (mTuner_1_1 != nullptr) {
73 mTunerVersion = TUNER_HAL_VERSION_1_1;
74 } else {
75 ALOGD("Failed to get ITuner_1_1 service");
76 }
77
78 // Register tuner resources to TRM.
79 updateTunerResources();
80 }
81
~TunerHidlService()82 TunerHidlService::~TunerHidlService() {
83 mOpenedFrontends.clear();
84 mLnaStatus = -1;
85 mTuner = nullptr;
86 mTuner_1_1 = nullptr;
87 }
88
instantiate()89 binder_status_t TunerHidlService::instantiate() {
90 if (HidlITuner::getService() == nullptr) {
91 ALOGD("Failed to get ITuner HIDL HAL");
92 return STATUS_NAME_NOT_FOUND;
93 }
94
95 shared_ptr<TunerHidlService> tunerService = ::ndk::SharedRefBase::make<TunerHidlService>();
96 bool lazyHal = property_get_bool("ro.tuner.lazyhal", false);
97 if (lazyHal) {
98 return AServiceManager_registerLazyService(tunerService->asBinder().get(),
99 getServiceName());
100 }
101 return AServiceManager_addService(tunerService->asBinder().get(), getServiceName());
102 }
103
openDemux(int32_t,shared_ptr<ITunerDemux> * _aidl_return)104 ::ndk::ScopedAStatus TunerHidlService::openDemux(int32_t /* in_demuxHandle */,
105 shared_ptr<ITunerDemux>* _aidl_return) {
106 ALOGV("openDemux");
107 HidlResult res;
108 uint32_t id;
109 sp<IDemux> demuxSp = nullptr;
110 mTuner->openDemux([&](HidlResult r, uint32_t demuxId, const sp<IDemux>& demux) {
111 demuxSp = demux;
112 id = demuxId;
113 res = r;
114 ALOGD("open demux, id = %d", demuxId);
115 });
116 if (res == HidlResult::SUCCESS) {
117 *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlDemux>(demuxSp, id,
118 this->ref<TunerHidlService>());
119 return ::ndk::ScopedAStatus::ok();
120 }
121
122 ALOGW("open demux failed, res = %d", res);
123 return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
124 }
125
getDemuxInfo(int32_t,DemuxInfo *)126 ::ndk::ScopedAStatus TunerHidlService::getDemuxInfo(int32_t /* in_demuxHandle */,
127 DemuxInfo* /* _aidl_return */) {
128 ALOGE("getDemuxInfo is not supported");
129 return ::ndk::ScopedAStatus::fromServiceSpecificError(
130 static_cast<int32_t>(HidlResult::UNAVAILABLE));
131 }
132
getDemuxInfoList(vector<DemuxInfo> *)133 ::ndk::ScopedAStatus TunerHidlService::getDemuxInfoList(
134 vector<DemuxInfo>* /* _aidle_return */) {
135 ALOGE("getDemuxInfoList is not supported");
136 return ::ndk::ScopedAStatus::fromServiceSpecificError(
137 static_cast<int32_t>(HidlResult::UNAVAILABLE));
138 }
139
getDemuxCaps(DemuxCapabilities * _aidl_return)140 ::ndk::ScopedAStatus TunerHidlService::getDemuxCaps(DemuxCapabilities* _aidl_return) {
141 ALOGV("getDemuxCaps");
142 HidlResult res;
143 HidlDemuxCapabilities caps;
144 mTuner->getDemuxCaps([&](HidlResult r, const HidlDemuxCapabilities& demuxCaps) {
145 caps = demuxCaps;
146 res = r;
147 });
148 if (res == HidlResult::SUCCESS) {
149 *_aidl_return = getAidlDemuxCaps(caps);
150 return ::ndk::ScopedAStatus::ok();
151 }
152
153 ALOGW("Get demux caps failed, res = %d", res);
154 return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
155 }
156
getFrontendIds(vector<int32_t> * ids)157 ::ndk::ScopedAStatus TunerHidlService::getFrontendIds(vector<int32_t>* ids) {
158 hidl_vec<HidlFrontendId> feIds;
159 HidlResult res = getHidlFrontendIds(feIds);
160 if (res != HidlResult::SUCCESS) {
161 return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
162 }
163 ids->resize(feIds.size());
164 copy(feIds.begin(), feIds.end(), ids->begin());
165
166 return ::ndk::ScopedAStatus::ok();
167 }
168
getFrontendInfo(int32_t id,FrontendInfo * _aidl_return)169 ::ndk::ScopedAStatus TunerHidlService::getFrontendInfo(int32_t id, FrontendInfo* _aidl_return) {
170 HidlFrontendInfo info;
171 HidlResult res = getHidlFrontendInfo(id, info);
172 if (res != HidlResult::SUCCESS) {
173 return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
174 }
175
176 HidlFrontendDtmbCapabilities dtmbCaps;
177 if (static_cast<HidlFrontendType>(info.type) == HidlFrontendType::DTMB) {
178 if (mTuner_1_1 == nullptr) {
179 ALOGE("ITuner_1_1 service is not init.");
180 return ::ndk::ScopedAStatus::fromServiceSpecificError(
181 static_cast<int32_t>(Result::UNAVAILABLE));
182 }
183
184 mTuner_1_1->getFrontendDtmbCapabilities(
185 id, [&](HidlResult r, const HidlFrontendDtmbCapabilities& caps) {
186 dtmbCaps = caps;
187 res = r;
188 });
189 if (res != HidlResult::SUCCESS) {
190 return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
191 }
192 }
193
194 *_aidl_return = getAidlFrontendInfo(info, dtmbCaps);
195 return ::ndk::ScopedAStatus::ok();
196 }
197
openFrontend(int32_t frontendHandle,shared_ptr<ITunerFrontend> * _aidl_return)198 ::ndk::ScopedAStatus TunerHidlService::openFrontend(int32_t frontendHandle,
199 shared_ptr<ITunerFrontend>* _aidl_return) {
200 HidlResult status;
201 sp<HidlIFrontend> frontend;
202 int id = TunerHelper::getResourceIdFromHandle(frontendHandle, FRONTEND);
203 mTuner->openFrontendById(id, [&](HidlResult result, const sp<HidlIFrontend>& fe) {
204 frontend = fe;
205 status = result;
206 });
207 if (status != HidlResult::SUCCESS) {
208 return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
209 }
210
211 shared_ptr<TunerHidlFrontend> tunerFrontend = ::ndk::SharedRefBase::make<TunerHidlFrontend>(
212 frontend, id, this->ref<TunerHidlService>());
213 if (mLnaStatus != -1) {
214 tunerFrontend->setLna(mLnaStatus == 1);
215 }
216 {
217 Mutex::Autolock _l(mOpenedFrontendsLock);
218 mOpenedFrontends.insert(tunerFrontend);
219 }
220 *_aidl_return = tunerFrontend;
221 return ::ndk::ScopedAStatus::ok();
222 }
223
openLnb(int lnbHandle,shared_ptr<ITunerLnb> * _aidl_return)224 ::ndk::ScopedAStatus TunerHidlService::openLnb(int lnbHandle, shared_ptr<ITunerLnb>* _aidl_return) {
225 HidlResult status;
226 sp<HidlILnb> lnb;
227 int id = TunerHelper::getResourceIdFromHandle(lnbHandle, LNB);
228 mTuner->openLnbById(id, [&](HidlResult result, const sp<HidlILnb>& lnbSp) {
229 lnb = lnbSp;
230 status = result;
231 });
232 if (status != HidlResult::SUCCESS) {
233 return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
234 }
235
236 *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlLnb>(lnb, id);
237 return ::ndk::ScopedAStatus::ok();
238 }
239
openLnbByName(const string & lnbName,shared_ptr<ITunerLnb> * _aidl_return)240 ::ndk::ScopedAStatus TunerHidlService::openLnbByName(const string& lnbName,
241 shared_ptr<ITunerLnb>* _aidl_return) {
242 int lnbId;
243 HidlResult status;
244 sp<HidlILnb> lnb;
245 mTuner->openLnbByName(lnbName, [&](HidlResult r, HidlLnbId id, const sp<HidlILnb>& lnbSp) {
246 status = r;
247 lnb = lnbSp;
248 lnbId = static_cast<int32_t>(id);
249 });
250 if (status != HidlResult::SUCCESS) {
251 return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
252 }
253
254 *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlLnb>(lnb, lnbId);
255 return ::ndk::ScopedAStatus::ok();
256 }
257
openDescrambler(int32_t,shared_ptr<ITunerDescrambler> * _aidl_return)258 ::ndk::ScopedAStatus TunerHidlService::openDescrambler(
259 int32_t /*descramblerHandle*/, shared_ptr<ITunerDescrambler>* _aidl_return) {
260 HidlResult status;
261 sp<HidlIDescrambler> descrambler;
262 //int id = TunerHelper::getResourceIdFromHandle(descramblerHandle, DESCRAMBLER);
263 mTuner->openDescrambler([&](HidlResult r, const sp<HidlIDescrambler>& descramblerSp) {
264 status = r;
265 descrambler = descramblerSp;
266 });
267 if (status != HidlResult::SUCCESS) {
268 return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
269 }
270
271 *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlDescrambler>(descrambler);
272 return ::ndk::ScopedAStatus::ok();
273 }
274
getTunerHalVersion(int * _aidl_return)275 ::ndk::ScopedAStatus TunerHidlService::getTunerHalVersion(int* _aidl_return) {
276 *_aidl_return = mTunerVersion;
277 return ::ndk::ScopedAStatus::ok();
278 }
279
openSharedFilter(const string & in_filterToken,const shared_ptr<ITunerFilterCallback> & in_cb,shared_ptr<ITunerFilter> * _aidl_return)280 ::ndk::ScopedAStatus TunerHidlService::openSharedFilter(
281 const string& in_filterToken, const shared_ptr<ITunerFilterCallback>& in_cb,
282 shared_ptr<ITunerFilter>* _aidl_return) {
283 if (mTuner == nullptr) {
284 ALOGE("get ITuner failed");
285 return ::ndk::ScopedAStatus::fromServiceSpecificError(
286 static_cast<int32_t>(Result::UNAVAILABLE));
287 }
288
289 if (!PermissionCache::checkCallingPermission(sSharedFilterPermission)) {
290 ALOGE("Request requires android.permission.ACCESS_TV_SHARED_FILTER");
291 return ::ndk::ScopedAStatus::fromServiceSpecificError(
292 static_cast<int32_t>(Result::UNAVAILABLE));
293 }
294
295 Mutex::Autolock _l(mSharedFiltersLock);
296 if (mSharedFilters.find(in_filterToken) == mSharedFilters.end()) {
297 *_aidl_return = nullptr;
298 ALOGD("fail to find %s", in_filterToken.c_str());
299 return ::ndk::ScopedAStatus::fromServiceSpecificError(
300 static_cast<int32_t>(Result::INVALID_STATE));
301 }
302
303 shared_ptr<TunerHidlFilter> filter = mSharedFilters.at(in_filterToken);
304 IPCThreadState* ipc = IPCThreadState::self();
305 const int pid = ipc->getCallingPid();
306 if (!filter->isSharedFilterAllowed(pid)) {
307 *_aidl_return = nullptr;
308 ALOGD("shared filter %s is opened in the same process", in_filterToken.c_str());
309 return ::ndk::ScopedAStatus::fromServiceSpecificError(
310 static_cast<int32_t>(Result::INVALID_STATE));
311 }
312
313 filter->attachSharedFilterCallback(in_cb);
314
315 *_aidl_return = filter;
316 return ::ndk::ScopedAStatus::ok();
317 }
318
isLnaSupported(bool *)319 ::ndk::ScopedAStatus TunerHidlService::isLnaSupported(bool* /* _aidl_return */) {
320 return ::ndk::ScopedAStatus::fromServiceSpecificError(
321 static_cast<int32_t>(Result::UNAVAILABLE));
322 }
323
setLna(bool bEnable)324 ::ndk::ScopedAStatus TunerHidlService::setLna(bool bEnable) {
325 if (mTuner == nullptr) {
326 ALOGE("get ITuner failed");
327 return ::ndk::ScopedAStatus::fromServiceSpecificError(
328 static_cast<int32_t>(Result::UNAVAILABLE));
329 }
330
331 mLnaStatus = bEnable ? 1 : 0;
332
333 {
334 Mutex::Autolock _l(mOpenedFrontendsLock);
335 for (auto it = mOpenedFrontends.begin(); it != mOpenedFrontends.end(); ++it) {
336 (*it)->setLna(mLnaStatus == 1);
337 }
338 }
339
340 return ::ndk::ScopedAStatus::ok();
341 }
342
setMaxNumberOfFrontends(FrontendType,int32_t)343 ::ndk::ScopedAStatus TunerHidlService::setMaxNumberOfFrontends(FrontendType /* in_frontendType */,
344 int32_t /* in_maxNumber */) {
345 return ::ndk::ScopedAStatus::fromServiceSpecificError(
346 static_cast<int32_t>(Result::UNAVAILABLE));
347 }
348
getMaxNumberOfFrontends(FrontendType,int32_t * _aidl_return)349 ::ndk::ScopedAStatus TunerHidlService::getMaxNumberOfFrontends(FrontendType /* in_frontendType */,
350 int32_t* _aidl_return) {
351 *_aidl_return = -1;
352 return ::ndk::ScopedAStatus::fromServiceSpecificError(
353 static_cast<int32_t>(Result::UNAVAILABLE));
354 }
355
addFilterToShared(const shared_ptr<TunerHidlFilter> & sharedFilter)356 string TunerHidlService::addFilterToShared(const shared_ptr<TunerHidlFilter>& sharedFilter) {
357 Mutex::Autolock _l(mSharedFiltersLock);
358
359 // Use sharedFilter address as token.
360 string token = to_string(reinterpret_cast<std::uintptr_t>(sharedFilter.get()));
361 mSharedFilters[token] = sharedFilter;
362
363 return token;
364 }
365
removeSharedFilter(const shared_ptr<TunerHidlFilter> & sharedFilter)366 void TunerHidlService::removeSharedFilter(const shared_ptr<TunerHidlFilter>& sharedFilter) {
367 Mutex::Autolock _l(mSharedFiltersLock);
368
369 // Use sharedFilter address as token.
370 mSharedFilters.erase(to_string(reinterpret_cast<std::uintptr_t>(sharedFilter.get())));
371 }
372
removeFrontend(const shared_ptr<TunerHidlFrontend> & frontend)373 void TunerHidlService::removeFrontend(const shared_ptr<TunerHidlFrontend>& frontend) {
374 Mutex::Autolock _l(mOpenedFrontendsLock);
375 for (auto it = mOpenedFrontends.begin(); it != mOpenedFrontends.end(); ++it) {
376 if (it->get() == frontend.get()) {
377 mOpenedFrontends.erase(it);
378 break;
379 }
380 }
381 }
382
updateTunerResources()383 void TunerHidlService::updateTunerResources() {
384 TunerHelper::updateTunerResources(getTRMFrontendInfos(), getTRMLnbHandles());
385 }
386
getTRMFrontendInfos()387 vector<TunerFrontendInfo> TunerHidlService::getTRMFrontendInfos() {
388 vector<TunerFrontendInfo> infos;
389 hidl_vec<HidlFrontendId> ids;
390 HidlResult res = getHidlFrontendIds(ids);
391 if (res != HidlResult::SUCCESS) {
392 return infos;
393 }
394
395 for (int i = 0; i < ids.size(); i++) {
396 HidlFrontendInfo frontendInfo;
397 HidlResult res = getHidlFrontendInfo(static_cast<int32_t>(ids[i]), frontendInfo);
398 if (res != HidlResult::SUCCESS) {
399 continue;
400 }
401 TunerFrontendInfo tunerFrontendInfo{
402 .handle = TunerHelper::getResourceHandleFromId(static_cast<int32_t>(ids[i]),
403 FRONTEND),
404 .type = static_cast<int32_t>(frontendInfo.type),
405 .exclusiveGroupId = static_cast<int32_t>(frontendInfo.exclusiveGroupId),
406 };
407 infos.push_back(tunerFrontendInfo);
408 }
409
410 return infos;
411 }
412
getTRMLnbHandles()413 vector<int32_t> TunerHidlService::getTRMLnbHandles() {
414 vector<int32_t> lnbHandles;
415 if (mTuner != nullptr) {
416 HidlResult res;
417 vector<HidlLnbId> lnbIds;
418 mTuner->getLnbIds([&](HidlResult r, const hidl_vec<HidlLnbId>& ids) {
419 lnbIds = ids;
420 res = r;
421 });
422 if (res == HidlResult::SUCCESS && lnbIds.size() > 0) {
423 for (int i = 0; i < lnbIds.size(); i++) {
424 lnbHandles.push_back(
425 TunerHelper::getResourceHandleFromId(static_cast<int32_t>(lnbIds[i]), LNB));
426 }
427 }
428 }
429
430 return lnbHandles;
431 }
432
getHidlFrontendIds(hidl_vec<HidlFrontendId> & ids)433 HidlResult TunerHidlService::getHidlFrontendIds(hidl_vec<HidlFrontendId>& ids) {
434 if (mTuner == nullptr) {
435 return HidlResult::NOT_INITIALIZED;
436 }
437 HidlResult res;
438 mTuner->getFrontendIds([&](HidlResult r, const hidl_vec<HidlFrontendId>& frontendIds) {
439 ids = frontendIds;
440 res = r;
441 });
442 return res;
443 }
444
getHidlFrontendInfo(const int id,HidlFrontendInfo & info)445 HidlResult TunerHidlService::getHidlFrontendInfo(const int id, HidlFrontendInfo& info) {
446 if (mTuner == nullptr) {
447 return HidlResult::NOT_INITIALIZED;
448 }
449 HidlResult res;
450 mTuner->getFrontendInfo(id, [&](HidlResult r, const HidlFrontendInfo& feInfo) {
451 info = feInfo;
452 res = r;
453 });
454 return res;
455 }
456
getAidlDemuxCaps(const HidlDemuxCapabilities & caps)457 DemuxCapabilities TunerHidlService::getAidlDemuxCaps(const HidlDemuxCapabilities& caps) {
458 DemuxCapabilities aidlCaps{
459 .numDemux = static_cast<int32_t>(caps.numDemux),
460 .numRecord = static_cast<int32_t>(caps.numRecord),
461 .numPlayback = static_cast<int32_t>(caps.numPlayback),
462 .numTsFilter = static_cast<int32_t>(caps.numTsFilter),
463 .numSectionFilter = static_cast<int32_t>(caps.numSectionFilter),
464 .numAudioFilter = static_cast<int32_t>(caps.numAudioFilter),
465 .numVideoFilter = static_cast<int32_t>(caps.numVideoFilter),
466 .numPesFilter = static_cast<int32_t>(caps.numPesFilter),
467 .numPcrFilter = static_cast<int32_t>(caps.numPcrFilter),
468 .numBytesInSectionFilter = static_cast<int64_t>(caps.numBytesInSectionFilter),
469 .filterCaps = static_cast<int32_t>(caps.filterCaps),
470 .bTimeFilter = caps.bTimeFilter,
471 };
472 aidlCaps.linkCaps.resize(caps.linkCaps.size());
473 copy(caps.linkCaps.begin(), caps.linkCaps.end(), aidlCaps.linkCaps.begin());
474 return aidlCaps;
475 }
476
getAidlFrontendInfo(const HidlFrontendInfo & halInfo,const HidlFrontendDtmbCapabilities & halDtmbCaps)477 FrontendInfo TunerHidlService::getAidlFrontendInfo(
478 const HidlFrontendInfo& halInfo, const HidlFrontendDtmbCapabilities& halDtmbCaps) {
479 FrontendInfo info{
480 .type = static_cast<FrontendType>(halInfo.type),
481 .minFrequency = static_cast<int64_t>(halInfo.minFrequency),
482 .maxFrequency = static_cast<int64_t>(halInfo.maxFrequency),
483 .minSymbolRate = static_cast<int32_t>(halInfo.minSymbolRate),
484 .maxSymbolRate = static_cast<int32_t>(halInfo.maxSymbolRate),
485 .acquireRange = static_cast<int64_t>(halInfo.acquireRange),
486 .exclusiveGroupId = static_cast<int32_t>(halInfo.exclusiveGroupId),
487 };
488 for (int i = 0; i < halInfo.statusCaps.size(); i++) {
489 info.statusCaps.push_back(static_cast<FrontendStatusType>(halInfo.statusCaps[i]));
490 }
491
492 FrontendCapabilities caps;
493 switch (halInfo.type) {
494 case ::android::hardware::tv::tuner::V1_0::FrontendType::ANALOG: {
495 if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::analogCaps ==
496 halInfo.frontendCaps.getDiscriminator()) {
497 FrontendAnalogCapabilities analogCaps{
498 .typeCap = static_cast<int32_t>(halInfo.frontendCaps.analogCaps().typeCap),
499 .sifStandardCap =
500 static_cast<int32_t>(halInfo.frontendCaps.analogCaps().sifStandardCap),
501 };
502 caps.set<FrontendCapabilities::analogCaps>(analogCaps);
503 }
504 break;
505 }
506 case ::android::hardware::tv::tuner::V1_0::FrontendType::ATSC: {
507 if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::atscCaps ==
508 halInfo.frontendCaps.getDiscriminator()) {
509 FrontendAtscCapabilities atscCaps{
510 .modulationCap =
511 static_cast<int32_t>(halInfo.frontendCaps.atscCaps().modulationCap),
512 };
513 caps.set<FrontendCapabilities::atscCaps>(atscCaps);
514 }
515 break;
516 }
517 case ::android::hardware::tv::tuner::V1_0::FrontendType::ATSC3: {
518 if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::atsc3Caps ==
519 halInfo.frontendCaps.getDiscriminator()) {
520 FrontendAtsc3Capabilities atsc3Caps{
521 .bandwidthCap =
522 static_cast<int32_t>(halInfo.frontendCaps.atsc3Caps().bandwidthCap),
523 .modulationCap =
524 static_cast<int32_t>(halInfo.frontendCaps.atsc3Caps().modulationCap),
525 .timeInterleaveModeCap = static_cast<int32_t>(
526 halInfo.frontendCaps.atsc3Caps().timeInterleaveModeCap),
527 .codeRateCap =
528 static_cast<int32_t>(halInfo.frontendCaps.atsc3Caps().codeRateCap),
529 .demodOutputFormatCap = static_cast<int8_t>(
530 halInfo.frontendCaps.atsc3Caps().demodOutputFormatCap),
531 .fecCap = static_cast<int32_t>(halInfo.frontendCaps.atsc3Caps().fecCap),
532 };
533 caps.set<FrontendCapabilities::atsc3Caps>(atsc3Caps);
534 }
535 break;
536 }
537 case ::android::hardware::tv::tuner::V1_0::FrontendType::DVBC: {
538 if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::dvbcCaps ==
539 halInfo.frontendCaps.getDiscriminator()) {
540 FrontendDvbcCapabilities dvbcCaps{
541 .modulationCap =
542 static_cast<int32_t>(halInfo.frontendCaps.dvbcCaps().modulationCap),
543 .fecCap = static_cast<int64_t>(halInfo.frontendCaps.dvbcCaps().fecCap),
544 .annexCap = static_cast<int8_t>(halInfo.frontendCaps.dvbcCaps().annexCap),
545 };
546 caps.set<FrontendCapabilities::dvbcCaps>(dvbcCaps);
547 }
548 break;
549 }
550 case ::android::hardware::tv::tuner::V1_0::FrontendType::DVBS: {
551 if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::dvbsCaps ==
552 halInfo.frontendCaps.getDiscriminator()) {
553 FrontendDvbsCapabilities dvbsCaps{
554 .modulationCap =
555 static_cast<int32_t>(halInfo.frontendCaps.dvbsCaps().modulationCap),
556 .innerfecCap =
557 static_cast<int64_t>(halInfo.frontendCaps.dvbsCaps().innerfecCap),
558 .standard = static_cast<int8_t>(halInfo.frontendCaps.dvbsCaps().standard),
559 };
560 caps.set<FrontendCapabilities::dvbsCaps>(dvbsCaps);
561 }
562 break;
563 }
564 case ::android::hardware::tv::tuner::V1_0::FrontendType::DVBT: {
565 if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::dvbtCaps ==
566 halInfo.frontendCaps.getDiscriminator()) {
567 FrontendDvbtCapabilities dvbtCaps{
568 .transmissionModeCap = static_cast<int32_t>(
569 halInfo.frontendCaps.dvbtCaps().transmissionModeCap),
570 .bandwidthCap =
571 static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().bandwidthCap),
572 .constellationCap =
573 static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().constellationCap),
574 .coderateCap =
575 static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().coderateCap),
576 .hierarchyCap =
577 static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().hierarchyCap),
578 .guardIntervalCap =
579 static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().guardIntervalCap),
580 .isT2Supported = halInfo.frontendCaps.dvbtCaps().isT2Supported,
581 .isMisoSupported = halInfo.frontendCaps.dvbtCaps().isMisoSupported,
582 };
583 caps.set<FrontendCapabilities::dvbtCaps>(dvbtCaps);
584 }
585 break;
586 }
587 case ::android::hardware::tv::tuner::V1_0::FrontendType::ISDBS: {
588 if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::isdbsCaps ==
589 halInfo.frontendCaps.getDiscriminator()) {
590 FrontendIsdbsCapabilities isdbsCaps{
591 .modulationCap =
592 static_cast<int32_t>(halInfo.frontendCaps.isdbsCaps().modulationCap),
593 .coderateCap =
594 static_cast<int32_t>(halInfo.frontendCaps.isdbsCaps().coderateCap),
595 };
596 caps.set<FrontendCapabilities::isdbsCaps>(isdbsCaps);
597 }
598 break;
599 }
600 case ::android::hardware::tv::tuner::V1_0::FrontendType::ISDBS3: {
601 if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::isdbs3Caps ==
602 halInfo.frontendCaps.getDiscriminator()) {
603 FrontendIsdbs3Capabilities isdbs3Caps{
604 .modulationCap =
605 static_cast<int32_t>(halInfo.frontendCaps.isdbs3Caps().modulationCap),
606 .coderateCap =
607 static_cast<int32_t>(halInfo.frontendCaps.isdbs3Caps().coderateCap),
608 };
609 caps.set<FrontendCapabilities::isdbs3Caps>(isdbs3Caps);
610 }
611 break;
612 }
613 case ::android::hardware::tv::tuner::V1_0::FrontendType::ISDBT: {
614 if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::isdbtCaps ==
615 halInfo.frontendCaps.getDiscriminator()) {
616 FrontendIsdbtCapabilities isdbtCaps{
617 .modeCap = static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().modeCap),
618 .bandwidthCap =
619 static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().bandwidthCap),
620 .modulationCap =
621 static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().modulationCap),
622 .coderateCap =
623 static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().coderateCap),
624 .guardIntervalCap =
625 static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().guardIntervalCap),
626 .timeInterleaveCap =
627 static_cast<int32_t>(FrontendIsdbtTimeInterleaveMode::UNDEFINED),
628 .isSegmentAuto = false,
629 .isFullSegment = false,
630 };
631 caps.set<FrontendCapabilities::isdbtCaps>(isdbtCaps);
632 }
633 break;
634 }
635 default: {
636 if (static_cast<HidlFrontendType>(info.type) == HidlFrontendType::DTMB) {
637 FrontendDtmbCapabilities dtmbCaps{
638 .transmissionModeCap = static_cast<int32_t>(halDtmbCaps.transmissionModeCap),
639 .bandwidthCap = static_cast<int32_t>(halDtmbCaps.bandwidthCap),
640 .modulationCap = static_cast<int32_t>(halDtmbCaps.modulationCap),
641 .codeRateCap = static_cast<int32_t>(halDtmbCaps.codeRateCap),
642 .guardIntervalCap = static_cast<int32_t>(halDtmbCaps.guardIntervalCap),
643 .interleaveModeCap = static_cast<int32_t>(halDtmbCaps.interleaveModeCap),
644 };
645 caps.set<FrontendCapabilities::dtmbCaps>(dtmbCaps);
646 }
647 break;
648 }
649 }
650
651 info.frontendCaps = caps;
652 return info;
653 }
654
655 } // namespace tuner
656 } // namespace tv
657 } // namespace media
658 } // namespace android
659 } // namespace aidl
660