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