blob: dc0bd5e3466e78bc33e8a207b58632710a1ab00a [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
20#include "Tuner.h"
21#include <utils/Log.h>
22#include "Demux.h"
23#include "Descrambler.h"
24#include "Frontend.h"
25#include "Lnb.h"
26
27namespace aidl {
28namespace android {
29namespace hardware {
30namespace tv {
31namespace tuner {
32
33Tuner::Tuner() {
34 // Static Frontends array to maintain local frontends information
35 // Array index matches their FrontendId in the default impl
36 mFrontendSize = 10;
37 mFrontends[0] = ndk::SharedRefBase::make<Frontend>(FrontendType::ISDBS, 0, ref<Tuner>());
38 mFrontends[1] = ndk::SharedRefBase::make<Frontend>(FrontendType::ATSC3, 1, ref<Tuner>());
39 mFrontends[2] = ndk::SharedRefBase::make<Frontend>(FrontendType::DVBC, 2, ref<Tuner>());
40 mFrontends[3] = ndk::SharedRefBase::make<Frontend>(FrontendType::DVBS, 3, ref<Tuner>());
41 mFrontends[4] = ndk::SharedRefBase::make<Frontend>(FrontendType::DVBT, 4, ref<Tuner>());
42 mFrontends[5] = ndk::SharedRefBase::make<Frontend>(FrontendType::ISDBT, 5, ref<Tuner>());
43 mFrontends[6] = ndk::SharedRefBase::make<Frontend>(FrontendType::ANALOG, 6, ref<Tuner>());
44 mFrontends[7] = ndk::SharedRefBase::make<Frontend>(FrontendType::ATSC, 7, ref<Tuner>());
45 mFrontends[8] = ndk::SharedRefBase::make<Frontend>(FrontendType::ISDBS3, 8, ref<Tuner>());
46 mFrontends[9] = ndk::SharedRefBase::make<Frontend>(FrontendType::DTMB, 9, ref<Tuner>());
47
48 vector<FrontendStatusType> statusCaps;
49
50 FrontendCapabilities capsIsdbs;
51 capsIsdbs.set<FrontendCapabilities::Tag::isdbsCaps>(FrontendIsdbsCapabilities());
52 mFrontendCaps[0] = capsIsdbs;
53 statusCaps = {
54 FrontendStatusType::DEMOD_LOCK, FrontendStatusType::SNR,
55 FrontendStatusType::FEC, FrontendStatusType::MODULATION,
56 FrontendStatusType::MODULATIONS, FrontendStatusType::ROLL_OFF,
57 };
58 mFrontendStatusCaps[0] = statusCaps;
59
60 FrontendCapabilities capsAtsc3;
61 capsAtsc3.set<FrontendCapabilities::Tag::atsc3Caps>(FrontendAtsc3Capabilities());
62 mFrontendCaps[1] = capsAtsc3;
63 statusCaps = {
64 FrontendStatusType::BER,
65 FrontendStatusType::PER,
66 FrontendStatusType::ATSC3_PLP_INFO,
67 FrontendStatusType::MODULATIONS,
68 FrontendStatusType::BERS,
69 FrontendStatusType::INTERLEAVINGS,
70 FrontendStatusType::BANDWIDTH,
71 };
72 mFrontendStatusCaps[1] = statusCaps;
73
74 FrontendCapabilities capsDvbc;
75 capsDvbc.set<FrontendCapabilities::Tag::dvbcCaps>(FrontendDvbcCapabilities());
76 mFrontendCaps[2] = capsDvbc;
77 statusCaps = {
78 FrontendStatusType::PRE_BER, FrontendStatusType::SIGNAL_QUALITY,
79 FrontendStatusType::MODULATION, FrontendStatusType::SPECTRAL,
80 FrontendStatusType::MODULATIONS, FrontendStatusType::CODERATES,
81 FrontendStatusType::INTERLEAVINGS, FrontendStatusType::BANDWIDTH,
82 };
83 mFrontendStatusCaps[2] = statusCaps;
84
85 FrontendCapabilities capsDvbs;
86 capsDvbs.set<FrontendCapabilities::Tag::dvbsCaps>(FrontendDvbsCapabilities());
87 mFrontendCaps[3] = capsDvbs;
88 statusCaps = {
89 FrontendStatusType::SIGNAL_STRENGTH, FrontendStatusType::SYMBOL_RATE,
90 FrontendStatusType::MODULATION, FrontendStatusType::MODULATIONS,
91 FrontendStatusType::ROLL_OFF, FrontendStatusType::IS_MISO,
92 };
93 mFrontendStatusCaps[3] = statusCaps;
94
95 FrontendCapabilities capsDvbt;
96 capsDvbt.set<FrontendCapabilities::Tag::dvbtCaps>(FrontendDvbtCapabilities());
97 mFrontendCaps[4] = capsDvbt;
98 statusCaps = {
99 FrontendStatusType::EWBS,
100 FrontendStatusType::PLP_ID,
101 FrontendStatusType::HIERARCHY,
102 FrontendStatusType::MODULATIONS,
103 FrontendStatusType::BANDWIDTH,
104 FrontendStatusType::GUARD_INTERVAL,
105 FrontendStatusType::TRANSMISSION_MODE,
106 FrontendStatusType::T2_SYSTEM_ID,
107 };
108 mFrontendStatusCaps[4] = statusCaps;
109
110 FrontendCapabilities capsIsdbt;
111 FrontendIsdbtCapabilities isdbtCaps{
112 .modeCap = (int)FrontendIsdbtMode::MODE_1 | (int)FrontendIsdbtMode::MODE_2,
113 .bandwidthCap = (int)FrontendIsdbtBandwidth::BANDWIDTH_6MHZ,
114 .modulationCap = (int)FrontendIsdbtModulation::MOD_16QAM,
115 // ISDBT shares coderate and guard interval with DVBT
116 .coderateCap = (int)FrontendDvbtCoderate::CODERATE_4_5 |
117 (int)FrontendDvbtCoderate::CODERATE_6_7,
118 .guardIntervalCap = (int)FrontendDvbtGuardInterval::INTERVAL_1_128,
119 };
120 capsIsdbt.set<FrontendCapabilities::Tag::isdbtCaps>(isdbtCaps);
121 mFrontendCaps[5] = capsIsdbt;
122 statusCaps = {
123 FrontendStatusType::AGC,
124 FrontendStatusType::LNA,
125 FrontendStatusType::MODULATION,
126 FrontendStatusType::MODULATIONS,
127 FrontendStatusType::BANDWIDTH,
128 FrontendStatusType::GUARD_INTERVAL,
129 FrontendStatusType::TRANSMISSION_MODE,
130 FrontendStatusType::ISDBT_SEGMENTS,
131 };
132 mFrontendStatusCaps[5] = statusCaps;
133
134 FrontendCapabilities capsAnalog;
135 capsAnalog.set<FrontendCapabilities::Tag::analogCaps>(FrontendAnalogCapabilities());
136 mFrontendCaps[6] = capsAnalog;
137 statusCaps = {
138 FrontendStatusType::LAYER_ERROR,
139 FrontendStatusType::MER,
140 FrontendStatusType::UEC,
141 FrontendStatusType::TS_DATA_RATES,
142 };
143 mFrontendStatusCaps[6] = statusCaps;
144
145 FrontendCapabilities capsAtsc;
146 capsAtsc.set<FrontendCapabilities::Tag::atscCaps>(FrontendAtscCapabilities());
147 mFrontendCaps[7] = capsAtsc;
148 statusCaps = {
149 FrontendStatusType::FREQ_OFFSET,
150 FrontendStatusType::RF_LOCK,
151 FrontendStatusType::MODULATIONS,
152 FrontendStatusType::IS_LINEAR,
153 };
154 mFrontendStatusCaps[7] = statusCaps;
155
156 FrontendCapabilities capsIsdbs3;
157 capsIsdbs3.set<FrontendCapabilities::Tag::isdbs3Caps>(FrontendIsdbs3Capabilities());
158 mFrontendCaps[8] = capsIsdbs3;
159 statusCaps = {
160 FrontendStatusType::DEMOD_LOCK, FrontendStatusType::MODULATION,
161 FrontendStatusType::MODULATIONS, FrontendStatusType::ROLL_OFF,
162 FrontendStatusType::IS_SHORT_FRAMES,
163 };
164 mFrontendStatusCaps[8] = statusCaps;
165
166 FrontendCapabilities capsDtmb;
167 capsDtmb.set<FrontendCapabilities::Tag::dtmbCaps>(FrontendDtmbCapabilities());
168 mFrontendCaps[9] = capsDtmb;
169 statusCaps = {
170 FrontendStatusType::MODULATIONS, FrontendStatusType::INTERLEAVINGS,
171 FrontendStatusType::BANDWIDTH, FrontendStatusType::GUARD_INTERVAL,
172 FrontendStatusType::TRANSMISSION_MODE,
173 };
174 mFrontendStatusCaps[9] = statusCaps;
175
176 mLnbs.resize(2);
177 mLnbs[0] = ndk::SharedRefBase::make<Lnb>(0);
178 mLnbs[1] = ndk::SharedRefBase::make<Lnb>(1);
179}
180
181Tuner::~Tuner() {}
182
183::ndk::ScopedAStatus Tuner::getFrontendIds(std::vector<int32_t>* _aidl_return) {
184 ALOGV("%s", __FUNCTION__);
185
186 _aidl_return->resize(mFrontendSize);
187 for (int i = 0; i < mFrontendSize; i++) {
188 (*_aidl_return)[i] = mFrontends[i]->getFrontendId();
189 }
190
191 return ::ndk::ScopedAStatus::ok();
192}
193
194::ndk::ScopedAStatus Tuner::openFrontendById(int32_t in_frontendId,
195 std::shared_ptr<IFrontend>* _aidl_return) {
196 ALOGV("%s", __FUNCTION__);
197
198 if (in_frontendId >= mFrontendSize || in_frontendId < 0) {
199 ALOGW("[ WARN ] Frontend with id %d isn't available", in_frontendId);
200 *_aidl_return = nullptr;
201 return ::ndk::ScopedAStatus::fromExceptionCode(STATUS_INVALID_OPERATION);
202 }
203
204 *_aidl_return = mFrontends[in_frontendId];
205 return ::ndk::ScopedAStatus::ok();
206}
207
208::ndk::ScopedAStatus Tuner::openDemux(std::vector<int32_t>* out_demuxId,
209 std::shared_ptr<IDemux>* _aidl_return) {
210 ALOGV("%s", __FUNCTION__);
211
212 mLastUsedId += 1;
213 mDemuxes[mLastUsedId] = ndk::SharedRefBase::make<Demux>(mLastUsedId, ref<Tuner>());
214
215 out_demuxId->push_back(mLastUsedId);
216 *_aidl_return = mDemuxes[mLastUsedId];
217
218 return ::ndk::ScopedAStatus::ok();
219}
220
221::ndk::ScopedAStatus Tuner::getDemuxCaps(DemuxCapabilities* _aidl_return) {
222 ALOGV("%s", __FUNCTION__);
223
224 // IP filter can be an MMTP filter's data source.
225 _aidl_return->linkCaps = {0x00, 0x00, 0x02, 0x00, 0x00};
226 // Support time filter testing
227 _aidl_return->bTimeFilter = true;
228
229 return ::ndk::ScopedAStatus::ok();
230}
231
232::ndk::ScopedAStatus Tuner::openDescrambler(std::shared_ptr<IDescrambler>* _aidl_return) {
233 ALOGV("%s", __FUNCTION__);
234
235 *_aidl_return = ndk::SharedRefBase::make<Descrambler>();
236
237 return ndk::ScopedAStatus::ok();
238}
239
240::ndk::ScopedAStatus Tuner::getFrontendInfo(int32_t in_frontendId, FrontendInfo* _aidl_return) {
241 ALOGV("%s", __FUNCTION__);
242
243 if (in_frontendId >= mFrontendSize) {
244 return ::ndk::ScopedAStatus::fromExceptionCode(STATUS_INVALID_OPERATION);
245 }
246
247 // assign randomly selected values for testing.
248 *_aidl_return = {
249 .type = mFrontends[in_frontendId]->getFrontendType(),
250 .minFrequency = 139,
251 .maxFrequency = 1139,
252 .minSymbolRate = 45,
253 .maxSymbolRate = 1145,
254 .acquireRange = 30,
255 .exclusiveGroupId = 57,
256 .statusCaps = mFrontendStatusCaps[in_frontendId],
257 .frontendCaps = mFrontendCaps[in_frontendId],
258 };
259
260 return ::ndk::ScopedAStatus::ok();
261}
262
263::ndk::ScopedAStatus Tuner::getLnbIds(std::vector<int32_t>* _aidl_return) {
264 ALOGV("%s", __FUNCTION__);
265
266 _aidl_return->resize(mLnbs.size());
267 for (int i = 0; i < mLnbs.size(); i++) {
268 (*_aidl_return)[i] = mLnbs[i]->getId();
269 }
270
271 return ::ndk::ScopedAStatus::ok();
272}
273
274::ndk::ScopedAStatus Tuner::openLnbById(int32_t in_lnbId, std::shared_ptr<ILnb>* _aidl_return) {
275 ALOGV("%s", __FUNCTION__);
276
277 if (in_lnbId >= mLnbs.size()) {
278 *_aidl_return = nullptr;
279 return ::ndk::ScopedAStatus::fromExceptionCode(STATUS_INVALID_OPERATION);
280 }
281
282 *_aidl_return = mLnbs[in_lnbId];
283 return ::ndk::ScopedAStatus::ok();
284}
285
286std::shared_ptr<Frontend> Tuner::getFrontendById(int32_t frontendId) {
287 ALOGV("%s", __FUNCTION__);
288
289 return mFrontends[frontendId];
290}
291
292::ndk::ScopedAStatus Tuner::openLnbByName(const std::string& /* in_lnbName */,
293 std::vector<int32_t>* out_lnbId,
294 std::shared_ptr<ILnb>* _aidl_return) {
295 ALOGV("%s", __FUNCTION__);
296
297 out_lnbId->push_back(1234);
298 *_aidl_return = ndk::SharedRefBase::make<Lnb>();
299
300 return ::ndk::ScopedAStatus::ok();
301}
302
303void Tuner::setFrontendAsDemuxSource(int32_t frontendId, int32_t demuxId) {
304 mFrontendToDemux[frontendId] = demuxId;
305 if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) {
306 mDemuxes[demuxId]->startFrontendInputLoop();
307 }
308}
309
310void Tuner::removeDemux(int32_t demuxId) {
311 map<int32_t, int32_t>::iterator it;
312 for (it = mFrontendToDemux.begin(); it != mFrontendToDemux.end(); it++) {
313 if (it->second == demuxId) {
314 it = mFrontendToDemux.erase(it);
315 break;
316 }
317 }
318 mDemuxes.erase(demuxId);
319}
320
321void Tuner::removeFrontend(int32_t frontendId) {
322 mFrontendToDemux.erase(frontendId);
323}
324
325void Tuner::frontendStopTune(int32_t frontendId) {
326 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
327 int32_t demuxId;
328 if (it != mFrontendToDemux.end()) {
329 demuxId = it->second;
330 mDemuxes[demuxId]->stopFrontendInput();
331 }
332}
333
334void Tuner::frontendStartTune(int32_t frontendId) {
335 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
336 int32_t demuxId;
337 if (it != mFrontendToDemux.end()) {
338 demuxId = it->second;
339 mDemuxes[demuxId]->startFrontendInputLoop();
340 }
341}
342
343} // namespace tuner
344} // namespace tv
345} // namespace hardware
346} // namespace android
347} // namespace aidl