blob: 7a5fa6ecad2146980d81c3c4e0526fbef2f29c52 [file] [log] [blame]
Hongguang4092f2f2021-07-08 18:49:12 -07001/*
2 * Copyright 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 "android.hardware.tv.tuner-service.example-Tuner"
19
Hongguange423acd2021-07-27 16:56:47 -070020#include <aidl/android/hardware/tv/tuner/Result.h>
Hongguang4092f2f2021-07-08 18:49:12 -070021#include <utils/Log.h>
Hongguange423acd2021-07-27 16:56:47 -070022
Hongguang4092f2f2021-07-08 18:49:12 -070023#include "Demux.h"
24#include "Descrambler.h"
25#include "Frontend.h"
26#include "Lnb.h"
Hongguange423acd2021-07-27 16:56:47 -070027#include "Tuner.h"
Hongguang4092f2f2021-07-08 18:49:12 -070028
29namespace aidl {
30namespace android {
31namespace hardware {
32namespace tv {
33namespace tuner {
34
Hongguang Chenff2c6b02021-08-07 00:12:26 +000035Tuner::Tuner() {}
36
37void Tuner::init() {
Hongguang4092f2f2021-07-08 18:49:12 -070038 // Static Frontends array to maintain local frontends information
39 // Array index matches their FrontendId in the default impl
40 mFrontendSize = 10;
Hongguang Chenff2c6b02021-08-07 00:12:26 +000041 mFrontends[0] = ndk::SharedRefBase::make<Frontend>(FrontendType::ISDBS, 0, this->ref<Tuner>());
42 mFrontends[1] = ndk::SharedRefBase::make<Frontend>(FrontendType::ATSC3, 1, this->ref<Tuner>());
43 mFrontends[2] = ndk::SharedRefBase::make<Frontend>(FrontendType::DVBC, 2, this->ref<Tuner>());
44 mFrontends[3] = ndk::SharedRefBase::make<Frontend>(FrontendType::DVBS, 3, this->ref<Tuner>());
45 mFrontends[4] = ndk::SharedRefBase::make<Frontend>(FrontendType::DVBT, 4, this->ref<Tuner>());
46 mFrontends[5] = ndk::SharedRefBase::make<Frontend>(FrontendType::ISDBT, 5, this->ref<Tuner>());
47 mFrontends[6] = ndk::SharedRefBase::make<Frontend>(FrontendType::ANALOG, 6, this->ref<Tuner>());
48 mFrontends[7] = ndk::SharedRefBase::make<Frontend>(FrontendType::ATSC, 7, this->ref<Tuner>());
49 mFrontends[8] = ndk::SharedRefBase::make<Frontend>(FrontendType::ISDBS3, 8, this->ref<Tuner>());
50 mFrontends[9] = ndk::SharedRefBase::make<Frontend>(FrontendType::DTMB, 9, this->ref<Tuner>());
Hongguang4092f2f2021-07-08 18:49:12 -070051
52 vector<FrontendStatusType> statusCaps;
53
54 FrontendCapabilities capsIsdbs;
55 capsIsdbs.set<FrontendCapabilities::Tag::isdbsCaps>(FrontendIsdbsCapabilities());
56 mFrontendCaps[0] = capsIsdbs;
57 statusCaps = {
Hongguang2ecfc392021-11-23 10:29:15 -080058 FrontendStatusType::DEMOD_LOCK,
59 FrontendStatusType::SNR,
60 FrontendStatusType::FEC,
61 FrontendStatusType::MODULATION,
62 FrontendStatusType::MODULATIONS,
63 FrontendStatusType::ROLL_OFF,
64 FrontendStatusType::STREAM_ID_LIST,
Hongguang4092f2f2021-07-08 18:49:12 -070065 };
66 mFrontendStatusCaps[0] = statusCaps;
Hongguang5766ddf2021-12-23 11:40:37 -080067 mMaxUsableFrontends[FrontendType::ISDBS] = 1;
Hongguang4092f2f2021-07-08 18:49:12 -070068
69 FrontendCapabilities capsAtsc3;
70 capsAtsc3.set<FrontendCapabilities::Tag::atsc3Caps>(FrontendAtsc3Capabilities());
71 mFrontendCaps[1] = capsAtsc3;
72 statusCaps = {
73 FrontendStatusType::BER,
74 FrontendStatusType::PER,
75 FrontendStatusType::ATSC3_PLP_INFO,
76 FrontendStatusType::MODULATIONS,
77 FrontendStatusType::BERS,
78 FrontendStatusType::INTERLEAVINGS,
79 FrontendStatusType::BANDWIDTH,
Hongguangd99c82d2022-01-13 12:42:52 -080080 FrontendStatusType::ATSC3_ALL_PLP_INFO,
Hongguang4092f2f2021-07-08 18:49:12 -070081 };
82 mFrontendStatusCaps[1] = statusCaps;
Hongguang5766ddf2021-12-23 11:40:37 -080083 mMaxUsableFrontends[FrontendType::ATSC3] = 1;
Hongguang4092f2f2021-07-08 18:49:12 -070084
85 FrontendCapabilities capsDvbc;
86 capsDvbc.set<FrontendCapabilities::Tag::dvbcCaps>(FrontendDvbcCapabilities());
87 mFrontendCaps[2] = capsDvbc;
88 statusCaps = {
89 FrontendStatusType::PRE_BER, FrontendStatusType::SIGNAL_QUALITY,
90 FrontendStatusType::MODULATION, FrontendStatusType::SPECTRAL,
91 FrontendStatusType::MODULATIONS, FrontendStatusType::CODERATES,
92 FrontendStatusType::INTERLEAVINGS, FrontendStatusType::BANDWIDTH,
93 };
94 mFrontendStatusCaps[2] = statusCaps;
Hongguang5766ddf2021-12-23 11:40:37 -080095 mMaxUsableFrontends[FrontendType::DVBC] = 1;
Hongguang4092f2f2021-07-08 18:49:12 -070096
97 FrontendCapabilities capsDvbs;
98 capsDvbs.set<FrontendCapabilities::Tag::dvbsCaps>(FrontendDvbsCapabilities());
99 mFrontendCaps[3] = capsDvbs;
100 statusCaps = {
101 FrontendStatusType::SIGNAL_STRENGTH, FrontendStatusType::SYMBOL_RATE,
102 FrontendStatusType::MODULATION, FrontendStatusType::MODULATIONS,
103 FrontendStatusType::ROLL_OFF, FrontendStatusType::IS_MISO,
104 };
105 mFrontendStatusCaps[3] = statusCaps;
Hongguang5766ddf2021-12-23 11:40:37 -0800106 mMaxUsableFrontends[FrontendType::DVBS] = 1;
Hongguang4092f2f2021-07-08 18:49:12 -0700107
108 FrontendCapabilities capsDvbt;
109 capsDvbt.set<FrontendCapabilities::Tag::dvbtCaps>(FrontendDvbtCapabilities());
110 mFrontendCaps[4] = capsDvbt;
111 statusCaps = {
112 FrontendStatusType::EWBS,
113 FrontendStatusType::PLP_ID,
114 FrontendStatusType::HIERARCHY,
115 FrontendStatusType::MODULATIONS,
116 FrontendStatusType::BANDWIDTH,
117 FrontendStatusType::GUARD_INTERVAL,
118 FrontendStatusType::TRANSMISSION_MODE,
119 FrontendStatusType::T2_SYSTEM_ID,
Hongguang7eda7822021-12-20 14:48:14 -0800120 FrontendStatusType::DVBT_CELL_IDS,
Hongguang4092f2f2021-07-08 18:49:12 -0700121 };
122 mFrontendStatusCaps[4] = statusCaps;
Hongguang5766ddf2021-12-23 11:40:37 -0800123 mMaxUsableFrontends[FrontendType::DVBT] = 1;
Hongguang4092f2f2021-07-08 18:49:12 -0700124
125 FrontendCapabilities capsIsdbt;
126 FrontendIsdbtCapabilities isdbtCaps{
127 .modeCap = (int)FrontendIsdbtMode::MODE_1 | (int)FrontendIsdbtMode::MODE_2,
128 .bandwidthCap = (int)FrontendIsdbtBandwidth::BANDWIDTH_6MHZ,
129 .modulationCap = (int)FrontendIsdbtModulation::MOD_16QAM,
Hongguange69a3b22021-08-03 14:23:42 -0700130 .coderateCap = (int)FrontendIsdbtCoderate::CODERATE_4_5 |
131 (int)FrontendIsdbtCoderate::CODERATE_6_7,
132 .guardIntervalCap = (int)FrontendIsdbtGuardInterval::INTERVAL_1_128,
Hongguang788284f2021-10-28 15:03:29 -0700133 .timeInterleaveCap = (int)FrontendIsdbtTimeInterleaveMode::AUTO |
134 (int)FrontendIsdbtTimeInterleaveMode::INTERLEAVE_1_0,
135 .isSegmentAuto = true,
136 .isFullSegment = true,
Hongguang4092f2f2021-07-08 18:49:12 -0700137 };
138 capsIsdbt.set<FrontendCapabilities::Tag::isdbtCaps>(isdbtCaps);
139 mFrontendCaps[5] = capsIsdbt;
140 statusCaps = {
141 FrontendStatusType::AGC,
142 FrontendStatusType::LNA,
143 FrontendStatusType::MODULATION,
144 FrontendStatusType::MODULATIONS,
145 FrontendStatusType::BANDWIDTH,
146 FrontendStatusType::GUARD_INTERVAL,
147 FrontendStatusType::TRANSMISSION_MODE,
148 FrontendStatusType::ISDBT_SEGMENTS,
Hongguang788284f2021-10-28 15:03:29 -0700149 FrontendStatusType::ISDBT_MODE,
150 FrontendStatusType::ISDBT_PARTIAL_RECEPTION_FLAG,
151 FrontendStatusType::INTERLEAVINGS,
Hongguang4092f2f2021-07-08 18:49:12 -0700152 };
153 mFrontendStatusCaps[5] = statusCaps;
Hongguang5766ddf2021-12-23 11:40:37 -0800154 mMaxUsableFrontends[FrontendType::ISDBT] = 1;
Hongguang4092f2f2021-07-08 18:49:12 -0700155
156 FrontendCapabilities capsAnalog;
157 capsAnalog.set<FrontendCapabilities::Tag::analogCaps>(FrontendAnalogCapabilities());
158 mFrontendCaps[6] = capsAnalog;
159 statusCaps = {
160 FrontendStatusType::LAYER_ERROR,
161 FrontendStatusType::MER,
162 FrontendStatusType::UEC,
163 FrontendStatusType::TS_DATA_RATES,
164 };
165 mFrontendStatusCaps[6] = statusCaps;
Hongguang5766ddf2021-12-23 11:40:37 -0800166 mMaxUsableFrontends[FrontendType::ANALOG] = 1;
Hongguang4092f2f2021-07-08 18:49:12 -0700167
168 FrontendCapabilities capsAtsc;
169 capsAtsc.set<FrontendCapabilities::Tag::atscCaps>(FrontendAtscCapabilities());
170 mFrontendCaps[7] = capsAtsc;
171 statusCaps = {
172 FrontendStatusType::FREQ_OFFSET,
173 FrontendStatusType::RF_LOCK,
174 FrontendStatusType::MODULATIONS,
175 FrontendStatusType::IS_LINEAR,
176 };
177 mFrontendStatusCaps[7] = statusCaps;
Hongguang5766ddf2021-12-23 11:40:37 -0800178 mMaxUsableFrontends[FrontendType::ATSC] = 1;
Hongguang4092f2f2021-07-08 18:49:12 -0700179
180 FrontendCapabilities capsIsdbs3;
181 capsIsdbs3.set<FrontendCapabilities::Tag::isdbs3Caps>(FrontendIsdbs3Capabilities());
182 mFrontendCaps[8] = capsIsdbs3;
183 statusCaps = {
184 FrontendStatusType::DEMOD_LOCK, FrontendStatusType::MODULATION,
185 FrontendStatusType::MODULATIONS, FrontendStatusType::ROLL_OFF,
Hongguang2ecfc392021-11-23 10:29:15 -0800186 FrontendStatusType::IS_SHORT_FRAMES, FrontendStatusType::STREAM_ID_LIST,
Hongguang4092f2f2021-07-08 18:49:12 -0700187 };
188 mFrontendStatusCaps[8] = statusCaps;
Hongguang5766ddf2021-12-23 11:40:37 -0800189 mMaxUsableFrontends[FrontendType::ISDBS3] = 1;
Hongguang4092f2f2021-07-08 18:49:12 -0700190
191 FrontendCapabilities capsDtmb;
192 capsDtmb.set<FrontendCapabilities::Tag::dtmbCaps>(FrontendDtmbCapabilities());
193 mFrontendCaps[9] = capsDtmb;
194 statusCaps = {
195 FrontendStatusType::MODULATIONS, FrontendStatusType::INTERLEAVINGS,
196 FrontendStatusType::BANDWIDTH, FrontendStatusType::GUARD_INTERVAL,
197 FrontendStatusType::TRANSMISSION_MODE,
198 };
199 mFrontendStatusCaps[9] = statusCaps;
Hongguang5766ddf2021-12-23 11:40:37 -0800200 mMaxUsableFrontends[FrontendType::DTMB] = 1;
Hongguang4092f2f2021-07-08 18:49:12 -0700201
202 mLnbs.resize(2);
203 mLnbs[0] = ndk::SharedRefBase::make<Lnb>(0);
204 mLnbs[1] = ndk::SharedRefBase::make<Lnb>(1);
205}
206
207Tuner::~Tuner() {}
208
209::ndk::ScopedAStatus Tuner::getFrontendIds(std::vector<int32_t>* _aidl_return) {
210 ALOGV("%s", __FUNCTION__);
211
212 _aidl_return->resize(mFrontendSize);
213 for (int i = 0; i < mFrontendSize; i++) {
214 (*_aidl_return)[i] = mFrontends[i]->getFrontendId();
215 }
216
217 return ::ndk::ScopedAStatus::ok();
218}
219
220::ndk::ScopedAStatus Tuner::openFrontendById(int32_t in_frontendId,
221 std::shared_ptr<IFrontend>* _aidl_return) {
222 ALOGV("%s", __FUNCTION__);
223
224 if (in_frontendId >= mFrontendSize || in_frontendId < 0) {
225 ALOGW("[ WARN ] Frontend with id %d isn't available", in_frontendId);
226 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700227 return ::ndk::ScopedAStatus::fromServiceSpecificError(
228 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700229 }
230
231 *_aidl_return = mFrontends[in_frontendId];
232 return ::ndk::ScopedAStatus::ok();
233}
234
235::ndk::ScopedAStatus Tuner::openDemux(std::vector<int32_t>* out_demuxId,
236 std::shared_ptr<IDemux>* _aidl_return) {
237 ALOGV("%s", __FUNCTION__);
238
239 mLastUsedId += 1;
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000240 mDemuxes[mLastUsedId] = ndk::SharedRefBase::make<Demux>(mLastUsedId, this->ref<Tuner>());
Hongguang4092f2f2021-07-08 18:49:12 -0700241
242 out_demuxId->push_back(mLastUsedId);
243 *_aidl_return = mDemuxes[mLastUsedId];
244
245 return ::ndk::ScopedAStatus::ok();
246}
247
248::ndk::ScopedAStatus Tuner::getDemuxCaps(DemuxCapabilities* _aidl_return) {
249 ALOGV("%s", __FUNCTION__);
250
251 // IP filter can be an MMTP filter's data source.
252 _aidl_return->linkCaps = {0x00, 0x00, 0x02, 0x00, 0x00};
253 // Support time filter testing
254 _aidl_return->bTimeFilter = true;
255
256 return ::ndk::ScopedAStatus::ok();
257}
258
259::ndk::ScopedAStatus Tuner::openDescrambler(std::shared_ptr<IDescrambler>* _aidl_return) {
260 ALOGV("%s", __FUNCTION__);
261
262 *_aidl_return = ndk::SharedRefBase::make<Descrambler>();
263
264 return ndk::ScopedAStatus::ok();
265}
266
267::ndk::ScopedAStatus Tuner::getFrontendInfo(int32_t in_frontendId, FrontendInfo* _aidl_return) {
268 ALOGV("%s", __FUNCTION__);
269
270 if (in_frontendId >= mFrontendSize) {
Hongguange423acd2021-07-27 16:56:47 -0700271 return ::ndk::ScopedAStatus::fromServiceSpecificError(
272 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700273 }
274
275 // assign randomly selected values for testing.
276 *_aidl_return = {
277 .type = mFrontends[in_frontendId]->getFrontendType(),
Gareth Fenn282fb372021-09-27 15:14:11 +0100278 .minFrequency = 139000000,
279 .maxFrequency = 1139000000,
Hongguang4092f2f2021-07-08 18:49:12 -0700280 .minSymbolRate = 45,
281 .maxSymbolRate = 1145,
282 .acquireRange = 30,
283 .exclusiveGroupId = 57,
284 .statusCaps = mFrontendStatusCaps[in_frontendId],
285 .frontendCaps = mFrontendCaps[in_frontendId],
286 };
287
288 return ::ndk::ScopedAStatus::ok();
289}
290
291::ndk::ScopedAStatus Tuner::getLnbIds(std::vector<int32_t>* _aidl_return) {
292 ALOGV("%s", __FUNCTION__);
293
294 _aidl_return->resize(mLnbs.size());
295 for (int i = 0; i < mLnbs.size(); i++) {
296 (*_aidl_return)[i] = mLnbs[i]->getId();
297 }
298
299 return ::ndk::ScopedAStatus::ok();
300}
301
302::ndk::ScopedAStatus Tuner::openLnbById(int32_t in_lnbId, std::shared_ptr<ILnb>* _aidl_return) {
303 ALOGV("%s", __FUNCTION__);
304
305 if (in_lnbId >= mLnbs.size()) {
306 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700307 return ::ndk::ScopedAStatus::fromServiceSpecificError(
308 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700309 }
310
311 *_aidl_return = mLnbs[in_lnbId];
312 return ::ndk::ScopedAStatus::ok();
313}
314
315std::shared_ptr<Frontend> Tuner::getFrontendById(int32_t frontendId) {
316 ALOGV("%s", __FUNCTION__);
317
318 return mFrontends[frontendId];
319}
320
321::ndk::ScopedAStatus Tuner::openLnbByName(const std::string& /* in_lnbName */,
322 std::vector<int32_t>* out_lnbId,
323 std::shared_ptr<ILnb>* _aidl_return) {
324 ALOGV("%s", __FUNCTION__);
325
326 out_lnbId->push_back(1234);
327 *_aidl_return = ndk::SharedRefBase::make<Lnb>();
328
329 return ::ndk::ScopedAStatus::ok();
330}
331
Hongguangfcedda02021-12-13 17:08:02 -0800332::ndk::ScopedAStatus Tuner::setLna(bool /* in_bEnable */) {
333 ALOGV("%s", __FUNCTION__);
334
335 return ::ndk::ScopedAStatus::ok();
336}
337
Hongguang5766ddf2021-12-23 11:40:37 -0800338::ndk::ScopedAStatus Tuner::setMaxNumberOfFrontends(FrontendType in_frontendType,
339 int32_t in_maxNumber) {
340 ALOGV("%s", __FUNCTION__);
341
342 // In the default implementation, every type only has one frontend.
343 if (in_maxNumber < 0 || in_maxNumber > 1) {
344 return ::ndk::ScopedAStatus::fromServiceSpecificError(
345 static_cast<int32_t>(Result::INVALID_ARGUMENT));
346 }
347 mMaxUsableFrontends[in_frontendType] = in_maxNumber;
348 return ::ndk::ScopedAStatus::ok();
349}
350
351::ndk::ScopedAStatus Tuner::getMaxNumberOfFrontends(FrontendType in_frontendType,
352 int32_t* _aidl_return) {
353 *_aidl_return = mMaxUsableFrontends[in_frontendType];
354 return ::ndk::ScopedAStatus::ok();
355}
356
Hongguang2ecfc392021-11-23 10:29:15 -0800357binder_status_t Tuner::dump(int fd, const char** args, uint32_t numArgs) {
358 ALOGV("%s", __FUNCTION__);
359 {
360 dprintf(fd, "Frontends:\n");
361 for (int i = 0; i < mFrontendSize; i++) {
362 mFrontends[i]->dump(fd, args, numArgs);
363 for (int j = 0; j < mFrontendStatusCaps[i].size(); j++) {
364 dprintf(fd, " statusCap: %d\n", mFrontendStatusCaps[i][j]);
365 }
366 }
367 }
368 {
369 dprintf(fd, "Demuxs:\n");
370 map<int32_t, std::shared_ptr<Demux>>::iterator it;
371 for (it = mDemuxes.begin(); it != mDemuxes.end(); it++) {
372 it->second->dump(fd, args, numArgs);
373 }
374 }
375 {
376 dprintf(fd, "Lnbs:\n");
377 for (int i = 0; i < mLnbs.size(); i++) {
378 mLnbs[i]->dump(fd, args, numArgs);
379 }
380 }
381 return STATUS_OK;
382}
383
Hongguang4092f2f2021-07-08 18:49:12 -0700384void Tuner::setFrontendAsDemuxSource(int32_t frontendId, int32_t demuxId) {
385 mFrontendToDemux[frontendId] = demuxId;
386 if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) {
387 mDemuxes[demuxId]->startFrontendInputLoop();
388 }
389}
390
391void Tuner::removeDemux(int32_t demuxId) {
392 map<int32_t, int32_t>::iterator it;
393 for (it = mFrontendToDemux.begin(); it != mFrontendToDemux.end(); it++) {
394 if (it->second == demuxId) {
395 it = mFrontendToDemux.erase(it);
396 break;
397 }
398 }
399 mDemuxes.erase(demuxId);
400}
401
402void Tuner::removeFrontend(int32_t frontendId) {
Hongguang2ecfc392021-11-23 10:29:15 -0800403 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
404 if (it != mFrontendToDemux.end()) {
405 mDemuxes.erase(it->second);
406 }
Hongguang4092f2f2021-07-08 18:49:12 -0700407 mFrontendToDemux.erase(frontendId);
408}
409
410void Tuner::frontendStopTune(int32_t frontendId) {
411 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
412 int32_t demuxId;
413 if (it != mFrontendToDemux.end()) {
414 demuxId = it->second;
415 mDemuxes[demuxId]->stopFrontendInput();
416 }
417}
418
419void Tuner::frontendStartTune(int32_t frontendId) {
420 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
421 int32_t demuxId;
422 if (it != mFrontendToDemux.end()) {
423 demuxId = it->second;
424 mDemuxes[demuxId]->startFrontendInputLoop();
425 }
426}
427
428} // namespace tuner
429} // namespace tv
430} // namespace hardware
431} // namespace android
432} // namespace aidl