blob: badb08fb33fa94fe40f8f155d9493a382a65bb0d [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 = {
58 FrontendStatusType::DEMOD_LOCK, FrontendStatusType::SNR,
59 FrontendStatusType::FEC, FrontendStatusType::MODULATION,
60 FrontendStatusType::MODULATIONS, FrontendStatusType::ROLL_OFF,
61 };
62 mFrontendStatusCaps[0] = statusCaps;
63
64 FrontendCapabilities capsAtsc3;
65 capsAtsc3.set<FrontendCapabilities::Tag::atsc3Caps>(FrontendAtsc3Capabilities());
66 mFrontendCaps[1] = capsAtsc3;
67 statusCaps = {
68 FrontendStatusType::BER,
69 FrontendStatusType::PER,
70 FrontendStatusType::ATSC3_PLP_INFO,
71 FrontendStatusType::MODULATIONS,
72 FrontendStatusType::BERS,
73 FrontendStatusType::INTERLEAVINGS,
74 FrontendStatusType::BANDWIDTH,
75 };
76 mFrontendStatusCaps[1] = statusCaps;
77
78 FrontendCapabilities capsDvbc;
79 capsDvbc.set<FrontendCapabilities::Tag::dvbcCaps>(FrontendDvbcCapabilities());
80 mFrontendCaps[2] = capsDvbc;
81 statusCaps = {
82 FrontendStatusType::PRE_BER, FrontendStatusType::SIGNAL_QUALITY,
83 FrontendStatusType::MODULATION, FrontendStatusType::SPECTRAL,
84 FrontendStatusType::MODULATIONS, FrontendStatusType::CODERATES,
85 FrontendStatusType::INTERLEAVINGS, FrontendStatusType::BANDWIDTH,
86 };
87 mFrontendStatusCaps[2] = statusCaps;
88
89 FrontendCapabilities capsDvbs;
90 capsDvbs.set<FrontendCapabilities::Tag::dvbsCaps>(FrontendDvbsCapabilities());
91 mFrontendCaps[3] = capsDvbs;
92 statusCaps = {
93 FrontendStatusType::SIGNAL_STRENGTH, FrontendStatusType::SYMBOL_RATE,
94 FrontendStatusType::MODULATION, FrontendStatusType::MODULATIONS,
95 FrontendStatusType::ROLL_OFF, FrontendStatusType::IS_MISO,
96 };
97 mFrontendStatusCaps[3] = statusCaps;
98
99 FrontendCapabilities capsDvbt;
100 capsDvbt.set<FrontendCapabilities::Tag::dvbtCaps>(FrontendDvbtCapabilities());
101 mFrontendCaps[4] = capsDvbt;
102 statusCaps = {
103 FrontendStatusType::EWBS,
104 FrontendStatusType::PLP_ID,
105 FrontendStatusType::HIERARCHY,
106 FrontendStatusType::MODULATIONS,
107 FrontendStatusType::BANDWIDTH,
108 FrontendStatusType::GUARD_INTERVAL,
109 FrontendStatusType::TRANSMISSION_MODE,
110 FrontendStatusType::T2_SYSTEM_ID,
111 };
112 mFrontendStatusCaps[4] = statusCaps;
113
114 FrontendCapabilities capsIsdbt;
115 FrontendIsdbtCapabilities isdbtCaps{
116 .modeCap = (int)FrontendIsdbtMode::MODE_1 | (int)FrontendIsdbtMode::MODE_2,
117 .bandwidthCap = (int)FrontendIsdbtBandwidth::BANDWIDTH_6MHZ,
118 .modulationCap = (int)FrontendIsdbtModulation::MOD_16QAM,
Hongguange69a3b22021-08-03 14:23:42 -0700119 .coderateCap = (int)FrontendIsdbtCoderate::CODERATE_4_5 |
120 (int)FrontendIsdbtCoderate::CODERATE_6_7,
121 .guardIntervalCap = (int)FrontendIsdbtGuardInterval::INTERVAL_1_128,
Hongguang788284f2021-10-28 15:03:29 -0700122 .timeInterleaveCap = (int)FrontendIsdbtTimeInterleaveMode::AUTO |
123 (int)FrontendIsdbtTimeInterleaveMode::INTERLEAVE_1_0,
124 .isSegmentAuto = true,
125 .isFullSegment = true,
Hongguang4092f2f2021-07-08 18:49:12 -0700126 };
127 capsIsdbt.set<FrontendCapabilities::Tag::isdbtCaps>(isdbtCaps);
128 mFrontendCaps[5] = capsIsdbt;
129 statusCaps = {
130 FrontendStatusType::AGC,
131 FrontendStatusType::LNA,
132 FrontendStatusType::MODULATION,
133 FrontendStatusType::MODULATIONS,
134 FrontendStatusType::BANDWIDTH,
135 FrontendStatusType::GUARD_INTERVAL,
136 FrontendStatusType::TRANSMISSION_MODE,
137 FrontendStatusType::ISDBT_SEGMENTS,
Hongguang788284f2021-10-28 15:03:29 -0700138 FrontendStatusType::ISDBT_MODE,
139 FrontendStatusType::ISDBT_PARTIAL_RECEPTION_FLAG,
140 FrontendStatusType::INTERLEAVINGS,
Hongguang4092f2f2021-07-08 18:49:12 -0700141 };
142 mFrontendStatusCaps[5] = statusCaps;
143
144 FrontendCapabilities capsAnalog;
145 capsAnalog.set<FrontendCapabilities::Tag::analogCaps>(FrontendAnalogCapabilities());
146 mFrontendCaps[6] = capsAnalog;
147 statusCaps = {
148 FrontendStatusType::LAYER_ERROR,
149 FrontendStatusType::MER,
150 FrontendStatusType::UEC,
151 FrontendStatusType::TS_DATA_RATES,
152 };
153 mFrontendStatusCaps[6] = statusCaps;
154
155 FrontendCapabilities capsAtsc;
156 capsAtsc.set<FrontendCapabilities::Tag::atscCaps>(FrontendAtscCapabilities());
157 mFrontendCaps[7] = capsAtsc;
158 statusCaps = {
159 FrontendStatusType::FREQ_OFFSET,
160 FrontendStatusType::RF_LOCK,
161 FrontendStatusType::MODULATIONS,
162 FrontendStatusType::IS_LINEAR,
163 };
164 mFrontendStatusCaps[7] = statusCaps;
165
166 FrontendCapabilities capsIsdbs3;
167 capsIsdbs3.set<FrontendCapabilities::Tag::isdbs3Caps>(FrontendIsdbs3Capabilities());
168 mFrontendCaps[8] = capsIsdbs3;
169 statusCaps = {
170 FrontendStatusType::DEMOD_LOCK, FrontendStatusType::MODULATION,
171 FrontendStatusType::MODULATIONS, FrontendStatusType::ROLL_OFF,
172 FrontendStatusType::IS_SHORT_FRAMES,
173 };
174 mFrontendStatusCaps[8] = statusCaps;
175
176 FrontendCapabilities capsDtmb;
177 capsDtmb.set<FrontendCapabilities::Tag::dtmbCaps>(FrontendDtmbCapabilities());
178 mFrontendCaps[9] = capsDtmb;
179 statusCaps = {
180 FrontendStatusType::MODULATIONS, FrontendStatusType::INTERLEAVINGS,
181 FrontendStatusType::BANDWIDTH, FrontendStatusType::GUARD_INTERVAL,
182 FrontendStatusType::TRANSMISSION_MODE,
183 };
184 mFrontendStatusCaps[9] = statusCaps;
185
186 mLnbs.resize(2);
187 mLnbs[0] = ndk::SharedRefBase::make<Lnb>(0);
188 mLnbs[1] = ndk::SharedRefBase::make<Lnb>(1);
189}
190
191Tuner::~Tuner() {}
192
193::ndk::ScopedAStatus Tuner::getFrontendIds(std::vector<int32_t>* _aidl_return) {
194 ALOGV("%s", __FUNCTION__);
195
196 _aidl_return->resize(mFrontendSize);
197 for (int i = 0; i < mFrontendSize; i++) {
198 (*_aidl_return)[i] = mFrontends[i]->getFrontendId();
199 }
200
201 return ::ndk::ScopedAStatus::ok();
202}
203
204::ndk::ScopedAStatus Tuner::openFrontendById(int32_t in_frontendId,
205 std::shared_ptr<IFrontend>* _aidl_return) {
206 ALOGV("%s", __FUNCTION__);
207
208 if (in_frontendId >= mFrontendSize || in_frontendId < 0) {
209 ALOGW("[ WARN ] Frontend with id %d isn't available", in_frontendId);
210 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700211 return ::ndk::ScopedAStatus::fromServiceSpecificError(
212 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700213 }
214
215 *_aidl_return = mFrontends[in_frontendId];
216 return ::ndk::ScopedAStatus::ok();
217}
218
219::ndk::ScopedAStatus Tuner::openDemux(std::vector<int32_t>* out_demuxId,
220 std::shared_ptr<IDemux>* _aidl_return) {
221 ALOGV("%s", __FUNCTION__);
222
223 mLastUsedId += 1;
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000224 mDemuxes[mLastUsedId] = ndk::SharedRefBase::make<Demux>(mLastUsedId, this->ref<Tuner>());
Hongguang4092f2f2021-07-08 18:49:12 -0700225
226 out_demuxId->push_back(mLastUsedId);
227 *_aidl_return = mDemuxes[mLastUsedId];
228
229 return ::ndk::ScopedAStatus::ok();
230}
231
232::ndk::ScopedAStatus Tuner::getDemuxCaps(DemuxCapabilities* _aidl_return) {
233 ALOGV("%s", __FUNCTION__);
234
235 // IP filter can be an MMTP filter's data source.
236 _aidl_return->linkCaps = {0x00, 0x00, 0x02, 0x00, 0x00};
237 // Support time filter testing
238 _aidl_return->bTimeFilter = true;
239
240 return ::ndk::ScopedAStatus::ok();
241}
242
243::ndk::ScopedAStatus Tuner::openDescrambler(std::shared_ptr<IDescrambler>* _aidl_return) {
244 ALOGV("%s", __FUNCTION__);
245
246 *_aidl_return = ndk::SharedRefBase::make<Descrambler>();
247
248 return ndk::ScopedAStatus::ok();
249}
250
251::ndk::ScopedAStatus Tuner::getFrontendInfo(int32_t in_frontendId, FrontendInfo* _aidl_return) {
252 ALOGV("%s", __FUNCTION__);
253
254 if (in_frontendId >= mFrontendSize) {
Hongguange423acd2021-07-27 16:56:47 -0700255 return ::ndk::ScopedAStatus::fromServiceSpecificError(
256 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700257 }
258
259 // assign randomly selected values for testing.
260 *_aidl_return = {
261 .type = mFrontends[in_frontendId]->getFrontendType(),
Gareth Fenn282fb372021-09-27 15:14:11 +0100262 .minFrequency = 139000000,
263 .maxFrequency = 1139000000,
Hongguang4092f2f2021-07-08 18:49:12 -0700264 .minSymbolRate = 45,
265 .maxSymbolRate = 1145,
266 .acquireRange = 30,
267 .exclusiveGroupId = 57,
268 .statusCaps = mFrontendStatusCaps[in_frontendId],
269 .frontendCaps = mFrontendCaps[in_frontendId],
270 };
271
272 return ::ndk::ScopedAStatus::ok();
273}
274
275::ndk::ScopedAStatus Tuner::getLnbIds(std::vector<int32_t>* _aidl_return) {
276 ALOGV("%s", __FUNCTION__);
277
278 _aidl_return->resize(mLnbs.size());
279 for (int i = 0; i < mLnbs.size(); i++) {
280 (*_aidl_return)[i] = mLnbs[i]->getId();
281 }
282
283 return ::ndk::ScopedAStatus::ok();
284}
285
286::ndk::ScopedAStatus Tuner::openLnbById(int32_t in_lnbId, std::shared_ptr<ILnb>* _aidl_return) {
287 ALOGV("%s", __FUNCTION__);
288
289 if (in_lnbId >= mLnbs.size()) {
290 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700291 return ::ndk::ScopedAStatus::fromServiceSpecificError(
292 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700293 }
294
295 *_aidl_return = mLnbs[in_lnbId];
296 return ::ndk::ScopedAStatus::ok();
297}
298
299std::shared_ptr<Frontend> Tuner::getFrontendById(int32_t frontendId) {
300 ALOGV("%s", __FUNCTION__);
301
302 return mFrontends[frontendId];
303}
304
305::ndk::ScopedAStatus Tuner::openLnbByName(const std::string& /* in_lnbName */,
306 std::vector<int32_t>* out_lnbId,
307 std::shared_ptr<ILnb>* _aidl_return) {
308 ALOGV("%s", __FUNCTION__);
309
310 out_lnbId->push_back(1234);
311 *_aidl_return = ndk::SharedRefBase::make<Lnb>();
312
313 return ::ndk::ScopedAStatus::ok();
314}
315
316void Tuner::setFrontendAsDemuxSource(int32_t frontendId, int32_t demuxId) {
317 mFrontendToDemux[frontendId] = demuxId;
318 if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) {
319 mDemuxes[demuxId]->startFrontendInputLoop();
320 }
321}
322
323void Tuner::removeDemux(int32_t demuxId) {
324 map<int32_t, int32_t>::iterator it;
325 for (it = mFrontendToDemux.begin(); it != mFrontendToDemux.end(); it++) {
326 if (it->second == demuxId) {
327 it = mFrontendToDemux.erase(it);
328 break;
329 }
330 }
331 mDemuxes.erase(demuxId);
332}
333
334void Tuner::removeFrontend(int32_t frontendId) {
335 mFrontendToDemux.erase(frontendId);
336}
337
338void Tuner::frontendStopTune(int32_t frontendId) {
339 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
340 int32_t demuxId;
341 if (it != mFrontendToDemux.end()) {
342 demuxId = it->second;
343 mDemuxes[demuxId]->stopFrontendInput();
344 }
345}
346
347void Tuner::frontendStartTune(int32_t frontendId) {
348 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
349 int32_t demuxId;
350 if (it != mFrontendToDemux.end()) {
351 demuxId = it->second;
352 mDemuxes[demuxId]->startFrontendInputLoop();
353 }
354}
355
356} // namespace tuner
357} // namespace tv
358} // namespace hardware
359} // namespace android
360} // namespace aidl