blob: f97cbfe1d62ed9d867c12894b79a13204b4f692d [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>
20#include <utils/Log.h>
21#include "TunerService.h"
Amy Zhanga046eee2021-01-12 14:44:58 -080022#include "TunerFrontend.h"
23#include "TunerLnb.h"
shubangae56a2e2021-01-21 07:29:55 -080024#include "TunerDemux.h"
shubang23aa3ac2020-09-07 18:56:28 -070025
Amy Zhang70de35a2020-10-12 20:13:16 -070026using ::aidl::android::media::tv::tuner::TunerFrontendAnalogCapabilities;
27using ::aidl::android::media::tv::tuner::TunerFrontendAtsc3Capabilities;
28using ::aidl::android::media::tv::tuner::TunerFrontendAtscCapabilities;
29using ::aidl::android::media::tv::tuner::TunerFrontendCableCapabilities;
30using ::aidl::android::media::tv::tuner::TunerFrontendCapabilities;
31using ::aidl::android::media::tv::tuner::TunerFrontendDvbsCapabilities;
32using ::aidl::android::media::tv::tuner::TunerFrontendDvbtCapabilities;
33using ::aidl::android::media::tv::tuner::TunerFrontendIsdbs3Capabilities;
34using ::aidl::android::media::tv::tuner::TunerFrontendIsdbsCapabilities;
35using ::aidl::android::media::tv::tuner::TunerFrontendIsdbtCapabilities;
shubang23aa3ac2020-09-07 18:56:28 -070036using ::android::hardware::hidl_vec;
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
60template <typename HidlPayload, typename AidlPayload, typename AidlFlavor>
61bool TunerService::unsafeHidlToAidlMQDescriptor(
62 const hardware::MQDescriptor<HidlPayload, FlavorTypeToValue<AidlFlavor>::value>& hidlDesc,
63 MQDescriptor<AidlPayload, AidlFlavor>* aidlDesc) {
64 // TODO: use the builtin coversion method when it's merged.
65 ALOGD("unsafeHidlToAidlMQDescriptor");
66 static_assert(sizeof(HidlPayload) == sizeof(AidlPayload), "Payload types are incompatible");
67 static_assert(
68 has_typedef_fixed_size<AidlPayload>::value == true ||
Amy Zhanga046eee2021-01-12 14:44:58 -080069 is_fundamental<AidlPayload>::value ||
70 is_enum<AidlPayload>::value,
shubang6d266262020-10-09 00:15:04 -070071 "Only fundamental types, enums, and AIDL parcelables annotated with @FixedSize "
72 "and built for the NDK backend are supported as AIDL payload types.");
73 aidlDesc->fileDescriptor = ndk::ScopedFileDescriptor(dup(hidlDesc.handle()->data[0]));
74 for (const auto& grantor : hidlDesc.grantors()) {
75 if (static_cast<int32_t>(grantor.offset) < 0 || static_cast<int64_t>(grantor.extent) < 0) {
76 ALOGD("Unsafe static_cast of grantor fields. offset=%d, extend=%ld",
77 static_cast<int32_t>(grantor.offset), static_cast<long>(grantor.extent));
78 logError(
79 "Unsafe static_cast of grantor fields. Either the hardware::MQDescriptor is "
80 "invalid, or the MessageQueue is too large to be described by AIDL.");
81 return false;
82 }
83 aidlDesc->grantors.push_back(
84 GrantorDescriptor {
85 .offset = static_cast<int32_t>(grantor.offset),
86 .extent = static_cast<int64_t>(grantor.extent)
87 });
88 }
89 if (static_cast<int32_t>(hidlDesc.getQuantum()) < 0 ||
90 static_cast<int32_t>(hidlDesc.getFlags()) < 0) {
91 ALOGD("Unsafe static_cast of quantum or flags. Quantum=%d, flags=%d",
92 static_cast<int32_t>(hidlDesc.getQuantum()),
93 static_cast<int32_t>(hidlDesc.getFlags()));
94 logError(
95 "Unsafe static_cast of quantum or flags. Either the hardware::MQDescriptor is "
96 "invalid, or the MessageQueue is too large to be described by AIDL.");
97 return false;
98 }
99 aidlDesc->quantum = static_cast<int32_t>(hidlDesc.getQuantum());
100 aidlDesc->flags = static_cast<int32_t>(hidlDesc.getFlags());
101 return true;
102}
103
104bool TunerService::getITuner() {
105 ALOGD("getITuner");
106 if (mTuner != nullptr) {
107 return true;
108 }
Amy Zhang0f04c452020-10-30 13:36:44 -0700109 mTuner = ITuner::getService();
110 if (mTuner == nullptr) {
shubang6d266262020-10-09 00:15:04 -0700111 ALOGE("Failed to get ITuner service");
112 return false;
Amy Zhang0f04c452020-10-30 13:36:44 -0700113 }
shubang6d266262020-10-09 00:15:04 -0700114 return true;
115}
116
shubangae56a2e2021-01-21 07:29:55 -0800117Status TunerService::openDemux(
118 int /* demuxHandle */, std::shared_ptr<ITunerDemux>* _aidl_return) {
shubang6d266262020-10-09 00:15:04 -0700119 ALOGD("openDemux");
120 if (!getITuner()) {
shubangae56a2e2021-01-21 07:29:55 -0800121 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::NOT_INITIALIZED));
shubang6d266262020-10-09 00:15:04 -0700122 }
123 if (mDemux != nullptr) {
shubangae56a2e2021-01-21 07:29:55 -0800124 *_aidl_return = mDemux->ref<ITunerDemux>();
125 return Status::ok();
shubang6d266262020-10-09 00:15:04 -0700126 }
127 Result res;
128 uint32_t id;
shubangae56a2e2021-01-21 07:29:55 -0800129 sp<IDemux> demuxSp = nullptr;
shubang6d266262020-10-09 00:15:04 -0700130 mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
131 demuxSp = demux;
132 id = demuxId;
133 res = r;
134 ALOGD("open demux, id = %d", demuxId);
135 });
136 if (res == Result::SUCCESS) {
shubangae56a2e2021-01-21 07:29:55 -0800137 mDemux = ::ndk::SharedRefBase::make<TunerDemux>(demuxSp, id);
138 *_aidl_return = mDemux->ref<ITunerDemux>();
139 return Status::ok();
shubang6d266262020-10-09 00:15:04 -0700140 }
141
shubangae56a2e2021-01-21 07:29:55 -0800142 ALOGD("open demux failed, res = %d", res);
143 mDemux = nullptr;
144 return Status::fromServiceSpecificError(static_cast<int32_t>(res));
shubang6d266262020-10-09 00:15:04 -0700145}
146
147Result TunerService::configFilter() {
148 ALOGD("configFilter");
149 if (mFilter == NULL) {
150 ALOGD("Failed to configure filter: filter not found");
151 return Result::NOT_INITIALIZED;
152 }
153 DemuxFilterSettings filterSettings;
154 DemuxTsFilterSettings tsFilterSettings {
155 .tpid = 256,
156 };
157 DemuxFilterAvSettings filterAvSettings {
158 .isPassthrough = false,
159 };
160 tsFilterSettings.filterSettings.av(filterAvSettings);
161 filterSettings.ts(tsFilterSettings);
162 Result res = mFilter->configure(filterSettings);
163
164 if (res != Result::SUCCESS) {
165 ALOGD("config filter failed, res = %d", res);
166 return res;
167 }
168
169 Result getQueueDescResult = Result::UNKNOWN_ERROR;
170 mFilter->getQueueDesc(
171 [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
172 mFilterMQDesc = desc;
173 getQueueDescResult = r;
174 ALOGD("getFilterQueueDesc");
175 });
176 if (getQueueDescResult == Result::SUCCESS) {
177 unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(
178 mFilterMQDesc, &mAidlMQDesc);
Amy Zhanga046eee2021-01-12 14:44:58 -0800179 mAidlMq = new (nothrow) AidlMessageQueue(mAidlMQDesc);
shubang6d266262020-10-09 00:15:04 -0700180 EventFlag::createEventFlag(mAidlMq->getEventFlagWord(), &mEventFlag);
181 } else {
182 ALOGD("get MQDesc failed, res = %d", getQueueDescResult);
183 }
184 return getQueueDescResult;
shubang23aa3ac2020-09-07 18:56:28 -0700185}
186
Amy Zhanga046eee2021-01-12 14:44:58 -0800187Status TunerService::getFrontendIds(vector<int32_t>* ids, int32_t* /* _aidl_return */) {
shubang6d266262020-10-09 00:15:04 -0700188 if (!getITuner()) {
Amy Zhanga046eee2021-01-12 14:44:58 -0800189 return Status::fromServiceSpecificError(
shubang6d266262020-10-09 00:15:04 -0700190 static_cast<int32_t>(Result::NOT_INITIALIZED));
shubang23aa3ac2020-09-07 18:56:28 -0700191 }
192 hidl_vec<FrontendId> feIds;
193 Result res;
194 mTuner->getFrontendIds([&](Result r, const hidl_vec<FrontendId>& frontendIds) {
195 feIds = frontendIds;
196 res = r;
197 });
198 if (res != Result::SUCCESS) {
Amy Zhanga046eee2021-01-12 14:44:58 -0800199 return Status::fromServiceSpecificError(static_cast<int32_t>(res));
shubang23aa3ac2020-09-07 18:56:28 -0700200 }
201 ids->resize(feIds.size());
Amy Zhanga046eee2021-01-12 14:44:58 -0800202 copy(feIds.begin(), feIds.end(), ids->begin());
shubang23aa3ac2020-09-07 18:56:28 -0700203
Amy Zhang0f04c452020-10-30 13:36:44 -0700204 return Status::ok();
shubang23aa3ac2020-09-07 18:56:28 -0700205}
206
Amy Zhang70de35a2020-10-12 20:13:16 -0700207Status TunerService::getFrontendInfo(
Amy Zhang1d28bbb2021-01-13 18:11:15 -0800208 int32_t frontendHandle, TunerFrontendInfo* _aidl_return) {
Amy Zhang70de35a2020-10-12 20:13:16 -0700209 if (mTuner == nullptr) {
Amy Zhang0f04c452020-10-30 13:36:44 -0700210 ALOGE("ITuner service is not init.");
211 return ::ndk::ScopedAStatus::fromServiceSpecificError(
212 static_cast<int32_t>(Result::UNAVAILABLE));
Amy Zhang70de35a2020-10-12 20:13:16 -0700213 }
214
215 Result res;
216 FrontendInfo info;
Amy Zhanga046eee2021-01-12 14:44:58 -0800217 int feId = getResourceIdFromHandle(frontendHandle, FRONTEND);
Amy Zhang70de35a2020-10-12 20:13:16 -0700218 mTuner->getFrontendInfo(feId, [&](Result r, const FrontendInfo& feInfo) {
219 info = feInfo;
220 res = r;
221 });
222 if (res != Result::SUCCESS) {
Amy Zhang0f04c452020-10-30 13:36:44 -0700223 return Status::fromServiceSpecificError(static_cast<int32_t>(res));
Amy Zhang70de35a2020-10-12 20:13:16 -0700224 }
225
Amy Zhang1d28bbb2021-01-13 18:11:15 -0800226 TunerFrontendInfo tunerInfo = convertToAidlFrontendInfo(info);
Amy Zhang70de35a2020-10-12 20:13:16 -0700227 *_aidl_return = tunerInfo;
Amy Zhang0f04c452020-10-30 13:36:44 -0700228 return Status::ok();
229}
230
231Status TunerService::openFrontend(
Amy Zhanga046eee2021-01-12 14:44:58 -0800232 int32_t frontendHandle, shared_ptr<ITunerFrontend>* _aidl_return) {
Amy Zhang0f04c452020-10-30 13:36:44 -0700233 if (mTuner == nullptr) {
234 ALOGE("ITuner service is not init.");
Amy Zhanga046eee2021-01-12 14:44:58 -0800235 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
Amy Zhang0f04c452020-10-30 13:36:44 -0700236 }
237
Amy Zhanga046eee2021-01-12 14:44:58 -0800238 Result status;
239 sp<IFrontend> frontend;
240 int id = getResourceIdFromHandle(frontendHandle, FRONTEND);
241 mTuner->openFrontendById(id, [&](Result result, const sp<IFrontend>& fe) {
242 frontend = fe;
243 status = result;
244 });
245 if (status != Result::SUCCESS) {
246 return Status::fromServiceSpecificError(static_cast<int32_t>(status));
247 }
248 *_aidl_return = ::ndk::SharedRefBase::make<TunerFrontend>(frontend, id);
249 return Status::ok();
250}
251
252Status TunerService::getFmqSyncReadWrite(
253 MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) {
254 ALOGD("getFmqSyncReadWrite");
255 // TODO: put the following methods AIDL, and should be called from clients.
Amy Zhanga046eee2021-01-12 14:44:58 -0800256 configFilter();
257 mFilter->start();
258 if (mqDesc == nullptr) {
259 ALOGD("getFmqSyncReadWrite null MQDescriptor.");
260 *_aidl_return = false;
261 } else {
262 ALOGD("getFmqSyncReadWrite true");
263 *_aidl_return = true;
264 *mqDesc = move(mAidlMQDesc);
265 }
266 return ndk::ScopedAStatus::ok();
267}
268
269Status TunerService::openLnb(int lnbHandle, shared_ptr<ITunerLnb>* _aidl_return) {
270 if (mTuner == nullptr) {
271 ALOGE("ITuner service is not init.");
272 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
273 }
274
275 Result status;
276 sp<ILnb> lnb;
277 int id = getResourceIdFromHandle(lnbHandle, LNB);
278 mTuner->openLnbById(id, [&](Result result, const sp<ILnb>& lnbSp){
279 lnb = lnbSp;
280 status = result;
281 });
282 if (status != Result::SUCCESS) {
283 return Status::fromServiceSpecificError(static_cast<int32_t>(status));
284 }
285
286 *_aidl_return = ::ndk::SharedRefBase::make<TunerLnb>(lnb, id);
287 return Status::ok();
288}
289
290Status TunerService::openLnbByName(const string& lnbName, shared_ptr<ITunerLnb>* _aidl_return) {
291 if (mTuner == nullptr) {
292 ALOGE("ITuner service is not init.");
293 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
294 }
295
296 int lnbId;
297 Result status;
298 sp<ILnb> lnb;
299 mTuner->openLnbByName(lnbName, [&](Result r, LnbId id, const sp<ILnb>& lnbSp) {
300 status = r;
301 lnb = lnbSp;
302 lnbId = (int)id;
303 });
304 if (status != Result::SUCCESS) {
305 return Status::fromServiceSpecificError(static_cast<int32_t>(status));
306 }
307
308 *_aidl_return = ::ndk::SharedRefBase::make<TunerLnb>(lnb, lnbId);
Amy Zhang0f04c452020-10-30 13:36:44 -0700309 return Status::ok();
Amy Zhang70de35a2020-10-12 20:13:16 -0700310}
311
Amy Zhang1d28bbb2021-01-13 18:11:15 -0800312TunerFrontendInfo TunerService::convertToAidlFrontendInfo(FrontendInfo halInfo) {
313 TunerFrontendInfo info{
Amy Zhang70de35a2020-10-12 20:13:16 -0700314 .type = (int)halInfo.type,
315 .minFrequency = (int)halInfo.minFrequency,
316 .maxFrequency = (int)halInfo.maxFrequency,
317 .minSymbolRate = (int)halInfo.minSymbolRate,
318 .maxSymbolRate = (int)halInfo.maxSymbolRate,
319 .acquireRange = (int)halInfo.acquireRange,
320 .exclusiveGroupId = (int)halInfo.exclusiveGroupId,
321 };
322 for (int i = 0; i < halInfo.statusCaps.size(); i++) {
323 info.statusCaps.push_back((int)halInfo.statusCaps[i]);
324 }
325
326 TunerFrontendCapabilities caps;
327 switch (halInfo.type) {
328 case FrontendType::ANALOG: {
329 TunerFrontendAnalogCapabilities analogCaps{
330 .typeCap = (int)halInfo.frontendCaps.analogCaps().typeCap,
331 .sifStandardCap = (int)halInfo.frontendCaps.analogCaps().sifStandardCap,
332 };
333 caps.set<TunerFrontendCapabilities::analogCaps>(analogCaps);
334 break;
335 }
336 case FrontendType::ATSC: {
337 TunerFrontendAtscCapabilities atscCaps{
338 .modulationCap = (int)halInfo.frontendCaps.atscCaps().modulationCap,
339 };
340 caps.set<TunerFrontendCapabilities::atscCaps>(atscCaps);
341 break;
342 }
343 case FrontendType::ATSC3: {
344 TunerFrontendAtsc3Capabilities atsc3Caps{
345 .bandwidthCap = (int)halInfo.frontendCaps.atsc3Caps().bandwidthCap,
346 .modulationCap = (int)halInfo.frontendCaps.atsc3Caps().modulationCap,
347 .timeInterleaveModeCap =
348 (int)halInfo.frontendCaps.atsc3Caps().timeInterleaveModeCap,
349 .codeRateCap = (int)halInfo.frontendCaps.atsc3Caps().codeRateCap,
350 .demodOutputFormatCap = (int)halInfo.frontendCaps.atsc3Caps().demodOutputFormatCap,
351 .fecCap = (int)halInfo.frontendCaps.atsc3Caps().fecCap,
352 };
353 caps.set<TunerFrontendCapabilities::atsc3Caps>(atsc3Caps);
354 break;
355 }
356 case FrontendType::DVBC: {
357 TunerFrontendCableCapabilities cableCaps{
358 .modulationCap = (int)halInfo.frontendCaps.dvbcCaps().modulationCap,
359 .codeRateCap = (int)halInfo.frontendCaps.dvbcCaps().fecCap,
360 .annexCap = (int)halInfo.frontendCaps.dvbcCaps().annexCap,
361 };
362 caps.set<TunerFrontendCapabilities::cableCaps>(cableCaps);
363 break;
364 }
365 case FrontendType::DVBS: {
366 TunerFrontendDvbsCapabilities dvbsCaps{
367 .modulationCap = (int)halInfo.frontendCaps.dvbsCaps().modulationCap,
368 .codeRateCap = (long)halInfo.frontendCaps.dvbsCaps().innerfecCap,
369 .standard = (int)halInfo.frontendCaps.dvbsCaps().standard,
370 };
371 caps.set<TunerFrontendCapabilities::dvbsCaps>(dvbsCaps);
372 break;
373 }
374 case FrontendType::DVBT: {
375 TunerFrontendDvbtCapabilities dvbtCaps{
376 .transmissionModeCap = (int)halInfo.frontendCaps.dvbtCaps().transmissionModeCap,
377 .bandwidthCap = (int)halInfo.frontendCaps.dvbtCaps().bandwidthCap,
378 .constellationCap = (int)halInfo.frontendCaps.dvbtCaps().constellationCap,
379 .codeRateCap = (int)halInfo.frontendCaps.dvbtCaps().coderateCap,
380 .hierarchyCap = (int)halInfo.frontendCaps.dvbtCaps().hierarchyCap,
381 .guardIntervalCap = (int)halInfo.frontendCaps.dvbtCaps().guardIntervalCap,
382 .isT2Supported = (bool)halInfo.frontendCaps.dvbtCaps().isT2Supported,
383 .isMisoSupported = (bool)halInfo.frontendCaps.dvbtCaps().isMisoSupported,
384 };
385 caps.set<TunerFrontendCapabilities::dvbtCaps>(dvbtCaps);
386 break;
387 }
388 case FrontendType::ISDBS: {
389 TunerFrontendIsdbsCapabilities isdbsCaps{
390 .modulationCap = (int)halInfo.frontendCaps.isdbsCaps().modulationCap,
391 .codeRateCap = (int)halInfo.frontendCaps.isdbsCaps().coderateCap,
392 };
393 caps.set<TunerFrontendCapabilities::isdbsCaps>(isdbsCaps);
394 break;
395 }
396 case FrontendType::ISDBS3: {
397 TunerFrontendIsdbs3Capabilities isdbs3Caps{
398 .modulationCap = (int)halInfo.frontendCaps.isdbs3Caps().modulationCap,
399 .codeRateCap = (int)halInfo.frontendCaps.isdbs3Caps().coderateCap,
400 };
401 caps.set<TunerFrontendCapabilities::isdbs3Caps>(isdbs3Caps);
402 break;
403 }
404 case FrontendType::ISDBT: {
405 TunerFrontendIsdbtCapabilities isdbtCaps{
406 .modeCap = (int)halInfo.frontendCaps.isdbtCaps().modeCap,
407 .bandwidthCap = (int)halInfo.frontendCaps.isdbtCaps().bandwidthCap,
408 .modulationCap = (int)halInfo.frontendCaps.isdbtCaps().modulationCap,
409 .codeRateCap = (int)halInfo.frontendCaps.isdbtCaps().coderateCap,
410 .guardIntervalCap = (int)halInfo.frontendCaps.isdbtCaps().guardIntervalCap,
411 };
412 caps.set<TunerFrontendCapabilities::isdbtCaps>(isdbtCaps);
413 break;
414 }
415 default:
416 break;
417 }
418
419 info.caps = caps;
420 return info;
421}
shubang23aa3ac2020-09-07 18:56:28 -0700422} // namespace android