blob: da9f541511e5974b1b955556c39367f7b009026f [file] [log] [blame]
shubang23aa3ac2020-09-07 18:56:28 -07001/**
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>
Devin Moore95bd53d2021-01-21 14:03:40 -080020#include <fmq/ConvertMQDescriptors.h>
shubang23aa3ac2020-09-07 18:56:28 -070021#include <utils/Log.h>
22#include "TunerService.h"
Amy Zhanga046eee2021-01-12 14:44:58 -080023#include "TunerFrontend.h"
24#include "TunerLnb.h"
shubangae56a2e2021-01-21 07:29:55 -080025#include "TunerDemux.h"
shubang23aa3ac2020-09-07 18:56:28 -070026
Amy Zhang70de35a2020-10-12 20:13:16 -070027using ::aidl::android::media::tv::tuner::TunerFrontendAnalogCapabilities;
28using ::aidl::android::media::tv::tuner::TunerFrontendAtsc3Capabilities;
29using ::aidl::android::media::tv::tuner::TunerFrontendAtscCapabilities;
30using ::aidl::android::media::tv::tuner::TunerFrontendCableCapabilities;
31using ::aidl::android::media::tv::tuner::TunerFrontendCapabilities;
32using ::aidl::android::media::tv::tuner::TunerFrontendDvbsCapabilities;
33using ::aidl::android::media::tv::tuner::TunerFrontendDvbtCapabilities;
34using ::aidl::android::media::tv::tuner::TunerFrontendIsdbs3Capabilities;
35using ::aidl::android::media::tv::tuner::TunerFrontendIsdbsCapabilities;
36using ::aidl::android::media::tv::tuner::TunerFrontendIsdbtCapabilities;
shubang6d266262020-10-09 00:15:04 -070037using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
38using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
39using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
40using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
41using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
shubang23aa3ac2020-09-07 18:56:28 -070042using ::android::hardware::tv::tuner::V1_0::FrontendId;
Amy Zhang70de35a2020-10-12 20:13:16 -070043using ::android::hardware::tv::tuner::V1_0::FrontendType;
Amy Zhanga046eee2021-01-12 14:44:58 -080044using ::android::hardware::tv::tuner::V1_0::IFrontend;
45using ::android::hardware::tv::tuner::V1_0::ILnb;
46using ::android::hardware::tv::tuner::V1_0::LnbId;
shubang23aa3ac2020-09-07 18:56:28 -070047using ::android::hardware::tv::tuner::V1_0::Result;
48
49namespace android {
50
shubang23aa3ac2020-09-07 18:56:28 -070051TunerService::TunerService() {}
52TunerService::~TunerService() {}
53
54void TunerService::instantiate() {
Amy Zhanga046eee2021-01-12 14:44:58 -080055 shared_ptr<TunerService> service =
shubang23aa3ac2020-09-07 18:56:28 -070056 ::ndk::SharedRefBase::make<TunerService>();
57 AServiceManager_addService(service->asBinder().get(), getServiceName());
shubang6d266262020-10-09 00:15:04 -070058}
59
shubang6d266262020-10-09 00:15:04 -070060bool TunerService::getITuner() {
61 ALOGD("getITuner");
62 if (mTuner != nullptr) {
63 return true;
64 }
Amy Zhang0f04c452020-10-30 13:36:44 -070065 mTuner = ITuner::getService();
66 if (mTuner == nullptr) {
shubang6d266262020-10-09 00:15:04 -070067 ALOGE("Failed to get ITuner service");
68 return false;
Amy Zhang0f04c452020-10-30 13:36:44 -070069 }
shubang6d266262020-10-09 00:15:04 -070070 return true;
71}
72
shubangae56a2e2021-01-21 07:29:55 -080073Status TunerService::openDemux(
74 int /* demuxHandle */, std::shared_ptr<ITunerDemux>* _aidl_return) {
shubang6d266262020-10-09 00:15:04 -070075 ALOGD("openDemux");
76 if (!getITuner()) {
shubangae56a2e2021-01-21 07:29:55 -080077 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::NOT_INITIALIZED));
shubang6d266262020-10-09 00:15:04 -070078 }
shubang6d266262020-10-09 00:15:04 -070079 Result res;
80 uint32_t id;
shubangae56a2e2021-01-21 07:29:55 -080081 sp<IDemux> demuxSp = nullptr;
Amy Zhangce2cb402021-01-21 12:50:47 -080082 shared_ptr<ITunerDemux> tunerDemux = nullptr;
shubang6d266262020-10-09 00:15:04 -070083 mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
84 demuxSp = demux;
85 id = demuxId;
86 res = r;
87 ALOGD("open demux, id = %d", demuxId);
88 });
89 if (res == Result::SUCCESS) {
Amy Zhangce2cb402021-01-21 12:50:47 -080090 tunerDemux = ::ndk::SharedRefBase::make<TunerDemux>(demuxSp, id);
91 *_aidl_return = tunerDemux->ref<ITunerDemux>();
shubangae56a2e2021-01-21 07:29:55 -080092 return Status::ok();
shubang6d266262020-10-09 00:15:04 -070093 }
94
shubangae56a2e2021-01-21 07:29:55 -080095 ALOGD("open demux failed, res = %d", res);
shubangae56a2e2021-01-21 07:29:55 -080096 return Status::fromServiceSpecificError(static_cast<int32_t>(res));
shubang6d266262020-10-09 00:15:04 -070097}
98
99Result TunerService::configFilter() {
100 ALOGD("configFilter");
101 if (mFilter == NULL) {
102 ALOGD("Failed to configure filter: filter not found");
103 return Result::NOT_INITIALIZED;
104 }
105 DemuxFilterSettings filterSettings;
106 DemuxTsFilterSettings tsFilterSettings {
107 .tpid = 256,
108 };
109 DemuxFilterAvSettings filterAvSettings {
110 .isPassthrough = false,
111 };
112 tsFilterSettings.filterSettings.av(filterAvSettings);
113 filterSettings.ts(tsFilterSettings);
114 Result res = mFilter->configure(filterSettings);
115
116 if (res != Result::SUCCESS) {
117 ALOGD("config filter failed, res = %d", res);
118 return res;
119 }
120
121 Result getQueueDescResult = Result::UNKNOWN_ERROR;
122 mFilter->getQueueDesc(
123 [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
124 mFilterMQDesc = desc;
125 getQueueDescResult = r;
126 ALOGD("getFilterQueueDesc");
127 });
128 if (getQueueDescResult == Result::SUCCESS) {
129 unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(
130 mFilterMQDesc, &mAidlMQDesc);
Amy Zhanga046eee2021-01-12 14:44:58 -0800131 mAidlMq = new (nothrow) AidlMessageQueue(mAidlMQDesc);
shubang6d266262020-10-09 00:15:04 -0700132 EventFlag::createEventFlag(mAidlMq->getEventFlagWord(), &mEventFlag);
133 } else {
134 ALOGD("get MQDesc failed, res = %d", getQueueDescResult);
135 }
136 return getQueueDescResult;
shubang23aa3ac2020-09-07 18:56:28 -0700137}
138
Amy Zhangce2cb402021-01-21 12:50:47 -0800139Status TunerService::getFrontendIds(vector<int32_t>* ids) {
shubang6d266262020-10-09 00:15:04 -0700140 if (!getITuner()) {
Amy Zhanga046eee2021-01-12 14:44:58 -0800141 return Status::fromServiceSpecificError(
shubang6d266262020-10-09 00:15:04 -0700142 static_cast<int32_t>(Result::NOT_INITIALIZED));
shubang23aa3ac2020-09-07 18:56:28 -0700143 }
144 hidl_vec<FrontendId> feIds;
Amy Zhangce2cb402021-01-21 12:50:47 -0800145 Result res = getHidlFrontendIds(feIds);
shubang23aa3ac2020-09-07 18:56:28 -0700146 if (res != Result::SUCCESS) {
Amy Zhanga046eee2021-01-12 14:44:58 -0800147 return Status::fromServiceSpecificError(static_cast<int32_t>(res));
shubang23aa3ac2020-09-07 18:56:28 -0700148 }
149 ids->resize(feIds.size());
Amy Zhanga046eee2021-01-12 14:44:58 -0800150 copy(feIds.begin(), feIds.end(), ids->begin());
shubang23aa3ac2020-09-07 18:56:28 -0700151
Amy Zhang0f04c452020-10-30 13:36:44 -0700152 return Status::ok();
shubang23aa3ac2020-09-07 18:56:28 -0700153}
154
Amy Zhang70de35a2020-10-12 20:13:16 -0700155Status TunerService::getFrontendInfo(
Amy Zhang1d28bbb2021-01-13 18:11:15 -0800156 int32_t frontendHandle, TunerFrontendInfo* _aidl_return) {
Amy Zhang70de35a2020-10-12 20:13:16 -0700157 if (mTuner == nullptr) {
Amy Zhang0f04c452020-10-30 13:36:44 -0700158 ALOGE("ITuner service is not init.");
159 return ::ndk::ScopedAStatus::fromServiceSpecificError(
160 static_cast<int32_t>(Result::UNAVAILABLE));
Amy Zhang70de35a2020-10-12 20:13:16 -0700161 }
162
Amy Zhang70de35a2020-10-12 20:13:16 -0700163 FrontendInfo info;
Amy Zhanga046eee2021-01-12 14:44:58 -0800164 int feId = getResourceIdFromHandle(frontendHandle, FRONTEND);
Amy Zhangce2cb402021-01-21 12:50:47 -0800165 Result res = getHidlFrontendInfo(feId, info);
Amy Zhang70de35a2020-10-12 20:13:16 -0700166 if (res != Result::SUCCESS) {
Amy Zhang0f04c452020-10-30 13:36:44 -0700167 return Status::fromServiceSpecificError(static_cast<int32_t>(res));
Amy Zhang70de35a2020-10-12 20:13:16 -0700168 }
169
Amy Zhang1d28bbb2021-01-13 18:11:15 -0800170 TunerFrontendInfo tunerInfo = convertToAidlFrontendInfo(info);
Amy Zhang70de35a2020-10-12 20:13:16 -0700171 *_aidl_return = tunerInfo;
Amy Zhang0f04c452020-10-30 13:36:44 -0700172 return Status::ok();
173}
174
175Status TunerService::openFrontend(
Amy Zhanga046eee2021-01-12 14:44:58 -0800176 int32_t frontendHandle, shared_ptr<ITunerFrontend>* _aidl_return) {
Amy Zhang0f04c452020-10-30 13:36:44 -0700177 if (mTuner == nullptr) {
178 ALOGE("ITuner service is not init.");
Amy Zhanga046eee2021-01-12 14:44:58 -0800179 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
Amy Zhang0f04c452020-10-30 13:36:44 -0700180 }
181
Amy Zhanga046eee2021-01-12 14:44:58 -0800182 Result status;
183 sp<IFrontend> frontend;
184 int id = getResourceIdFromHandle(frontendHandle, FRONTEND);
185 mTuner->openFrontendById(id, [&](Result result, const sp<IFrontend>& fe) {
186 frontend = fe;
187 status = result;
188 });
189 if (status != Result::SUCCESS) {
190 return Status::fromServiceSpecificError(static_cast<int32_t>(status));
191 }
192 *_aidl_return = ::ndk::SharedRefBase::make<TunerFrontend>(frontend, id);
193 return Status::ok();
194}
195
196Status TunerService::getFmqSyncReadWrite(
197 MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) {
198 ALOGD("getFmqSyncReadWrite");
199 // TODO: put the following methods AIDL, and should be called from clients.
Amy Zhanga046eee2021-01-12 14:44:58 -0800200 configFilter();
201 mFilter->start();
202 if (mqDesc == nullptr) {
203 ALOGD("getFmqSyncReadWrite null MQDescriptor.");
204 *_aidl_return = false;
205 } else {
206 ALOGD("getFmqSyncReadWrite true");
207 *_aidl_return = true;
208 *mqDesc = move(mAidlMQDesc);
209 }
210 return ndk::ScopedAStatus::ok();
211}
212
213Status TunerService::openLnb(int lnbHandle, shared_ptr<ITunerLnb>* _aidl_return) {
Amy Zhangce2cb402021-01-21 12:50:47 -0800214 if (!getITuner()) {
215 ALOGD("get ITuner failed");
Amy Zhanga046eee2021-01-12 14:44:58 -0800216 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
217 }
218
219 Result status;
220 sp<ILnb> lnb;
221 int id = getResourceIdFromHandle(lnbHandle, LNB);
222 mTuner->openLnbById(id, [&](Result result, const sp<ILnb>& lnbSp){
223 lnb = lnbSp;
224 status = result;
225 });
226 if (status != Result::SUCCESS) {
227 return Status::fromServiceSpecificError(static_cast<int32_t>(status));
228 }
229
230 *_aidl_return = ::ndk::SharedRefBase::make<TunerLnb>(lnb, id);
231 return Status::ok();
232}
233
234Status TunerService::openLnbByName(const string& lnbName, shared_ptr<ITunerLnb>* _aidl_return) {
Amy Zhangce2cb402021-01-21 12:50:47 -0800235 if (!getITuner()) {
236 ALOGE("get ITuner failed");
Amy Zhanga046eee2021-01-12 14:44:58 -0800237 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
238 }
239
240 int lnbId;
241 Result status;
242 sp<ILnb> lnb;
243 mTuner->openLnbByName(lnbName, [&](Result r, LnbId id, const sp<ILnb>& lnbSp) {
244 status = r;
245 lnb = lnbSp;
246 lnbId = (int)id;
247 });
248 if (status != Result::SUCCESS) {
249 return Status::fromServiceSpecificError(static_cast<int32_t>(status));
250 }
251
252 *_aidl_return = ::ndk::SharedRefBase::make<TunerLnb>(lnb, lnbId);
Amy Zhang0f04c452020-10-30 13:36:44 -0700253 return Status::ok();
Amy Zhang70de35a2020-10-12 20:13:16 -0700254}
255
Amy Zhangce2cb402021-01-21 12:50:47 -0800256Status TunerService::updateTunerResources() {
257 if (!getITuner()) {
258 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
259 }
260
261 // Connect with Tuner Resource Manager.
262 ::ndk::SpAIBinder binder(AServiceManager_getService("tv_tuner_resource_mgr"));
263 mTunerResourceManager = ITunerResourceManager::fromBinder(binder);
264
265 updateFrontendResources();
266 updateLnbResources();
267 // TODO: update Demux, Descrambler.
268 return Status::ok();
269}
270
271void TunerService::updateFrontendResources() {
272 hidl_vec<FrontendId> ids;
273 Result res = getHidlFrontendIds(ids);
274 if (res != Result::SUCCESS) {
275 return;
276 }
277 vector<TunerFrontendInfo> infos;
278 for (int i = 0; i < ids.size(); i++) {
279 FrontendInfo frontendInfo;
280 Result res = getHidlFrontendInfo((int)ids[i], frontendInfo);
281 if (res != Result::SUCCESS) {
282 continue;
283 }
284 TunerFrontendInfo tunerFrontendInfo{
285 .handle = getResourceHandleFromId((int)ids[i], FRONTEND),
286 .type = static_cast<int>(frontendInfo.type),
287 .exclusiveGroupId = static_cast<int>(frontendInfo.exclusiveGroupId),
288 };
289 infos.push_back(tunerFrontendInfo);
290 }
291 mTunerResourceManager->setFrontendInfoList(infos);
292}
293
294void TunerService::updateLnbResources() {
295 vector<int> handles = getLnbHandles();
296 if (handles.size() == 0) {
297 return;
298 }
299 mTunerResourceManager->setLnbInfoList(handles);
300}
301
302vector<int> TunerService::getLnbHandles() {
303 vector<int> lnbHandles;
304 if (mTuner != NULL) {
305 Result res;
306 vector<LnbId> lnbIds;
307 mTuner->getLnbIds([&](Result r, const hardware::hidl_vec<LnbId>& ids) {
308 lnbIds = ids;
309 res = r;
310 });
311 if (res != Result::SUCCESS || lnbIds.size() == 0) {
312 } else {
313 for (int i = 0; i < lnbIds.size(); i++) {
314 lnbHandles.push_back(getResourceHandleFromId((int)lnbIds[i], LNB));
315 }
316 }
317 }
318
319 return lnbHandles;
320}
321
322Result TunerService::getHidlFrontendIds(hidl_vec<FrontendId>& ids) {
323 if (mTuner == NULL) {
324 return Result::NOT_INITIALIZED;
325 }
326 Result res;
327 mTuner->getFrontendIds([&](Result r, const hidl_vec<FrontendId>& frontendIds) {
328 ids = frontendIds;
329 res = r;
330 });
331 return res;
332}
333
334Result TunerService::getHidlFrontendInfo(int id, FrontendInfo& info) {
335 if (mTuner == NULL) {
336 return Result::NOT_INITIALIZED;
337 }
338 Result res;
339 mTuner->getFrontendInfo(id, [&](Result r, const FrontendInfo& feInfo) {
340 info = feInfo;
341 res = r;
342 });
343 return res;
344}
345
Amy Zhang1d28bbb2021-01-13 18:11:15 -0800346TunerFrontendInfo TunerService::convertToAidlFrontendInfo(FrontendInfo halInfo) {
347 TunerFrontendInfo info{
Amy Zhang70de35a2020-10-12 20:13:16 -0700348 .type = (int)halInfo.type,
349 .minFrequency = (int)halInfo.minFrequency,
350 .maxFrequency = (int)halInfo.maxFrequency,
351 .minSymbolRate = (int)halInfo.minSymbolRate,
352 .maxSymbolRate = (int)halInfo.maxSymbolRate,
353 .acquireRange = (int)halInfo.acquireRange,
354 .exclusiveGroupId = (int)halInfo.exclusiveGroupId,
355 };
356 for (int i = 0; i < halInfo.statusCaps.size(); i++) {
357 info.statusCaps.push_back((int)halInfo.statusCaps[i]);
358 }
359
360 TunerFrontendCapabilities caps;
361 switch (halInfo.type) {
362 case FrontendType::ANALOG: {
363 TunerFrontendAnalogCapabilities analogCaps{
364 .typeCap = (int)halInfo.frontendCaps.analogCaps().typeCap,
365 .sifStandardCap = (int)halInfo.frontendCaps.analogCaps().sifStandardCap,
366 };
367 caps.set<TunerFrontendCapabilities::analogCaps>(analogCaps);
368 break;
369 }
370 case FrontendType::ATSC: {
371 TunerFrontendAtscCapabilities atscCaps{
372 .modulationCap = (int)halInfo.frontendCaps.atscCaps().modulationCap,
373 };
374 caps.set<TunerFrontendCapabilities::atscCaps>(atscCaps);
375 break;
376 }
377 case FrontendType::ATSC3: {
378 TunerFrontendAtsc3Capabilities atsc3Caps{
379 .bandwidthCap = (int)halInfo.frontendCaps.atsc3Caps().bandwidthCap,
380 .modulationCap = (int)halInfo.frontendCaps.atsc3Caps().modulationCap,
381 .timeInterleaveModeCap =
382 (int)halInfo.frontendCaps.atsc3Caps().timeInterleaveModeCap,
383 .codeRateCap = (int)halInfo.frontendCaps.atsc3Caps().codeRateCap,
384 .demodOutputFormatCap = (int)halInfo.frontendCaps.atsc3Caps().demodOutputFormatCap,
385 .fecCap = (int)halInfo.frontendCaps.atsc3Caps().fecCap,
386 };
387 caps.set<TunerFrontendCapabilities::atsc3Caps>(atsc3Caps);
388 break;
389 }
390 case FrontendType::DVBC: {
391 TunerFrontendCableCapabilities cableCaps{
392 .modulationCap = (int)halInfo.frontendCaps.dvbcCaps().modulationCap,
393 .codeRateCap = (int)halInfo.frontendCaps.dvbcCaps().fecCap,
394 .annexCap = (int)halInfo.frontendCaps.dvbcCaps().annexCap,
395 };
396 caps.set<TunerFrontendCapabilities::cableCaps>(cableCaps);
397 break;
398 }
399 case FrontendType::DVBS: {
400 TunerFrontendDvbsCapabilities dvbsCaps{
401 .modulationCap = (int)halInfo.frontendCaps.dvbsCaps().modulationCap,
402 .codeRateCap = (long)halInfo.frontendCaps.dvbsCaps().innerfecCap,
403 .standard = (int)halInfo.frontendCaps.dvbsCaps().standard,
404 };
405 caps.set<TunerFrontendCapabilities::dvbsCaps>(dvbsCaps);
406 break;
407 }
408 case FrontendType::DVBT: {
409 TunerFrontendDvbtCapabilities dvbtCaps{
410 .transmissionModeCap = (int)halInfo.frontendCaps.dvbtCaps().transmissionModeCap,
411 .bandwidthCap = (int)halInfo.frontendCaps.dvbtCaps().bandwidthCap,
412 .constellationCap = (int)halInfo.frontendCaps.dvbtCaps().constellationCap,
413 .codeRateCap = (int)halInfo.frontendCaps.dvbtCaps().coderateCap,
414 .hierarchyCap = (int)halInfo.frontendCaps.dvbtCaps().hierarchyCap,
415 .guardIntervalCap = (int)halInfo.frontendCaps.dvbtCaps().guardIntervalCap,
416 .isT2Supported = (bool)halInfo.frontendCaps.dvbtCaps().isT2Supported,
417 .isMisoSupported = (bool)halInfo.frontendCaps.dvbtCaps().isMisoSupported,
418 };
419 caps.set<TunerFrontendCapabilities::dvbtCaps>(dvbtCaps);
420 break;
421 }
422 case FrontendType::ISDBS: {
423 TunerFrontendIsdbsCapabilities isdbsCaps{
424 .modulationCap = (int)halInfo.frontendCaps.isdbsCaps().modulationCap,
425 .codeRateCap = (int)halInfo.frontendCaps.isdbsCaps().coderateCap,
426 };
427 caps.set<TunerFrontendCapabilities::isdbsCaps>(isdbsCaps);
428 break;
429 }
430 case FrontendType::ISDBS3: {
431 TunerFrontendIsdbs3Capabilities isdbs3Caps{
432 .modulationCap = (int)halInfo.frontendCaps.isdbs3Caps().modulationCap,
433 .codeRateCap = (int)halInfo.frontendCaps.isdbs3Caps().coderateCap,
434 };
435 caps.set<TunerFrontendCapabilities::isdbs3Caps>(isdbs3Caps);
436 break;
437 }
438 case FrontendType::ISDBT: {
439 TunerFrontendIsdbtCapabilities isdbtCaps{
440 .modeCap = (int)halInfo.frontendCaps.isdbtCaps().modeCap,
441 .bandwidthCap = (int)halInfo.frontendCaps.isdbtCaps().bandwidthCap,
442 .modulationCap = (int)halInfo.frontendCaps.isdbtCaps().modulationCap,
443 .codeRateCap = (int)halInfo.frontendCaps.isdbtCaps().coderateCap,
444 .guardIntervalCap = (int)halInfo.frontendCaps.isdbtCaps().guardIntervalCap,
445 };
446 caps.set<TunerFrontendCapabilities::isdbtCaps>(isdbtCaps);
447 break;
448 }
449 default:
450 break;
451 }
452
453 info.caps = caps;
454 return info;
455}
shubang23aa3ac2020-09-07 18:56:28 -0700456} // namespace android