xref: /aosp_15_r20/frameworks/av/services/tuner/hidl/TunerHidlService.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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(int64_t,shared_ptr<ITunerDemux> * _aidl_return)104 ::ndk::ScopedAStatus TunerHidlService::openDemux(int64_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(int64_t,DemuxInfo *)126 ::ndk::ScopedAStatus TunerHidlService::getDemuxInfo(int64_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(int64_t frontendHandle,shared_ptr<ITunerFrontend> * _aidl_return)198 ::ndk::ScopedAStatus TunerHidlService::openFrontend(int64_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(int64_t lnbHandle,shared_ptr<ITunerLnb> * _aidl_return)224 ::ndk::ScopedAStatus TunerHidlService::openLnb(int64_t lnbHandle,
225                                                shared_ptr<ITunerLnb>* _aidl_return) {
226     HidlResult status;
227     sp<HidlILnb> lnb;
228     int id = TunerHelper::getResourceIdFromHandle(lnbHandle, LNB);
229     mTuner->openLnbById(id, [&](HidlResult result, const sp<HidlILnb>& lnbSp) {
230         lnb = lnbSp;
231         status = result;
232     });
233     if (status != HidlResult::SUCCESS) {
234         return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
235     }
236 
237     *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlLnb>(lnb, id);
238     return ::ndk::ScopedAStatus::ok();
239 }
240 
openLnbByName(const string & lnbName,shared_ptr<ITunerLnb> * _aidl_return)241 ::ndk::ScopedAStatus TunerHidlService::openLnbByName(const string& lnbName,
242                                                      shared_ptr<ITunerLnb>* _aidl_return) {
243     int lnbId;
244     HidlResult status;
245     sp<HidlILnb> lnb;
246     mTuner->openLnbByName(lnbName, [&](HidlResult r, HidlLnbId id, const sp<HidlILnb>& lnbSp) {
247         status = r;
248         lnb = lnbSp;
249         lnbId = static_cast<int32_t>(id);
250     });
251     if (status != HidlResult::SUCCESS) {
252         return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
253     }
254 
255     *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlLnb>(lnb, lnbId);
256     return ::ndk::ScopedAStatus::ok();
257 }
258 
openDescrambler(int64_t,shared_ptr<ITunerDescrambler> * _aidl_return)259 ::ndk::ScopedAStatus TunerHidlService::openDescrambler(
260         int64_t /*descramblerHandle*/, shared_ptr<ITunerDescrambler>* _aidl_return) {
261     HidlResult status;
262     sp<HidlIDescrambler> descrambler;
263     //int id = TunerHelper::getResourceIdFromHandle(descramblerHandle, DESCRAMBLER);
264     mTuner->openDescrambler([&](HidlResult r, const sp<HidlIDescrambler>& descramblerSp) {
265         status = r;
266         descrambler = descramblerSp;
267     });
268     if (status != HidlResult::SUCCESS) {
269         return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
270     }
271 
272     *_aidl_return = ::ndk::SharedRefBase::make<TunerHidlDescrambler>(descrambler);
273     return ::ndk::ScopedAStatus::ok();
274 }
275 
getTunerHalVersion(int * _aidl_return)276 ::ndk::ScopedAStatus TunerHidlService::getTunerHalVersion(int* _aidl_return) {
277     *_aidl_return = mTunerVersion;
278     return ::ndk::ScopedAStatus::ok();
279 }
280 
openSharedFilter(const string & in_filterToken,const shared_ptr<ITunerFilterCallback> & in_cb,shared_ptr<ITunerFilter> * _aidl_return)281 ::ndk::ScopedAStatus TunerHidlService::openSharedFilter(
282         const string& in_filterToken, const shared_ptr<ITunerFilterCallback>& in_cb,
283         shared_ptr<ITunerFilter>* _aidl_return) {
284     if (mTuner == nullptr) {
285         ALOGE("get ITuner failed");
286         return ::ndk::ScopedAStatus::fromServiceSpecificError(
287                 static_cast<int32_t>(Result::UNAVAILABLE));
288     }
289 
290     if (!PermissionCache::checkCallingPermission(sSharedFilterPermission)) {
291         ALOGE("Request requires android.permission.ACCESS_TV_SHARED_FILTER");
292         return ::ndk::ScopedAStatus::fromServiceSpecificError(
293                 static_cast<int32_t>(Result::UNAVAILABLE));
294     }
295 
296     Mutex::Autolock _l(mSharedFiltersLock);
297     if (mSharedFilters.find(in_filterToken) == mSharedFilters.end()) {
298         *_aidl_return = nullptr;
299         ALOGD("fail to find %s", in_filterToken.c_str());
300         return ::ndk::ScopedAStatus::fromServiceSpecificError(
301                 static_cast<int32_t>(Result::INVALID_STATE));
302     }
303 
304     shared_ptr<TunerHidlFilter> filter = mSharedFilters.at(in_filterToken);
305     IPCThreadState* ipc = IPCThreadState::self();
306     const int pid = ipc->getCallingPid();
307     if (!filter->isSharedFilterAllowed(pid)) {
308         *_aidl_return = nullptr;
309         ALOGD("shared filter %s is opened in the same process", in_filterToken.c_str());
310         return ::ndk::ScopedAStatus::fromServiceSpecificError(
311                 static_cast<int32_t>(Result::INVALID_STATE));
312     }
313 
314     filter->attachSharedFilterCallback(in_cb);
315 
316     *_aidl_return = filter;
317     return ::ndk::ScopedAStatus::ok();
318 }
319 
isLnaSupported(bool *)320 ::ndk::ScopedAStatus TunerHidlService::isLnaSupported(bool* /* _aidl_return */) {
321     return ::ndk::ScopedAStatus::fromServiceSpecificError(
322             static_cast<int32_t>(Result::UNAVAILABLE));
323 }
324 
setLna(bool bEnable)325 ::ndk::ScopedAStatus TunerHidlService::setLna(bool bEnable) {
326     if (mTuner == nullptr) {
327         ALOGE("get ITuner failed");
328         return ::ndk::ScopedAStatus::fromServiceSpecificError(
329                 static_cast<int32_t>(Result::UNAVAILABLE));
330     }
331 
332     mLnaStatus = bEnable ? 1 : 0;
333 
334     {
335         Mutex::Autolock _l(mOpenedFrontendsLock);
336         for (auto it = mOpenedFrontends.begin(); it != mOpenedFrontends.end(); ++it) {
337             (*it)->setLna(mLnaStatus == 1);
338         }
339     }
340 
341     return ::ndk::ScopedAStatus::ok();
342 }
343 
setMaxNumberOfFrontends(FrontendType,int32_t)344 ::ndk::ScopedAStatus TunerHidlService::setMaxNumberOfFrontends(FrontendType /* in_frontendType */,
345                                                                int32_t /* in_maxNumber */) {
346     return ::ndk::ScopedAStatus::fromServiceSpecificError(
347             static_cast<int32_t>(Result::UNAVAILABLE));
348 }
349 
getMaxNumberOfFrontends(FrontendType,int32_t * _aidl_return)350 ::ndk::ScopedAStatus TunerHidlService::getMaxNumberOfFrontends(FrontendType /* in_frontendType */,
351                                                                int32_t* _aidl_return) {
352     *_aidl_return = -1;
353     return ::ndk::ScopedAStatus::fromServiceSpecificError(
354             static_cast<int32_t>(Result::UNAVAILABLE));
355 }
356 
addFilterToShared(const shared_ptr<TunerHidlFilter> & sharedFilter)357 string TunerHidlService::addFilterToShared(const shared_ptr<TunerHidlFilter>& sharedFilter) {
358     Mutex::Autolock _l(mSharedFiltersLock);
359 
360     // Use sharedFilter address as token.
361     string token = to_string(reinterpret_cast<std::uintptr_t>(sharedFilter.get()));
362     mSharedFilters[token] = sharedFilter;
363 
364     return token;
365 }
366 
removeSharedFilter(const shared_ptr<TunerHidlFilter> & sharedFilter)367 void TunerHidlService::removeSharedFilter(const shared_ptr<TunerHidlFilter>& sharedFilter) {
368     Mutex::Autolock _l(mSharedFiltersLock);
369 
370     // Use sharedFilter address as token.
371     mSharedFilters.erase(to_string(reinterpret_cast<std::uintptr_t>(sharedFilter.get())));
372 }
373 
removeFrontend(const shared_ptr<TunerHidlFrontend> & frontend)374 void TunerHidlService::removeFrontend(const shared_ptr<TunerHidlFrontend>& frontend) {
375     Mutex::Autolock _l(mOpenedFrontendsLock);
376     for (auto it = mOpenedFrontends.begin(); it != mOpenedFrontends.end(); ++it) {
377         if (it->get() == frontend.get()) {
378             mOpenedFrontends.erase(it);
379             break;
380         }
381     }
382 }
383 
updateTunerResources()384 void TunerHidlService::updateTunerResources() {
385     TunerHelper::updateTunerResources(getTRMFrontendInfos(), getTRMLnbHandles());
386 }
387 
getTRMFrontendInfos()388 vector<TunerFrontendInfo> TunerHidlService::getTRMFrontendInfos() {
389     vector<TunerFrontendInfo> infos;
390     hidl_vec<HidlFrontendId> ids;
391     HidlResult res = getHidlFrontendIds(ids);
392     if (res != HidlResult::SUCCESS) {
393         return infos;
394     }
395 
396     for (int i = 0; i < ids.size(); i++) {
397         HidlFrontendInfo frontendInfo;
398         HidlResult res = getHidlFrontendInfo(static_cast<int32_t>(ids[i]), frontendInfo);
399         if (res != HidlResult::SUCCESS) {
400             continue;
401         }
402         TunerFrontendInfo tunerFrontendInfo{
403                 .handle = TunerHelper::getResourceHandleFromId(static_cast<int32_t>(ids[i]),
404                                                                FRONTEND),
405                 .type = static_cast<int32_t>(frontendInfo.type),
406                 .exclusiveGroupId = static_cast<int32_t>(frontendInfo.exclusiveGroupId),
407         };
408         infos.push_back(tunerFrontendInfo);
409     }
410 
411     return infos;
412 }
413 
getTRMLnbHandles()414 vector<int64_t> TunerHidlService::getTRMLnbHandles() {
415     vector<int64_t> lnbHandles;
416     if (mTuner != nullptr) {
417         HidlResult res;
418         vector<HidlLnbId> lnbIds;
419         mTuner->getLnbIds([&](HidlResult r, const hidl_vec<HidlLnbId>& ids) {
420             lnbIds = ids;
421             res = r;
422         });
423         if (res == HidlResult::SUCCESS && lnbIds.size() > 0) {
424             for (int i = 0; i < lnbIds.size(); i++) {
425                 lnbHandles.push_back(
426                         TunerHelper::getResourceHandleFromId(static_cast<int32_t>(lnbIds[i]), LNB));
427             }
428         }
429     }
430 
431     return lnbHandles;
432 }
433 
getHidlFrontendIds(hidl_vec<HidlFrontendId> & ids)434 HidlResult TunerHidlService::getHidlFrontendIds(hidl_vec<HidlFrontendId>& ids) {
435     if (mTuner == nullptr) {
436         return HidlResult::NOT_INITIALIZED;
437     }
438     HidlResult res;
439     mTuner->getFrontendIds([&](HidlResult r, const hidl_vec<HidlFrontendId>& frontendIds) {
440         ids = frontendIds;
441         res = r;
442     });
443     return res;
444 }
445 
getHidlFrontendInfo(const int id,HidlFrontendInfo & info)446 HidlResult TunerHidlService::getHidlFrontendInfo(const int id, HidlFrontendInfo& info) {
447     if (mTuner == nullptr) {
448         return HidlResult::NOT_INITIALIZED;
449     }
450     HidlResult res;
451     mTuner->getFrontendInfo(id, [&](HidlResult r, const HidlFrontendInfo& feInfo) {
452         info = feInfo;
453         res = r;
454     });
455     return res;
456 }
457 
getAidlDemuxCaps(const HidlDemuxCapabilities & caps)458 DemuxCapabilities TunerHidlService::getAidlDemuxCaps(const HidlDemuxCapabilities& caps) {
459     DemuxCapabilities aidlCaps{
460             .numDemux = static_cast<int32_t>(caps.numDemux),
461             .numRecord = static_cast<int32_t>(caps.numRecord),
462             .numPlayback = static_cast<int32_t>(caps.numPlayback),
463             .numTsFilter = static_cast<int32_t>(caps.numTsFilter),
464             .numSectionFilter = static_cast<int32_t>(caps.numSectionFilter),
465             .numAudioFilter = static_cast<int32_t>(caps.numAudioFilter),
466             .numVideoFilter = static_cast<int32_t>(caps.numVideoFilter),
467             .numPesFilter = static_cast<int32_t>(caps.numPesFilter),
468             .numPcrFilter = static_cast<int32_t>(caps.numPcrFilter),
469             .numBytesInSectionFilter = static_cast<int64_t>(caps.numBytesInSectionFilter),
470             .filterCaps = static_cast<int32_t>(caps.filterCaps),
471             .bTimeFilter = caps.bTimeFilter,
472     };
473     aidlCaps.linkCaps.resize(caps.linkCaps.size());
474     copy(caps.linkCaps.begin(), caps.linkCaps.end(), aidlCaps.linkCaps.begin());
475     return aidlCaps;
476 }
477 
getAidlFrontendInfo(const HidlFrontendInfo & halInfo,const HidlFrontendDtmbCapabilities & halDtmbCaps)478 FrontendInfo TunerHidlService::getAidlFrontendInfo(
479         const HidlFrontendInfo& halInfo, const HidlFrontendDtmbCapabilities& halDtmbCaps) {
480     FrontendInfo info{
481             .type = static_cast<FrontendType>(halInfo.type),
482             .minFrequency = static_cast<int64_t>(halInfo.minFrequency),
483             .maxFrequency = static_cast<int64_t>(halInfo.maxFrequency),
484             .minSymbolRate = static_cast<int32_t>(halInfo.minSymbolRate),
485             .maxSymbolRate = static_cast<int32_t>(halInfo.maxSymbolRate),
486             .acquireRange = static_cast<int64_t>(halInfo.acquireRange),
487             .exclusiveGroupId = static_cast<int32_t>(halInfo.exclusiveGroupId),
488     };
489     for (int i = 0; i < halInfo.statusCaps.size(); i++) {
490         info.statusCaps.push_back(static_cast<FrontendStatusType>(halInfo.statusCaps[i]));
491     }
492 
493     FrontendCapabilities caps;
494     switch (halInfo.type) {
495     case ::android::hardware::tv::tuner::V1_0::FrontendType::ANALOG: {
496         if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::analogCaps ==
497             halInfo.frontendCaps.getDiscriminator()) {
498             FrontendAnalogCapabilities analogCaps{
499                     .typeCap = static_cast<int32_t>(halInfo.frontendCaps.analogCaps().typeCap),
500                     .sifStandardCap =
501                             static_cast<int32_t>(halInfo.frontendCaps.analogCaps().sifStandardCap),
502             };
503             caps.set<FrontendCapabilities::analogCaps>(analogCaps);
504         }
505         break;
506     }
507     case ::android::hardware::tv::tuner::V1_0::FrontendType::ATSC: {
508         if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::atscCaps ==
509             halInfo.frontendCaps.getDiscriminator()) {
510             FrontendAtscCapabilities atscCaps{
511                     .modulationCap =
512                             static_cast<int32_t>(halInfo.frontendCaps.atscCaps().modulationCap),
513             };
514             caps.set<FrontendCapabilities::atscCaps>(atscCaps);
515         }
516         break;
517     }
518     case ::android::hardware::tv::tuner::V1_0::FrontendType::ATSC3: {
519         if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::atsc3Caps ==
520             halInfo.frontendCaps.getDiscriminator()) {
521             FrontendAtsc3Capabilities atsc3Caps{
522                     .bandwidthCap =
523                             static_cast<int32_t>(halInfo.frontendCaps.atsc3Caps().bandwidthCap),
524                     .modulationCap =
525                             static_cast<int32_t>(halInfo.frontendCaps.atsc3Caps().modulationCap),
526                     .timeInterleaveModeCap = static_cast<int32_t>(
527                             halInfo.frontendCaps.atsc3Caps().timeInterleaveModeCap),
528                     .codeRateCap =
529                             static_cast<int32_t>(halInfo.frontendCaps.atsc3Caps().codeRateCap),
530                     .demodOutputFormatCap = static_cast<int8_t>(
531                             halInfo.frontendCaps.atsc3Caps().demodOutputFormatCap),
532                     .fecCap = static_cast<int32_t>(halInfo.frontendCaps.atsc3Caps().fecCap),
533             };
534             caps.set<FrontendCapabilities::atsc3Caps>(atsc3Caps);
535         }
536         break;
537     }
538     case ::android::hardware::tv::tuner::V1_0::FrontendType::DVBC: {
539         if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::dvbcCaps ==
540             halInfo.frontendCaps.getDiscriminator()) {
541             FrontendDvbcCapabilities dvbcCaps{
542                     .modulationCap =
543                             static_cast<int32_t>(halInfo.frontendCaps.dvbcCaps().modulationCap),
544                     .fecCap = static_cast<int64_t>(halInfo.frontendCaps.dvbcCaps().fecCap),
545                     .annexCap = static_cast<int8_t>(halInfo.frontendCaps.dvbcCaps().annexCap),
546             };
547             caps.set<FrontendCapabilities::dvbcCaps>(dvbcCaps);
548         }
549         break;
550     }
551     case ::android::hardware::tv::tuner::V1_0::FrontendType::DVBS: {
552         if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::dvbsCaps ==
553             halInfo.frontendCaps.getDiscriminator()) {
554             FrontendDvbsCapabilities dvbsCaps{
555                     .modulationCap =
556                             static_cast<int32_t>(halInfo.frontendCaps.dvbsCaps().modulationCap),
557                     .innerfecCap =
558                             static_cast<int64_t>(halInfo.frontendCaps.dvbsCaps().innerfecCap),
559                     .standard = static_cast<int8_t>(halInfo.frontendCaps.dvbsCaps().standard),
560             };
561             caps.set<FrontendCapabilities::dvbsCaps>(dvbsCaps);
562         }
563         break;
564     }
565     case ::android::hardware::tv::tuner::V1_0::FrontendType::DVBT: {
566         if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::dvbtCaps ==
567             halInfo.frontendCaps.getDiscriminator()) {
568             FrontendDvbtCapabilities dvbtCaps{
569                     .transmissionModeCap = static_cast<int32_t>(
570                             halInfo.frontendCaps.dvbtCaps().transmissionModeCap),
571                     .bandwidthCap =
572                             static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().bandwidthCap),
573                     .constellationCap =
574                             static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().constellationCap),
575                     .coderateCap =
576                             static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().coderateCap),
577                     .hierarchyCap =
578                             static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().hierarchyCap),
579                     .guardIntervalCap =
580                             static_cast<int32_t>(halInfo.frontendCaps.dvbtCaps().guardIntervalCap),
581                     .isT2Supported = halInfo.frontendCaps.dvbtCaps().isT2Supported,
582                     .isMisoSupported = halInfo.frontendCaps.dvbtCaps().isMisoSupported,
583             };
584             caps.set<FrontendCapabilities::dvbtCaps>(dvbtCaps);
585         }
586         break;
587     }
588     case ::android::hardware::tv::tuner::V1_0::FrontendType::ISDBS: {
589         if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::isdbsCaps ==
590             halInfo.frontendCaps.getDiscriminator()) {
591             FrontendIsdbsCapabilities isdbsCaps{
592                     .modulationCap =
593                             static_cast<int32_t>(halInfo.frontendCaps.isdbsCaps().modulationCap),
594                     .coderateCap =
595                             static_cast<int32_t>(halInfo.frontendCaps.isdbsCaps().coderateCap),
596             };
597             caps.set<FrontendCapabilities::isdbsCaps>(isdbsCaps);
598         }
599         break;
600     }
601     case ::android::hardware::tv::tuner::V1_0::FrontendType::ISDBS3: {
602         if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::isdbs3Caps ==
603             halInfo.frontendCaps.getDiscriminator()) {
604             FrontendIsdbs3Capabilities isdbs3Caps{
605                     .modulationCap =
606                             static_cast<int32_t>(halInfo.frontendCaps.isdbs3Caps().modulationCap),
607                     .coderateCap =
608                             static_cast<int32_t>(halInfo.frontendCaps.isdbs3Caps().coderateCap),
609             };
610             caps.set<FrontendCapabilities::isdbs3Caps>(isdbs3Caps);
611         }
612         break;
613     }
614     case ::android::hardware::tv::tuner::V1_0::FrontendType::ISDBT: {
615         if (HidlFrontendInfo::FrontendCapabilities::hidl_discriminator::isdbtCaps ==
616             halInfo.frontendCaps.getDiscriminator()) {
617             FrontendIsdbtCapabilities isdbtCaps{
618                     .modeCap = static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().modeCap),
619                     .bandwidthCap =
620                             static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().bandwidthCap),
621                     .modulationCap =
622                             static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().modulationCap),
623                     .coderateCap =
624                             static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().coderateCap),
625                     .guardIntervalCap =
626                             static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().guardIntervalCap),
627                     .timeInterleaveCap =
628                             static_cast<int32_t>(FrontendIsdbtTimeInterleaveMode::UNDEFINED),
629                     .isSegmentAuto = false,
630                     .isFullSegment = false,
631             };
632             caps.set<FrontendCapabilities::isdbtCaps>(isdbtCaps);
633         }
634         break;
635     }
636     default: {
637         if (static_cast<HidlFrontendType>(info.type) == HidlFrontendType::DTMB) {
638             FrontendDtmbCapabilities dtmbCaps{
639                     .transmissionModeCap = static_cast<int32_t>(halDtmbCaps.transmissionModeCap),
640                     .bandwidthCap = static_cast<int32_t>(halDtmbCaps.bandwidthCap),
641                     .modulationCap = static_cast<int32_t>(halDtmbCaps.modulationCap),
642                     .codeRateCap = static_cast<int32_t>(halDtmbCaps.codeRateCap),
643                     .guardIntervalCap = static_cast<int32_t>(halDtmbCaps.guardIntervalCap),
644                     .interleaveModeCap = static_cast<int32_t>(halDtmbCaps.interleaveModeCap),
645             };
646             caps.set<FrontendCapabilities::dtmbCaps>(dtmbCaps);
647         }
648         break;
649     }
650     }
651 
652     info.frontendCaps = caps;
653     return info;
654 }
655 
656 }  // namespace tuner
657 }  // namespace tv
658 }  // namespace media
659 }  // namespace android
660 }  // namespace aidl
661