• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2020, 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_TAG "TunerService"
18 
19 #include <android/binder_manager.h>
20 #include <android/content/pm/IPackageManagerNative.h>
21 #include <binder/IServiceManager.h>
22 #include <utils/Log.h>
23 #include "TunerService.h"
24 #include "TunerFrontend.h"
25 #include "TunerLnb.h"
26 #include "TunerDemux.h"
27 #include "TunerDescrambler.h"
28 
29 using ::aidl::android::media::tv::tuner::TunerFrontendAnalogCapabilities;
30 using ::aidl::android::media::tv::tuner::TunerFrontendAtsc3Capabilities;
31 using ::aidl::android::media::tv::tuner::TunerFrontendAtscCapabilities;
32 using ::aidl::android::media::tv::tuner::TunerFrontendCableCapabilities;
33 using ::aidl::android::media::tv::tuner::TunerFrontendCapabilities;
34 using ::aidl::android::media::tv::tuner::TunerFrontendDvbsCapabilities;
35 using ::aidl::android::media::tv::tuner::TunerFrontendDvbtCapabilities;
36 using ::aidl::android::media::tv::tuner::TunerFrontendIsdbs3Capabilities;
37 using ::aidl::android::media::tv::tuner::TunerFrontendIsdbsCapabilities;
38 using ::aidl::android::media::tv::tuner::TunerFrontendIsdbtCapabilities;
39 using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
40 using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
41 using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
42 using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
43 using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
44 using ::android::hardware::tv::tuner::V1_0::FrontendId;
45 using ::android::hardware::tv::tuner::V1_0::FrontendType;
46 using ::android::hardware::tv::tuner::V1_0::IFrontend;
47 using ::android::hardware::tv::tuner::V1_0::ILnb;
48 using ::android::hardware::tv::tuner::V1_0::LnbId;
49 using ::android::hardware::tv::tuner::V1_0::Result;
50 using ::android::hardware::tv::tuner::V1_1::FrontendDtmbCapabilities;
51 
52 namespace android {
53 
TunerService()54 TunerService::TunerService() {
55     sp<IServiceManager> serviceMgr = defaultServiceManager();
56     sp<content::pm::IPackageManagerNative> packageMgr;
57     if (serviceMgr.get() == nullptr) {
58         ALOGE("%s: Cannot find service manager", __func__);
59         return;
60     } else {
61         sp<IBinder> binder = serviceMgr->waitForService(String16("package_native"));
62         packageMgr = interface_cast<content::pm::IPackageManagerNative>(binder);
63     }
64 
65     bool hasFeature = false;
66     if (packageMgr != nullptr) {
67         binder::Status status = packageMgr->hasSystemFeature(FEATURE_TUNER, 0, &hasFeature);
68         if (!status.isOk()) {
69             ALOGE("%s: hasSystemFeature failed: %s",
70                     __func__, status.exceptionMessage().c_str());
71             return;
72         }
73         if (!hasFeature) {
74             ALOGD("Current device does not support tuner feaure.");
75             return;
76         }
77     } else {
78         ALOGD("%s: Cannot find package manager.", __func__);
79         return;
80     }
81 
82     ::ndk::SpAIBinder binder(AServiceManager_waitForService("tv_tuner_resource_mgr"));
83     mTunerResourceManager = ITunerResourceManager::fromBinder(binder);
84     updateTunerResources();
85 }
86 
~TunerService()87 TunerService::~TunerService() {}
88 
instantiate()89 binder_status_t TunerService::instantiate() {
90     shared_ptr<TunerService> service =
91             ::ndk::SharedRefBase::make<TunerService>();
92     return AServiceManager_addService(service->asBinder().get(), getServiceName());
93 }
94 
hasITuner()95 bool TunerService::hasITuner() {
96     ALOGD("hasITuner");
97     if (mTuner != nullptr) {
98         return true;
99     }
100     mTuner = ITuner::getService();
101     if (mTuner == nullptr) {
102         ALOGE("Failed to get ITuner service");
103         return false;
104     }
105     mTunerVersion = TUNER_HAL_VERSION_1_0;
106     mTuner_1_1 = ::android::hardware::tv::tuner::V1_1::ITuner::castFrom(mTuner);
107     if (mTuner_1_1 != nullptr) {
108         mTunerVersion = TUNER_HAL_VERSION_1_1;
109     } else {
110         ALOGE("Failed to get ITuner_1_1 service");
111     }
112     return true;
113 }
114 
hasITuner_1_1()115 bool TunerService::hasITuner_1_1() {
116     ALOGD("hasITuner_1_1");
117     hasITuner();
118     return (mTunerVersion == TUNER_HAL_VERSION_1_1);
119 }
120 
openDemux(int,std::shared_ptr<ITunerDemux> * _aidl_return)121 Status TunerService::openDemux(
122         int /* demuxHandle */, std::shared_ptr<ITunerDemux>* _aidl_return) {
123     ALOGD("openDemux");
124     if (!hasITuner()) {
125         return Status::fromServiceSpecificError(static_cast<int32_t>(Result::NOT_INITIALIZED));
126     }
127     Result res;
128     uint32_t id;
129     sp<IDemux> demuxSp = nullptr;
130     shared_ptr<ITunerDemux> tunerDemux = nullptr;
131     mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
132         demuxSp = demux;
133         id = demuxId;
134         res = r;
135         ALOGD("open demux, id = %d", demuxId);
136     });
137     if (res == Result::SUCCESS) {
138         tunerDemux = ::ndk::SharedRefBase::make<TunerDemux>(demuxSp, id);
139         *_aidl_return = tunerDemux->ref<ITunerDemux>();
140         return Status::ok();
141     }
142 
143     ALOGW("open demux failed, res = %d", res);
144     return Status::fromServiceSpecificError(static_cast<int32_t>(res));
145 }
146 
getDemuxCaps(TunerDemuxCapabilities * _aidl_return)147 Status TunerService::getDemuxCaps(TunerDemuxCapabilities* _aidl_return) {
148     ALOGD("getDemuxCaps");
149     if (!hasITuner()) {
150         return Status::fromServiceSpecificError(static_cast<int32_t>(Result::NOT_INITIALIZED));
151     }
152     Result res;
153     DemuxCapabilities caps;
154     mTuner->getDemuxCaps([&](Result r, const DemuxCapabilities& demuxCaps) {
155         caps = demuxCaps;
156         res = r;
157     });
158     if (res == Result::SUCCESS) {
159         *_aidl_return = getAidlDemuxCaps(caps);
160         return Status::ok();
161     }
162 
163     ALOGW("Get demux caps failed, res = %d", res);
164     return Status::fromServiceSpecificError(static_cast<int32_t>(res));
165 }
166 
getFrontendIds(vector<int32_t> * ids)167 Status TunerService::getFrontendIds(vector<int32_t>* ids) {
168     if (!hasITuner()) {
169         return Status::fromServiceSpecificError(
170                 static_cast<int32_t>(Result::NOT_INITIALIZED));
171     }
172     hidl_vec<FrontendId> feIds;
173     Result res = getHidlFrontendIds(feIds);
174     if (res != Result::SUCCESS) {
175         return Status::fromServiceSpecificError(static_cast<int32_t>(res));
176     }
177     ids->resize(feIds.size());
178     copy(feIds.begin(), feIds.end(), ids->begin());
179 
180     return Status::ok();
181 }
182 
getFrontendInfo(int32_t id,TunerFrontendInfo * _aidl_return)183 Status TunerService::getFrontendInfo(int32_t id, TunerFrontendInfo* _aidl_return) {
184     if (!hasITuner()) {
185         ALOGE("ITuner service is not init.");
186         return ::ndk::ScopedAStatus::fromServiceSpecificError(
187                 static_cast<int32_t>(Result::UNAVAILABLE));
188     }
189 
190     FrontendInfo info;
191     Result res = getHidlFrontendInfo(id, info);
192     if (res != Result::SUCCESS) {
193         return Status::fromServiceSpecificError(static_cast<int32_t>(res));
194     }
195 
196     TunerFrontendInfo tunerInfo = convertToAidlFrontendInfo(info);
197     *_aidl_return = tunerInfo;
198     return Status::ok();
199 }
200 
getFrontendDtmbCapabilities(int32_t id,TunerFrontendDtmbCapabilities * _aidl_return)201 Status TunerService::getFrontendDtmbCapabilities(
202         int32_t id, TunerFrontendDtmbCapabilities* _aidl_return) {
203     if (!hasITuner_1_1()) {
204         ALOGE("ITuner_1_1 service is not init.");
205         return ::ndk::ScopedAStatus::fromServiceSpecificError(
206                 static_cast<int32_t>(Result::UNAVAILABLE));
207     }
208 
209     Result res;
210     FrontendDtmbCapabilities dtmbCaps;
211     mTuner_1_1->getFrontendDtmbCapabilities(id,
212             [&](Result r, const FrontendDtmbCapabilities& caps) {
213         dtmbCaps = caps;
214         res = r;
215     });
216     if (res != Result::SUCCESS) {
217         return Status::fromServiceSpecificError(static_cast<int32_t>(res));
218     }
219 
220     TunerFrontendDtmbCapabilities aidlDtmbCaps{
221         .transmissionModeCap = (int)dtmbCaps.transmissionModeCap,
222         .bandwidthCap = (int)dtmbCaps.bandwidthCap,
223         .modulationCap = (int)dtmbCaps.modulationCap,
224         .codeRateCap = (int)dtmbCaps.codeRateCap,
225         .guardIntervalCap = (int)dtmbCaps.guardIntervalCap,
226         .interleaveModeCap = (int)dtmbCaps.interleaveModeCap,
227     };
228 
229     *_aidl_return = aidlDtmbCaps;
230     return Status::ok();
231 }
232 
openFrontend(int32_t frontendHandle,shared_ptr<ITunerFrontend> * _aidl_return)233 Status TunerService::openFrontend(
234         int32_t frontendHandle, shared_ptr<ITunerFrontend>* _aidl_return) {
235     if (!hasITuner()) {
236         ALOGE("ITuner service is not init.");
237         return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
238     }
239 
240     Result status;
241     sp<IFrontend> frontend;
242     int id = getResourceIdFromHandle(frontendHandle, FRONTEND);
243     mTuner->openFrontendById(id, [&](Result result, const sp<IFrontend>& fe) {
244         frontend = fe;
245         status = result;
246     });
247     if (status != Result::SUCCESS) {
248         return Status::fromServiceSpecificError(static_cast<int32_t>(status));
249     }
250     *_aidl_return = ::ndk::SharedRefBase::make<TunerFrontend>(frontend, id);
251     return Status::ok();
252 }
253 
openLnb(int lnbHandle,shared_ptr<ITunerLnb> * _aidl_return)254 Status TunerService::openLnb(int lnbHandle, shared_ptr<ITunerLnb>* _aidl_return) {
255     if (!hasITuner()) {
256         ALOGD("get ITuner failed");
257         return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
258     }
259 
260     Result status;
261     sp<ILnb> lnb;
262     int id = getResourceIdFromHandle(lnbHandle, LNB);
263     mTuner->openLnbById(id, [&](Result result, const sp<ILnb>& lnbSp){
264         lnb = lnbSp;
265         status = result;
266     });
267     if (status != Result::SUCCESS) {
268         return Status::fromServiceSpecificError(static_cast<int32_t>(status));
269     }
270 
271     *_aidl_return = ::ndk::SharedRefBase::make<TunerLnb>(lnb, id);
272     return Status::ok();
273 }
274 
openLnbByName(const string & lnbName,shared_ptr<ITunerLnb> * _aidl_return)275 Status TunerService::openLnbByName(const string& lnbName, shared_ptr<ITunerLnb>* _aidl_return) {
276     if (!hasITuner()) {
277         ALOGE("get ITuner failed");
278         return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
279     }
280 
281     int lnbId;
282     Result status;
283     sp<ILnb> lnb;
284     mTuner->openLnbByName(lnbName, [&](Result r, LnbId id, const sp<ILnb>& lnbSp) {
285         status = r;
286         lnb = lnbSp;
287         lnbId = (int)id;
288     });
289     if (status != Result::SUCCESS) {
290         return Status::fromServiceSpecificError(static_cast<int32_t>(status));
291     }
292 
293     *_aidl_return = ::ndk::SharedRefBase::make<TunerLnb>(lnb, lnbId);
294     return Status::ok();
295 }
296 
openDescrambler(int32_t,std::shared_ptr<ITunerDescrambler> * _aidl_return)297 Status TunerService::openDescrambler(int32_t /*descramblerHandle*/,
298             std::shared_ptr<ITunerDescrambler>* _aidl_return) {
299     if (!hasITuner()) {
300         ALOGD("get ITuner failed");
301         return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
302     }
303 
304     Result status;
305     sp<IDescrambler> descrambler;
306     //int id = getResourceIdFromHandle(descramblerHandle, DESCRAMBLER);
307     mTuner->openDescrambler([&](Result r, const sp<IDescrambler>& descramblerSp) {
308         status = r;
309         descrambler = descramblerSp;
310     });
311     if (status != Result::SUCCESS) {
312         return Status::fromServiceSpecificError(static_cast<int32_t>(status));
313     }
314 
315     *_aidl_return = ::ndk::SharedRefBase::make<TunerDescrambler>(descrambler);
316     return Status::ok();
317 }
318 
updateTunerResources()319 void TunerService::updateTunerResources() {
320     if (!hasITuner() || mTunerResourceManager == NULL) {
321         ALOGE("Failed to updateTunerResources");
322         return;
323     }
324 
325     updateFrontendResources();
326     updateLnbResources();
327     // TODO: update Demux, Descrambler.
328 }
329 
getTunerHalVersion(int * _aidl_return)330 Status TunerService::getTunerHalVersion(int* _aidl_return) {
331     hasITuner();
332     *_aidl_return = mTunerVersion;
333     return Status::ok();
334 }
335 
updateFrontendResources()336 void TunerService::updateFrontendResources() {
337     hidl_vec<FrontendId> ids;
338     Result res = getHidlFrontendIds(ids);
339     if (res != Result::SUCCESS) {
340         return;
341     }
342     vector<TunerFrontendInfo> infos;
343     for (int i = 0; i < ids.size(); i++) {
344         FrontendInfo frontendInfo;
345         Result res = getHidlFrontendInfo((int)ids[i], frontendInfo);
346         if (res != Result::SUCCESS) {
347             continue;
348         }
349         TunerFrontendInfo tunerFrontendInfo{
350             .handle = getResourceHandleFromId((int)ids[i], FRONTEND),
351             .type = static_cast<int>(frontendInfo.type),
352             .exclusiveGroupId = static_cast<int>(frontendInfo.exclusiveGroupId),
353         };
354         infos.push_back(tunerFrontendInfo);
355     }
356     mTunerResourceManager->setFrontendInfoList(infos);
357 }
358 
updateLnbResources()359 void TunerService::updateLnbResources() {
360     vector<int> handles = getLnbHandles();
361     if (handles.size() == 0) {
362         return;
363     }
364     mTunerResourceManager->setLnbInfoList(handles);
365 }
366 
getLnbHandles()367 vector<int> TunerService::getLnbHandles() {
368     vector<int> lnbHandles;
369     if (mTuner != NULL) {
370         Result res;
371         vector<LnbId> lnbIds;
372         mTuner->getLnbIds([&](Result r, const hardware::hidl_vec<LnbId>& ids) {
373             lnbIds = ids;
374             res = r;
375         });
376         if (res != Result::SUCCESS || lnbIds.size() == 0) {
377         } else {
378             for (int i = 0; i < lnbIds.size(); i++) {
379                 lnbHandles.push_back(getResourceHandleFromId((int)lnbIds[i], LNB));
380             }
381         }
382     }
383 
384     return lnbHandles;
385 }
386 
getHidlFrontendIds(hidl_vec<FrontendId> & ids)387 Result TunerService::getHidlFrontendIds(hidl_vec<FrontendId>& ids) {
388     if (mTuner == NULL) {
389         return Result::NOT_INITIALIZED;
390     }
391     Result res;
392     mTuner->getFrontendIds([&](Result r, const hidl_vec<FrontendId>& frontendIds) {
393         ids = frontendIds;
394         res = r;
395     });
396     return res;
397 }
398 
getHidlFrontendInfo(int id,FrontendInfo & info)399 Result TunerService::getHidlFrontendInfo(int id, FrontendInfo& info) {
400     if (mTuner == NULL) {
401         return Result::NOT_INITIALIZED;
402     }
403     Result res;
404     mTuner->getFrontendInfo(id, [&](Result r, const FrontendInfo& feInfo) {
405         info = feInfo;
406         res = r;
407     });
408     return res;
409 }
410 
getAidlDemuxCaps(DemuxCapabilities caps)411 TunerDemuxCapabilities TunerService::getAidlDemuxCaps(DemuxCapabilities caps) {
412     TunerDemuxCapabilities aidlCaps{
413         .numDemux = (int)caps.numDemux,
414         .numRecord = (int)caps.numRecord,
415         .numPlayback = (int)caps.numPlayback,
416         .numTsFilter = (int)caps.numTsFilter,
417         .numSectionFilter = (int)caps.numSectionFilter,
418         .numAudioFilter = (int)caps.numAudioFilter,
419         .numVideoFilter = (int)caps.numVideoFilter,
420         .numPesFilter = (int)caps.numPesFilter,
421         .numPcrFilter = (int)caps.numPcrFilter,
422         .numBytesInSectionFilter = (int)caps.numBytesInSectionFilter,
423         .filterCaps = (int)caps.filterCaps,
424         .bTimeFilter = caps.bTimeFilter,
425     };
426     aidlCaps.linkCaps.resize(caps.linkCaps.size());
427     copy(caps.linkCaps.begin(), caps.linkCaps.end(), aidlCaps.linkCaps.begin());
428     return aidlCaps;
429 }
430 
convertToAidlFrontendInfo(FrontendInfo halInfo)431 TunerFrontendInfo TunerService::convertToAidlFrontendInfo(FrontendInfo halInfo) {
432     TunerFrontendInfo info{
433         .type = (int)halInfo.type,
434         .minFrequency = (int)halInfo.minFrequency,
435         .maxFrequency = (int)halInfo.maxFrequency,
436         .minSymbolRate = (int)halInfo.minSymbolRate,
437         .maxSymbolRate = (int)halInfo.maxSymbolRate,
438         .acquireRange = (int)halInfo.acquireRange,
439         .exclusiveGroupId = (int)halInfo.exclusiveGroupId,
440     };
441     for (int i = 0; i < halInfo.statusCaps.size(); i++) {
442         info.statusCaps.push_back((int)halInfo.statusCaps[i]);
443     }
444 
445     TunerFrontendCapabilities caps;
446     switch (halInfo.type) {
447         case FrontendType::ANALOG: {
448             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::analogCaps
449                     == halInfo.frontendCaps.getDiscriminator()) {
450                 TunerFrontendAnalogCapabilities analogCaps{
451                     .typeCap = (int)halInfo.frontendCaps.analogCaps().typeCap,
452                     .sifStandardCap = (int)halInfo.frontendCaps.analogCaps().sifStandardCap,
453                 };
454                 caps.set<TunerFrontendCapabilities::analogCaps>(analogCaps);
455             }
456             break;
457         }
458         case FrontendType::ATSC: {
459             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atscCaps
460                     == halInfo.frontendCaps.getDiscriminator()) {
461                 TunerFrontendAtscCapabilities atscCaps{
462                     .modulationCap = (int)halInfo.frontendCaps.atscCaps().modulationCap,
463                 };
464                 caps.set<TunerFrontendCapabilities::atscCaps>(atscCaps);
465             }
466             break;
467         }
468         case FrontendType::ATSC3: {
469             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atsc3Caps
470                     == halInfo.frontendCaps.getDiscriminator()) {
471                 TunerFrontendAtsc3Capabilities atsc3Caps{
472                     .bandwidthCap = (int)halInfo.frontendCaps.atsc3Caps().bandwidthCap,
473                     .modulationCap = (int)halInfo.frontendCaps.atsc3Caps().modulationCap,
474                     .timeInterleaveModeCap =
475                             (int)halInfo.frontendCaps.atsc3Caps().timeInterleaveModeCap,
476                     .codeRateCap = (int)halInfo.frontendCaps.atsc3Caps().codeRateCap,
477                     .demodOutputFormatCap
478                         = (int)halInfo.frontendCaps.atsc3Caps().demodOutputFormatCap,
479                     .fecCap = (int)halInfo.frontendCaps.atsc3Caps().fecCap,
480                 };
481                 caps.set<TunerFrontendCapabilities::atsc3Caps>(atsc3Caps);
482             }
483             break;
484         }
485         case FrontendType::DVBC: {
486             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbcCaps
487                     == halInfo.frontendCaps.getDiscriminator()) {
488                 TunerFrontendCableCapabilities cableCaps{
489                     .modulationCap = (int)halInfo.frontendCaps.dvbcCaps().modulationCap,
490                     .codeRateCap = (int64_t)halInfo.frontendCaps.dvbcCaps().fecCap,
491                     .annexCap = (int)halInfo.frontendCaps.dvbcCaps().annexCap,
492                 };
493                 caps.set<TunerFrontendCapabilities::cableCaps>(cableCaps);
494             }
495             break;
496         }
497         case FrontendType::DVBS: {
498             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbsCaps
499                     == halInfo.frontendCaps.getDiscriminator()) {
500                 TunerFrontendDvbsCapabilities dvbsCaps{
501                     .modulationCap = (int)halInfo.frontendCaps.dvbsCaps().modulationCap,
502                     .codeRateCap = (long)halInfo.frontendCaps.dvbsCaps().innerfecCap,
503                     .standard = (int)halInfo.frontendCaps.dvbsCaps().standard,
504                 };
505                 caps.set<TunerFrontendCapabilities::dvbsCaps>(dvbsCaps);
506             }
507             break;
508         }
509         case FrontendType::DVBT: {
510             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbtCaps
511                     == halInfo.frontendCaps.getDiscriminator()) {
512                 TunerFrontendDvbtCapabilities dvbtCaps{
513                     .transmissionModeCap = (int)halInfo.frontendCaps.dvbtCaps().transmissionModeCap,
514                     .bandwidthCap = (int)halInfo.frontendCaps.dvbtCaps().bandwidthCap,
515                     .constellationCap = (int)halInfo.frontendCaps.dvbtCaps().constellationCap,
516                     .codeRateCap = (int)halInfo.frontendCaps.dvbtCaps().coderateCap,
517                     .hierarchyCap = (int)halInfo.frontendCaps.dvbtCaps().hierarchyCap,
518                     .guardIntervalCap = (int)halInfo.frontendCaps.dvbtCaps().guardIntervalCap,
519                     .isT2Supported = (bool)halInfo.frontendCaps.dvbtCaps().isT2Supported,
520                     .isMisoSupported = (bool)halInfo.frontendCaps.dvbtCaps().isMisoSupported,
521                 };
522                 caps.set<TunerFrontendCapabilities::dvbtCaps>(dvbtCaps);
523             }
524             break;
525         }
526         case FrontendType::ISDBS: {
527             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbsCaps
528                     == halInfo.frontendCaps.getDiscriminator()) {
529                 TunerFrontendIsdbsCapabilities isdbsCaps{
530                     .modulationCap = (int)halInfo.frontendCaps.isdbsCaps().modulationCap,
531                     .codeRateCap = (int)halInfo.frontendCaps.isdbsCaps().coderateCap,
532                 };
533                 caps.set<TunerFrontendCapabilities::isdbsCaps>(isdbsCaps);
534             }
535             break;
536         }
537         case FrontendType::ISDBS3: {
538             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbs3Caps
539                     == halInfo.frontendCaps.getDiscriminator()) {
540                 TunerFrontendIsdbs3Capabilities isdbs3Caps{
541                     .modulationCap = (int)halInfo.frontendCaps.isdbs3Caps().modulationCap,
542                     .codeRateCap = (int)halInfo.frontendCaps.isdbs3Caps().coderateCap,
543                 };
544                 caps.set<TunerFrontendCapabilities::isdbs3Caps>(isdbs3Caps);
545             }
546             break;
547         }
548         case FrontendType::ISDBT: {
549             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbtCaps
550                     == halInfo.frontendCaps.getDiscriminator()) {
551                 TunerFrontendIsdbtCapabilities isdbtCaps{
552                     .modeCap = (int)halInfo.frontendCaps.isdbtCaps().modeCap,
553                     .bandwidthCap = (int)halInfo.frontendCaps.isdbtCaps().bandwidthCap,
554                     .modulationCap = (int)halInfo.frontendCaps.isdbtCaps().modulationCap,
555                     .codeRateCap = (int)halInfo.frontendCaps.isdbtCaps().coderateCap,
556                     .guardIntervalCap = (int)halInfo.frontendCaps.isdbtCaps().guardIntervalCap,
557                 };
558                 caps.set<TunerFrontendCapabilities::isdbtCaps>(isdbtCaps);
559             }
560             break;
561         }
562         default:
563             break;
564     }
565 
566     info.caps = caps;
567     return info;
568 }
569 } // namespace android
570