blob: ef3d1f2eaa2903eaf826c884774811fb85e80ec6 [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"
shubang23aa3ac2020-09-07 18:56:28 -070024
Amy Zhang70de35a2020-10-12 20:13:16 -070025using ::aidl::android::media::tv::tuner::TunerFrontendAnalogCapabilities;
26using ::aidl::android::media::tv::tuner::TunerFrontendAtsc3Capabilities;
27using ::aidl::android::media::tv::tuner::TunerFrontendAtscCapabilities;
28using ::aidl::android::media::tv::tuner::TunerFrontendCableCapabilities;
29using ::aidl::android::media::tv::tuner::TunerFrontendCapabilities;
30using ::aidl::android::media::tv::tuner::TunerFrontendDvbsCapabilities;
31using ::aidl::android::media::tv::tuner::TunerFrontendDvbtCapabilities;
32using ::aidl::android::media::tv::tuner::TunerFrontendIsdbs3Capabilities;
33using ::aidl::android::media::tv::tuner::TunerFrontendIsdbsCapabilities;
34using ::aidl::android::media::tv::tuner::TunerFrontendIsdbtCapabilities;
shubang23aa3ac2020-09-07 18:56:28 -070035using ::android::hardware::hidl_vec;
shubang6d266262020-10-09 00:15:04 -070036using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
37using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
38using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
39using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
40using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
shubang23aa3ac2020-09-07 18:56:28 -070041using ::android::hardware::tv::tuner::V1_0::FrontendId;
Amy Zhang70de35a2020-10-12 20:13:16 -070042using ::android::hardware::tv::tuner::V1_0::FrontendType;
Amy Zhanga046eee2021-01-12 14:44:58 -080043using ::android::hardware::tv::tuner::V1_0::IFrontend;
44using ::android::hardware::tv::tuner::V1_0::ILnb;
45using ::android::hardware::tv::tuner::V1_0::LnbId;
shubang23aa3ac2020-09-07 18:56:28 -070046using ::android::hardware::tv::tuner::V1_0::Result;
47
48namespace android {
49
shubang23aa3ac2020-09-07 18:56:28 -070050TunerService::TunerService() {}
51TunerService::~TunerService() {}
52
53void TunerService::instantiate() {
Amy Zhanga046eee2021-01-12 14:44:58 -080054 shared_ptr<TunerService> service =
shubang23aa3ac2020-09-07 18:56:28 -070055 ::ndk::SharedRefBase::make<TunerService>();
56 AServiceManager_addService(service->asBinder().get(), getServiceName());
shubang6d266262020-10-09 00:15:04 -070057}
58
59template <typename HidlPayload, typename AidlPayload, typename AidlFlavor>
60bool TunerService::unsafeHidlToAidlMQDescriptor(
61 const hardware::MQDescriptor<HidlPayload, FlavorTypeToValue<AidlFlavor>::value>& hidlDesc,
62 MQDescriptor<AidlPayload, AidlFlavor>* aidlDesc) {
63 // TODO: use the builtin coversion method when it's merged.
64 ALOGD("unsafeHidlToAidlMQDescriptor");
65 static_assert(sizeof(HidlPayload) == sizeof(AidlPayload), "Payload types are incompatible");
66 static_assert(
67 has_typedef_fixed_size<AidlPayload>::value == true ||
Amy Zhanga046eee2021-01-12 14:44:58 -080068 is_fundamental<AidlPayload>::value ||
69 is_enum<AidlPayload>::value,
shubang6d266262020-10-09 00:15:04 -070070 "Only fundamental types, enums, and AIDL parcelables annotated with @FixedSize "
71 "and built for the NDK backend are supported as AIDL payload types.");
72 aidlDesc->fileDescriptor = ndk::ScopedFileDescriptor(dup(hidlDesc.handle()->data[0]));
73 for (const auto& grantor : hidlDesc.grantors()) {
74 if (static_cast<int32_t>(grantor.offset) < 0 || static_cast<int64_t>(grantor.extent) < 0) {
75 ALOGD("Unsafe static_cast of grantor fields. offset=%d, extend=%ld",
76 static_cast<int32_t>(grantor.offset), static_cast<long>(grantor.extent));
77 logError(
78 "Unsafe static_cast of grantor fields. Either the hardware::MQDescriptor is "
79 "invalid, or the MessageQueue is too large to be described by AIDL.");
80 return false;
81 }
82 aidlDesc->grantors.push_back(
83 GrantorDescriptor {
84 .offset = static_cast<int32_t>(grantor.offset),
85 .extent = static_cast<int64_t>(grantor.extent)
86 });
87 }
88 if (static_cast<int32_t>(hidlDesc.getQuantum()) < 0 ||
89 static_cast<int32_t>(hidlDesc.getFlags()) < 0) {
90 ALOGD("Unsafe static_cast of quantum or flags. Quantum=%d, flags=%d",
91 static_cast<int32_t>(hidlDesc.getQuantum()),
92 static_cast<int32_t>(hidlDesc.getFlags()));
93 logError(
94 "Unsafe static_cast of quantum or flags. Either the hardware::MQDescriptor is "
95 "invalid, or the MessageQueue is too large to be described by AIDL.");
96 return false;
97 }
98 aidlDesc->quantum = static_cast<int32_t>(hidlDesc.getQuantum());
99 aidlDesc->flags = static_cast<int32_t>(hidlDesc.getFlags());
100 return true;
101}
102
103bool TunerService::getITuner() {
104 ALOGD("getITuner");
105 if (mTuner != nullptr) {
106 return true;
107 }
Amy Zhang0f04c452020-10-30 13:36:44 -0700108 mTuner = ITuner::getService();
109 if (mTuner == nullptr) {
shubang6d266262020-10-09 00:15:04 -0700110 ALOGE("Failed to get ITuner service");
111 return false;
Amy Zhang0f04c452020-10-30 13:36:44 -0700112 }
shubang6d266262020-10-09 00:15:04 -0700113 return true;
114}
115
116Result TunerService::openDemux() {
117 ALOGD("openDemux");
118 if (!getITuner()) {
119 return Result::NOT_INITIALIZED;
120 }
121 if (mDemux != nullptr) {
122 return Result::SUCCESS;
123 }
124 Result res;
125 uint32_t id;
126 sp<IDemux> demuxSp;
127 mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
128 demuxSp = demux;
129 id = demuxId;
130 res = r;
131 ALOGD("open demux, id = %d", demuxId);
132 });
133 if (res == Result::SUCCESS) {
134 mDemux = demuxSp;
135 } else {
136 ALOGD("open demux failed, res = %d", res);
137 }
138 return res;
139}
140
141Result TunerService::openFilter() {
142 ALOGD("openFilter");
143 if (!getITuner()) {
144 return Result::NOT_INITIALIZED;
145 }
146 DemuxFilterMainType mainType = DemuxFilterMainType::TS;
147 DemuxFilterType filterType {
148 .mainType = mainType,
149 };
150 filterType.subType.tsFilterType(DemuxTsFilterType::VIDEO);
151
152 sp<FilterCallback> callback = new FilterCallback();
153 Result res;
154 mDemux->openFilter(filterType, 16000000, callback,
155 [&](Result r, const sp<IFilter>& filter) {
156 mFilter = filter;
157 res = r;
158 });
159 if (res != Result::SUCCESS || mFilter == NULL) {
160 ALOGD("Failed to open filter, type = %d", filterType.mainType);
161 return res;
162 }
163
164 return Result::SUCCESS;
165}
166
167Result TunerService::configFilter() {
168 ALOGD("configFilter");
169 if (mFilter == NULL) {
170 ALOGD("Failed to configure filter: filter not found");
171 return Result::NOT_INITIALIZED;
172 }
173 DemuxFilterSettings filterSettings;
174 DemuxTsFilterSettings tsFilterSettings {
175 .tpid = 256,
176 };
177 DemuxFilterAvSettings filterAvSettings {
178 .isPassthrough = false,
179 };
180 tsFilterSettings.filterSettings.av(filterAvSettings);
181 filterSettings.ts(tsFilterSettings);
182 Result res = mFilter->configure(filterSettings);
183
184 if (res != Result::SUCCESS) {
185 ALOGD("config filter failed, res = %d", res);
186 return res;
187 }
188
189 Result getQueueDescResult = Result::UNKNOWN_ERROR;
190 mFilter->getQueueDesc(
191 [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
192 mFilterMQDesc = desc;
193 getQueueDescResult = r;
194 ALOGD("getFilterQueueDesc");
195 });
196 if (getQueueDescResult == Result::SUCCESS) {
197 unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(
198 mFilterMQDesc, &mAidlMQDesc);
Amy Zhanga046eee2021-01-12 14:44:58 -0800199 mAidlMq = new (nothrow) AidlMessageQueue(mAidlMQDesc);
shubang6d266262020-10-09 00:15:04 -0700200 EventFlag::createEventFlag(mAidlMq->getEventFlagWord(), &mEventFlag);
201 } else {
202 ALOGD("get MQDesc failed, res = %d", getQueueDescResult);
203 }
204 return getQueueDescResult;
shubang23aa3ac2020-09-07 18:56:28 -0700205}
206
Amy Zhanga046eee2021-01-12 14:44:58 -0800207Status TunerService::getFrontendIds(vector<int32_t>* ids, int32_t* /* _aidl_return */) {
shubang6d266262020-10-09 00:15:04 -0700208 if (!getITuner()) {
Amy Zhanga046eee2021-01-12 14:44:58 -0800209 return Status::fromServiceSpecificError(
shubang6d266262020-10-09 00:15:04 -0700210 static_cast<int32_t>(Result::NOT_INITIALIZED));
shubang23aa3ac2020-09-07 18:56:28 -0700211 }
212 hidl_vec<FrontendId> feIds;
213 Result res;
214 mTuner->getFrontendIds([&](Result r, const hidl_vec<FrontendId>& frontendIds) {
215 feIds = frontendIds;
216 res = r;
217 });
218 if (res != Result::SUCCESS) {
Amy Zhanga046eee2021-01-12 14:44:58 -0800219 return Status::fromServiceSpecificError(static_cast<int32_t>(res));
shubang23aa3ac2020-09-07 18:56:28 -0700220 }
221 ids->resize(feIds.size());
Amy Zhanga046eee2021-01-12 14:44:58 -0800222 copy(feIds.begin(), feIds.end(), ids->begin());
shubang23aa3ac2020-09-07 18:56:28 -0700223
Amy Zhang0f04c452020-10-30 13:36:44 -0700224 return Status::ok();
shubang23aa3ac2020-09-07 18:56:28 -0700225}
226
Amy Zhang70de35a2020-10-12 20:13:16 -0700227Status TunerService::getFrontendInfo(
Amy Zhang1d28bbb2021-01-13 18:11:15 -0800228 int32_t frontendHandle, TunerFrontendInfo* _aidl_return) {
Amy Zhang70de35a2020-10-12 20:13:16 -0700229 if (mTuner == nullptr) {
Amy Zhang0f04c452020-10-30 13:36:44 -0700230 ALOGE("ITuner service is not init.");
231 return ::ndk::ScopedAStatus::fromServiceSpecificError(
232 static_cast<int32_t>(Result::UNAVAILABLE));
Amy Zhang70de35a2020-10-12 20:13:16 -0700233 }
234
235 Result res;
236 FrontendInfo info;
Amy Zhanga046eee2021-01-12 14:44:58 -0800237 int feId = getResourceIdFromHandle(frontendHandle, FRONTEND);
Amy Zhang70de35a2020-10-12 20:13:16 -0700238 mTuner->getFrontendInfo(feId, [&](Result r, const FrontendInfo& feInfo) {
239 info = feInfo;
240 res = r;
241 });
242 if (res != Result::SUCCESS) {
Amy Zhang0f04c452020-10-30 13:36:44 -0700243 return Status::fromServiceSpecificError(static_cast<int32_t>(res));
Amy Zhang70de35a2020-10-12 20:13:16 -0700244 }
245
Amy Zhang1d28bbb2021-01-13 18:11:15 -0800246 TunerFrontendInfo tunerInfo = convertToAidlFrontendInfo(info);
Amy Zhang70de35a2020-10-12 20:13:16 -0700247 *_aidl_return = tunerInfo;
Amy Zhang0f04c452020-10-30 13:36:44 -0700248 return Status::ok();
249}
250
251Status TunerService::openFrontend(
Amy Zhanga046eee2021-01-12 14:44:58 -0800252 int32_t frontendHandle, shared_ptr<ITunerFrontend>* _aidl_return) {
Amy Zhang0f04c452020-10-30 13:36:44 -0700253 if (mTuner == nullptr) {
254 ALOGE("ITuner service is not init.");
Amy Zhanga046eee2021-01-12 14:44:58 -0800255 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
Amy Zhang0f04c452020-10-30 13:36:44 -0700256 }
257
Amy Zhanga046eee2021-01-12 14:44:58 -0800258 Result status;
259 sp<IFrontend> frontend;
260 int id = getResourceIdFromHandle(frontendHandle, FRONTEND);
261 mTuner->openFrontendById(id, [&](Result result, const sp<IFrontend>& fe) {
262 frontend = fe;
263 status = result;
264 });
265 if (status != Result::SUCCESS) {
266 return Status::fromServiceSpecificError(static_cast<int32_t>(status));
267 }
268 *_aidl_return = ::ndk::SharedRefBase::make<TunerFrontend>(frontend, id);
269 return Status::ok();
270}
271
272Status TunerService::getFmqSyncReadWrite(
273 MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) {
274 ALOGD("getFmqSyncReadWrite");
275 // TODO: put the following methods AIDL, and should be called from clients.
276 openDemux();
277 openFilter();
278 configFilter();
279 mFilter->start();
280 if (mqDesc == nullptr) {
281 ALOGD("getFmqSyncReadWrite null MQDescriptor.");
282 *_aidl_return = false;
283 } else {
284 ALOGD("getFmqSyncReadWrite true");
285 *_aidl_return = true;
286 *mqDesc = move(mAidlMQDesc);
287 }
288 return ndk::ScopedAStatus::ok();
289}
290
291Status TunerService::openLnb(int lnbHandle, shared_ptr<ITunerLnb>* _aidl_return) {
292 if (mTuner == nullptr) {
293 ALOGE("ITuner service is not init.");
294 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
295 }
296
297 Result status;
298 sp<ILnb> lnb;
299 int id = getResourceIdFromHandle(lnbHandle, LNB);
300 mTuner->openLnbById(id, [&](Result result, const sp<ILnb>& lnbSp){
301 lnb = lnbSp;
302 status = result;
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, id);
309 return Status::ok();
310}
311
312Status TunerService::openLnbByName(const string& lnbName, shared_ptr<ITunerLnb>* _aidl_return) {
313 if (mTuner == nullptr) {
314 ALOGE("ITuner service is not init.");
315 return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
316 }
317
318 int lnbId;
319 Result status;
320 sp<ILnb> lnb;
321 mTuner->openLnbByName(lnbName, [&](Result r, LnbId id, const sp<ILnb>& lnbSp) {
322 status = r;
323 lnb = lnbSp;
324 lnbId = (int)id;
325 });
326 if (status != Result::SUCCESS) {
327 return Status::fromServiceSpecificError(static_cast<int32_t>(status));
328 }
329
330 *_aidl_return = ::ndk::SharedRefBase::make<TunerLnb>(lnb, lnbId);
Amy Zhang0f04c452020-10-30 13:36:44 -0700331 return Status::ok();
Amy Zhang70de35a2020-10-12 20:13:16 -0700332}
333
Amy Zhang1d28bbb2021-01-13 18:11:15 -0800334TunerFrontendInfo TunerService::convertToAidlFrontendInfo(FrontendInfo halInfo) {
335 TunerFrontendInfo info{
Amy Zhang70de35a2020-10-12 20:13:16 -0700336 .type = (int)halInfo.type,
337 .minFrequency = (int)halInfo.minFrequency,
338 .maxFrequency = (int)halInfo.maxFrequency,
339 .minSymbolRate = (int)halInfo.minSymbolRate,
340 .maxSymbolRate = (int)halInfo.maxSymbolRate,
341 .acquireRange = (int)halInfo.acquireRange,
342 .exclusiveGroupId = (int)halInfo.exclusiveGroupId,
343 };
344 for (int i = 0; i < halInfo.statusCaps.size(); i++) {
345 info.statusCaps.push_back((int)halInfo.statusCaps[i]);
346 }
347
348 TunerFrontendCapabilities caps;
349 switch (halInfo.type) {
350 case FrontendType::ANALOG: {
351 TunerFrontendAnalogCapabilities analogCaps{
352 .typeCap = (int)halInfo.frontendCaps.analogCaps().typeCap,
353 .sifStandardCap = (int)halInfo.frontendCaps.analogCaps().sifStandardCap,
354 };
355 caps.set<TunerFrontendCapabilities::analogCaps>(analogCaps);
356 break;
357 }
358 case FrontendType::ATSC: {
359 TunerFrontendAtscCapabilities atscCaps{
360 .modulationCap = (int)halInfo.frontendCaps.atscCaps().modulationCap,
361 };
362 caps.set<TunerFrontendCapabilities::atscCaps>(atscCaps);
363 break;
364 }
365 case FrontendType::ATSC3: {
366 TunerFrontendAtsc3Capabilities atsc3Caps{
367 .bandwidthCap = (int)halInfo.frontendCaps.atsc3Caps().bandwidthCap,
368 .modulationCap = (int)halInfo.frontendCaps.atsc3Caps().modulationCap,
369 .timeInterleaveModeCap =
370 (int)halInfo.frontendCaps.atsc3Caps().timeInterleaveModeCap,
371 .codeRateCap = (int)halInfo.frontendCaps.atsc3Caps().codeRateCap,
372 .demodOutputFormatCap = (int)halInfo.frontendCaps.atsc3Caps().demodOutputFormatCap,
373 .fecCap = (int)halInfo.frontendCaps.atsc3Caps().fecCap,
374 };
375 caps.set<TunerFrontendCapabilities::atsc3Caps>(atsc3Caps);
376 break;
377 }
378 case FrontendType::DVBC: {
379 TunerFrontendCableCapabilities cableCaps{
380 .modulationCap = (int)halInfo.frontendCaps.dvbcCaps().modulationCap,
381 .codeRateCap = (int)halInfo.frontendCaps.dvbcCaps().fecCap,
382 .annexCap = (int)halInfo.frontendCaps.dvbcCaps().annexCap,
383 };
384 caps.set<TunerFrontendCapabilities::cableCaps>(cableCaps);
385 break;
386 }
387 case FrontendType::DVBS: {
388 TunerFrontendDvbsCapabilities dvbsCaps{
389 .modulationCap = (int)halInfo.frontendCaps.dvbsCaps().modulationCap,
390 .codeRateCap = (long)halInfo.frontendCaps.dvbsCaps().innerfecCap,
391 .standard = (int)halInfo.frontendCaps.dvbsCaps().standard,
392 };
393 caps.set<TunerFrontendCapabilities::dvbsCaps>(dvbsCaps);
394 break;
395 }
396 case FrontendType::DVBT: {
397 TunerFrontendDvbtCapabilities dvbtCaps{
398 .transmissionModeCap = (int)halInfo.frontendCaps.dvbtCaps().transmissionModeCap,
399 .bandwidthCap = (int)halInfo.frontendCaps.dvbtCaps().bandwidthCap,
400 .constellationCap = (int)halInfo.frontendCaps.dvbtCaps().constellationCap,
401 .codeRateCap = (int)halInfo.frontendCaps.dvbtCaps().coderateCap,
402 .hierarchyCap = (int)halInfo.frontendCaps.dvbtCaps().hierarchyCap,
403 .guardIntervalCap = (int)halInfo.frontendCaps.dvbtCaps().guardIntervalCap,
404 .isT2Supported = (bool)halInfo.frontendCaps.dvbtCaps().isT2Supported,
405 .isMisoSupported = (bool)halInfo.frontendCaps.dvbtCaps().isMisoSupported,
406 };
407 caps.set<TunerFrontendCapabilities::dvbtCaps>(dvbtCaps);
408 break;
409 }
410 case FrontendType::ISDBS: {
411 TunerFrontendIsdbsCapabilities isdbsCaps{
412 .modulationCap = (int)halInfo.frontendCaps.isdbsCaps().modulationCap,
413 .codeRateCap = (int)halInfo.frontendCaps.isdbsCaps().coderateCap,
414 };
415 caps.set<TunerFrontendCapabilities::isdbsCaps>(isdbsCaps);
416 break;
417 }
418 case FrontendType::ISDBS3: {
419 TunerFrontendIsdbs3Capabilities isdbs3Caps{
420 .modulationCap = (int)halInfo.frontendCaps.isdbs3Caps().modulationCap,
421 .codeRateCap = (int)halInfo.frontendCaps.isdbs3Caps().coderateCap,
422 };
423 caps.set<TunerFrontendCapabilities::isdbs3Caps>(isdbs3Caps);
424 break;
425 }
426 case FrontendType::ISDBT: {
427 TunerFrontendIsdbtCapabilities isdbtCaps{
428 .modeCap = (int)halInfo.frontendCaps.isdbtCaps().modeCap,
429 .bandwidthCap = (int)halInfo.frontendCaps.isdbtCaps().bandwidthCap,
430 .modulationCap = (int)halInfo.frontendCaps.isdbtCaps().modulationCap,
431 .codeRateCap = (int)halInfo.frontendCaps.isdbtCaps().coderateCap,
432 .guardIntervalCap = (int)halInfo.frontendCaps.isdbtCaps().guardIntervalCap,
433 };
434 caps.set<TunerFrontendCapabilities::isdbtCaps>(isdbtCaps);
435 break;
436 }
437 default:
438 break;
439 }
440
441 info.caps = caps;
442 return info;
443}
shubang23aa3ac2020-09-07 18:56:28 -0700444} // namespace android