blob: fbf4763af91e98ad130ba59342d177caea1021ec [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;
67
68 FrontendCapabilities capsAtsc3;
69 capsAtsc3.set<FrontendCapabilities::Tag::atsc3Caps>(FrontendAtsc3Capabilities());
70 mFrontendCaps[1] = capsAtsc3;
71 statusCaps = {
72 FrontendStatusType::BER,
73 FrontendStatusType::PER,
74 FrontendStatusType::ATSC3_PLP_INFO,
75 FrontendStatusType::MODULATIONS,
76 FrontendStatusType::BERS,
77 FrontendStatusType::INTERLEAVINGS,
78 FrontendStatusType::BANDWIDTH,
79 };
80 mFrontendStatusCaps[1] = statusCaps;
81
82 FrontendCapabilities capsDvbc;
83 capsDvbc.set<FrontendCapabilities::Tag::dvbcCaps>(FrontendDvbcCapabilities());
84 mFrontendCaps[2] = capsDvbc;
85 statusCaps = {
86 FrontendStatusType::PRE_BER, FrontendStatusType::SIGNAL_QUALITY,
87 FrontendStatusType::MODULATION, FrontendStatusType::SPECTRAL,
88 FrontendStatusType::MODULATIONS, FrontendStatusType::CODERATES,
89 FrontendStatusType::INTERLEAVINGS, FrontendStatusType::BANDWIDTH,
90 };
91 mFrontendStatusCaps[2] = statusCaps;
92
93 FrontendCapabilities capsDvbs;
94 capsDvbs.set<FrontendCapabilities::Tag::dvbsCaps>(FrontendDvbsCapabilities());
95 mFrontendCaps[3] = capsDvbs;
96 statusCaps = {
97 FrontendStatusType::SIGNAL_STRENGTH, FrontendStatusType::SYMBOL_RATE,
98 FrontendStatusType::MODULATION, FrontendStatusType::MODULATIONS,
99 FrontendStatusType::ROLL_OFF, FrontendStatusType::IS_MISO,
100 };
101 mFrontendStatusCaps[3] = statusCaps;
102
103 FrontendCapabilities capsDvbt;
104 capsDvbt.set<FrontendCapabilities::Tag::dvbtCaps>(FrontendDvbtCapabilities());
105 mFrontendCaps[4] = capsDvbt;
106 statusCaps = {
107 FrontendStatusType::EWBS,
108 FrontendStatusType::PLP_ID,
109 FrontendStatusType::HIERARCHY,
110 FrontendStatusType::MODULATIONS,
111 FrontendStatusType::BANDWIDTH,
112 FrontendStatusType::GUARD_INTERVAL,
113 FrontendStatusType::TRANSMISSION_MODE,
114 FrontendStatusType::T2_SYSTEM_ID,
115 };
116 mFrontendStatusCaps[4] = statusCaps;
117
118 FrontendCapabilities capsIsdbt;
119 FrontendIsdbtCapabilities isdbtCaps{
120 .modeCap = (int)FrontendIsdbtMode::MODE_1 | (int)FrontendIsdbtMode::MODE_2,
121 .bandwidthCap = (int)FrontendIsdbtBandwidth::BANDWIDTH_6MHZ,
122 .modulationCap = (int)FrontendIsdbtModulation::MOD_16QAM,
Hongguange69a3b22021-08-03 14:23:42 -0700123 .coderateCap = (int)FrontendIsdbtCoderate::CODERATE_4_5 |
124 (int)FrontendIsdbtCoderate::CODERATE_6_7,
125 .guardIntervalCap = (int)FrontendIsdbtGuardInterval::INTERVAL_1_128,
Hongguang788284f2021-10-28 15:03:29 -0700126 .timeInterleaveCap = (int)FrontendIsdbtTimeInterleaveMode::AUTO |
127 (int)FrontendIsdbtTimeInterleaveMode::INTERLEAVE_1_0,
128 .isSegmentAuto = true,
129 .isFullSegment = true,
Hongguang4092f2f2021-07-08 18:49:12 -0700130 };
131 capsIsdbt.set<FrontendCapabilities::Tag::isdbtCaps>(isdbtCaps);
132 mFrontendCaps[5] = capsIsdbt;
133 statusCaps = {
134 FrontendStatusType::AGC,
135 FrontendStatusType::LNA,
136 FrontendStatusType::MODULATION,
137 FrontendStatusType::MODULATIONS,
138 FrontendStatusType::BANDWIDTH,
139 FrontendStatusType::GUARD_INTERVAL,
140 FrontendStatusType::TRANSMISSION_MODE,
141 FrontendStatusType::ISDBT_SEGMENTS,
Hongguang788284f2021-10-28 15:03:29 -0700142 FrontendStatusType::ISDBT_MODE,
143 FrontendStatusType::ISDBT_PARTIAL_RECEPTION_FLAG,
144 FrontendStatusType::INTERLEAVINGS,
Hongguang4092f2f2021-07-08 18:49:12 -0700145 };
146 mFrontendStatusCaps[5] = statusCaps;
147
148 FrontendCapabilities capsAnalog;
149 capsAnalog.set<FrontendCapabilities::Tag::analogCaps>(FrontendAnalogCapabilities());
150 mFrontendCaps[6] = capsAnalog;
151 statusCaps = {
152 FrontendStatusType::LAYER_ERROR,
153 FrontendStatusType::MER,
154 FrontendStatusType::UEC,
155 FrontendStatusType::TS_DATA_RATES,
156 };
157 mFrontendStatusCaps[6] = statusCaps;
158
159 FrontendCapabilities capsAtsc;
160 capsAtsc.set<FrontendCapabilities::Tag::atscCaps>(FrontendAtscCapabilities());
161 mFrontendCaps[7] = capsAtsc;
162 statusCaps = {
163 FrontendStatusType::FREQ_OFFSET,
164 FrontendStatusType::RF_LOCK,
165 FrontendStatusType::MODULATIONS,
166 FrontendStatusType::IS_LINEAR,
167 };
168 mFrontendStatusCaps[7] = statusCaps;
169
170 FrontendCapabilities capsIsdbs3;
171 capsIsdbs3.set<FrontendCapabilities::Tag::isdbs3Caps>(FrontendIsdbs3Capabilities());
172 mFrontendCaps[8] = capsIsdbs3;
173 statusCaps = {
174 FrontendStatusType::DEMOD_LOCK, FrontendStatusType::MODULATION,
175 FrontendStatusType::MODULATIONS, FrontendStatusType::ROLL_OFF,
Hongguang2ecfc392021-11-23 10:29:15 -0800176 FrontendStatusType::IS_SHORT_FRAMES, FrontendStatusType::STREAM_ID_LIST,
Hongguang4092f2f2021-07-08 18:49:12 -0700177 };
178 mFrontendStatusCaps[8] = statusCaps;
179
180 FrontendCapabilities capsDtmb;
181 capsDtmb.set<FrontendCapabilities::Tag::dtmbCaps>(FrontendDtmbCapabilities());
182 mFrontendCaps[9] = capsDtmb;
183 statusCaps = {
184 FrontendStatusType::MODULATIONS, FrontendStatusType::INTERLEAVINGS,
185 FrontendStatusType::BANDWIDTH, FrontendStatusType::GUARD_INTERVAL,
186 FrontendStatusType::TRANSMISSION_MODE,
187 };
188 mFrontendStatusCaps[9] = statusCaps;
189
190 mLnbs.resize(2);
191 mLnbs[0] = ndk::SharedRefBase::make<Lnb>(0);
192 mLnbs[1] = ndk::SharedRefBase::make<Lnb>(1);
193}
194
195Tuner::~Tuner() {}
196
197::ndk::ScopedAStatus Tuner::getFrontendIds(std::vector<int32_t>* _aidl_return) {
198 ALOGV("%s", __FUNCTION__);
199
200 _aidl_return->resize(mFrontendSize);
201 for (int i = 0; i < mFrontendSize; i++) {
202 (*_aidl_return)[i] = mFrontends[i]->getFrontendId();
203 }
204
205 return ::ndk::ScopedAStatus::ok();
206}
207
208::ndk::ScopedAStatus Tuner::openFrontendById(int32_t in_frontendId,
209 std::shared_ptr<IFrontend>* _aidl_return) {
210 ALOGV("%s", __FUNCTION__);
211
212 if (in_frontendId >= mFrontendSize || in_frontendId < 0) {
213 ALOGW("[ WARN ] Frontend with id %d isn't available", in_frontendId);
214 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700215 return ::ndk::ScopedAStatus::fromServiceSpecificError(
216 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700217 }
218
219 *_aidl_return = mFrontends[in_frontendId];
220 return ::ndk::ScopedAStatus::ok();
221}
222
223::ndk::ScopedAStatus Tuner::openDemux(std::vector<int32_t>* out_demuxId,
224 std::shared_ptr<IDemux>* _aidl_return) {
225 ALOGV("%s", __FUNCTION__);
226
227 mLastUsedId += 1;
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000228 mDemuxes[mLastUsedId] = ndk::SharedRefBase::make<Demux>(mLastUsedId, this->ref<Tuner>());
Hongguang4092f2f2021-07-08 18:49:12 -0700229
230 out_demuxId->push_back(mLastUsedId);
231 *_aidl_return = mDemuxes[mLastUsedId];
232
233 return ::ndk::ScopedAStatus::ok();
234}
235
236::ndk::ScopedAStatus Tuner::getDemuxCaps(DemuxCapabilities* _aidl_return) {
237 ALOGV("%s", __FUNCTION__);
238
239 // IP filter can be an MMTP filter's data source.
240 _aidl_return->linkCaps = {0x00, 0x00, 0x02, 0x00, 0x00};
241 // Support time filter testing
242 _aidl_return->bTimeFilter = true;
243
244 return ::ndk::ScopedAStatus::ok();
245}
246
247::ndk::ScopedAStatus Tuner::openDescrambler(std::shared_ptr<IDescrambler>* _aidl_return) {
248 ALOGV("%s", __FUNCTION__);
249
250 *_aidl_return = ndk::SharedRefBase::make<Descrambler>();
251
252 return ndk::ScopedAStatus::ok();
253}
254
255::ndk::ScopedAStatus Tuner::getFrontendInfo(int32_t in_frontendId, FrontendInfo* _aidl_return) {
256 ALOGV("%s", __FUNCTION__);
257
258 if (in_frontendId >= mFrontendSize) {
Hongguange423acd2021-07-27 16:56:47 -0700259 return ::ndk::ScopedAStatus::fromServiceSpecificError(
260 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700261 }
262
263 // assign randomly selected values for testing.
264 *_aidl_return = {
265 .type = mFrontends[in_frontendId]->getFrontendType(),
Gareth Fenn282fb372021-09-27 15:14:11 +0100266 .minFrequency = 139000000,
267 .maxFrequency = 1139000000,
Hongguang4092f2f2021-07-08 18:49:12 -0700268 .minSymbolRate = 45,
269 .maxSymbolRate = 1145,
270 .acquireRange = 30,
271 .exclusiveGroupId = 57,
272 .statusCaps = mFrontendStatusCaps[in_frontendId],
273 .frontendCaps = mFrontendCaps[in_frontendId],
274 };
275
276 return ::ndk::ScopedAStatus::ok();
277}
278
279::ndk::ScopedAStatus Tuner::getLnbIds(std::vector<int32_t>* _aidl_return) {
280 ALOGV("%s", __FUNCTION__);
281
282 _aidl_return->resize(mLnbs.size());
283 for (int i = 0; i < mLnbs.size(); i++) {
284 (*_aidl_return)[i] = mLnbs[i]->getId();
285 }
286
287 return ::ndk::ScopedAStatus::ok();
288}
289
290::ndk::ScopedAStatus Tuner::openLnbById(int32_t in_lnbId, std::shared_ptr<ILnb>* _aidl_return) {
291 ALOGV("%s", __FUNCTION__);
292
293 if (in_lnbId >= mLnbs.size()) {
294 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700295 return ::ndk::ScopedAStatus::fromServiceSpecificError(
296 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700297 }
298
299 *_aidl_return = mLnbs[in_lnbId];
300 return ::ndk::ScopedAStatus::ok();
301}
302
303std::shared_ptr<Frontend> Tuner::getFrontendById(int32_t frontendId) {
304 ALOGV("%s", __FUNCTION__);
305
306 return mFrontends[frontendId];
307}
308
309::ndk::ScopedAStatus Tuner::openLnbByName(const std::string& /* in_lnbName */,
310 std::vector<int32_t>* out_lnbId,
311 std::shared_ptr<ILnb>* _aidl_return) {
312 ALOGV("%s", __FUNCTION__);
313
314 out_lnbId->push_back(1234);
315 *_aidl_return = ndk::SharedRefBase::make<Lnb>();
316
317 return ::ndk::ScopedAStatus::ok();
318}
319
Hongguangfcedda02021-12-13 17:08:02 -0800320::ndk::ScopedAStatus Tuner::setLna(bool /* in_bEnable */) {
321 ALOGV("%s", __FUNCTION__);
322
323 return ::ndk::ScopedAStatus::ok();
324}
325
Hongguang2ecfc392021-11-23 10:29:15 -0800326binder_status_t Tuner::dump(int fd, const char** args, uint32_t numArgs) {
327 ALOGV("%s", __FUNCTION__);
328 {
329 dprintf(fd, "Frontends:\n");
330 for (int i = 0; i < mFrontendSize; i++) {
331 mFrontends[i]->dump(fd, args, numArgs);
332 for (int j = 0; j < mFrontendStatusCaps[i].size(); j++) {
333 dprintf(fd, " statusCap: %d\n", mFrontendStatusCaps[i][j]);
334 }
335 }
336 }
337 {
338 dprintf(fd, "Demuxs:\n");
339 map<int32_t, std::shared_ptr<Demux>>::iterator it;
340 for (it = mDemuxes.begin(); it != mDemuxes.end(); it++) {
341 it->second->dump(fd, args, numArgs);
342 }
343 }
344 {
345 dprintf(fd, "Lnbs:\n");
346 for (int i = 0; i < mLnbs.size(); i++) {
347 mLnbs[i]->dump(fd, args, numArgs);
348 }
349 }
350 return STATUS_OK;
351}
352
Hongguang4092f2f2021-07-08 18:49:12 -0700353void Tuner::setFrontendAsDemuxSource(int32_t frontendId, int32_t demuxId) {
354 mFrontendToDemux[frontendId] = demuxId;
355 if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) {
356 mDemuxes[demuxId]->startFrontendInputLoop();
357 }
358}
359
360void Tuner::removeDemux(int32_t demuxId) {
361 map<int32_t, int32_t>::iterator it;
362 for (it = mFrontendToDemux.begin(); it != mFrontendToDemux.end(); it++) {
363 if (it->second == demuxId) {
364 it = mFrontendToDemux.erase(it);
365 break;
366 }
367 }
368 mDemuxes.erase(demuxId);
369}
370
371void Tuner::removeFrontend(int32_t frontendId) {
Hongguang2ecfc392021-11-23 10:29:15 -0800372 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
373 if (it != mFrontendToDemux.end()) {
374 mDemuxes.erase(it->second);
375 }
Hongguang4092f2f2021-07-08 18:49:12 -0700376 mFrontendToDemux.erase(frontendId);
377}
378
379void Tuner::frontendStopTune(int32_t frontendId) {
380 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
381 int32_t demuxId;
382 if (it != mFrontendToDemux.end()) {
383 demuxId = it->second;
384 mDemuxes[demuxId]->stopFrontendInput();
385 }
386}
387
388void Tuner::frontendStartTune(int32_t frontendId) {
389 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
390 int32_t demuxId;
391 if (it != mFrontendToDemux.end()) {
392 demuxId = it->second;
393 mDemuxes[demuxId]->startFrontendInputLoop();
394 }
395}
396
397} // namespace tuner
398} // namespace tv
399} // namespace hardware
400} // namespace android
401} // namespace aidl