blob: 0c1ae2da8a35bfa647bb0dd937c324f14e5c25e8 [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
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -080020#include <aidl/android/hardware/tv/tuner/DemuxFilterMainType.h>
Hongguange423acd2021-07-27 16:56:47 -070021#include <aidl/android/hardware/tv/tuner/Result.h>
Hongguang4092f2f2021-07-08 18:49:12 -070022#include <utils/Log.h>
Hongguange423acd2021-07-27 16:56:47 -070023
Hongguang4092f2f2021-07-08 18:49:12 -070024#include "Demux.h"
25#include "Descrambler.h"
26#include "Frontend.h"
27#include "Lnb.h"
Hongguange423acd2021-07-27 16:56:47 -070028#include "Tuner.h"
Hongguang4092f2f2021-07-08 18:49:12 -070029
30namespace aidl {
31namespace android {
32namespace hardware {
33namespace tv {
34namespace tuner {
35
Hongguang Chenff2c6b02021-08-07 00:12:26 +000036Tuner::Tuner() {}
37
38void Tuner::init() {
Hongguang4092f2f2021-07-08 18:49:12 -070039 // Static Frontends array to maintain local frontends information
40 // Array index matches their FrontendId in the default impl
41 mFrontendSize = 10;
Hongguang4a8ac292022-08-09 14:02:03 -070042 mFrontends[0] = ndk::SharedRefBase::make<Frontend>(FrontendType::ISDBS, 0);
43 mFrontends[1] = ndk::SharedRefBase::make<Frontend>(FrontendType::ATSC3, 1);
44 mFrontends[2] = ndk::SharedRefBase::make<Frontend>(FrontendType::DVBC, 2);
45 mFrontends[3] = ndk::SharedRefBase::make<Frontend>(FrontendType::DVBS, 3);
46 mFrontends[4] = ndk::SharedRefBase::make<Frontend>(FrontendType::DVBT, 4);
47 mFrontends[5] = ndk::SharedRefBase::make<Frontend>(FrontendType::ISDBT, 5);
48 mFrontends[6] = ndk::SharedRefBase::make<Frontend>(FrontendType::ANALOG, 6);
49 mFrontends[7] = ndk::SharedRefBase::make<Frontend>(FrontendType::ATSC, 7);
50 mFrontends[8] = ndk::SharedRefBase::make<Frontend>(FrontendType::ISDBS3, 8);
51 mFrontends[9] = ndk::SharedRefBase::make<Frontend>(FrontendType::DTMB, 9);
Hongguang4092f2f2021-07-08 18:49:12 -070052
Hongguang5766ddf2021-12-23 11:40:37 -080053 mMaxUsableFrontends[FrontendType::ISDBS] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080054 mMaxUsableFrontends[FrontendType::ATSC3] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080055 mMaxUsableFrontends[FrontendType::DVBC] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080056 mMaxUsableFrontends[FrontendType::DVBS] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080057 mMaxUsableFrontends[FrontendType::DVBT] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080058 mMaxUsableFrontends[FrontendType::ISDBT] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080059 mMaxUsableFrontends[FrontendType::ANALOG] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080060 mMaxUsableFrontends[FrontendType::ATSC] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080061 mMaxUsableFrontends[FrontendType::ISDBS3] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080062 mMaxUsableFrontends[FrontendType::DTMB] = 1;
Hongguang4092f2f2021-07-08 18:49:12 -070063
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -080064 mDemuxes[0] =
65 ndk::SharedRefBase::make<Demux>(0, (static_cast<int32_t>(DemuxFilterMainType::TS) |
66 static_cast<int32_t>(DemuxFilterMainType::MMTP) |
67 static_cast<int32_t>(DemuxFilterMainType::TLV)));
68 mDemuxes[1] =
69 ndk::SharedRefBase::make<Demux>(1, (static_cast<int32_t>(DemuxFilterMainType::MMTP) |
70 static_cast<int32_t>(DemuxFilterMainType::TLV)));
71 mDemuxes[2] = ndk::SharedRefBase::make<Demux>(2, static_cast<int32_t>(DemuxFilterMainType::IP));
72 mDemuxes[3] = ndk::SharedRefBase::make<Demux>(3, static_cast<int32_t>(DemuxFilterMainType::TS));
73
Hongguang4092f2f2021-07-08 18:49:12 -070074 mLnbs.resize(2);
75 mLnbs[0] = ndk::SharedRefBase::make<Lnb>(0);
76 mLnbs[1] = ndk::SharedRefBase::make<Lnb>(1);
77}
78
79Tuner::~Tuner() {}
80
81::ndk::ScopedAStatus Tuner::getFrontendIds(std::vector<int32_t>* _aidl_return) {
82 ALOGV("%s", __FUNCTION__);
83
84 _aidl_return->resize(mFrontendSize);
85 for (int i = 0; i < mFrontendSize; i++) {
86 (*_aidl_return)[i] = mFrontends[i]->getFrontendId();
87 }
88
89 return ::ndk::ScopedAStatus::ok();
90}
91
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -080092::ndk::ScopedAStatus Tuner::getDemuxInfo(int32_t in_demuxId, DemuxInfo* _aidl_return) {
93 if (mDemuxes.find(in_demuxId) == mDemuxes.end()) {
94 return ::ndk::ScopedAStatus::fromServiceSpecificError(
95 static_cast<int32_t>(Result::INVALID_ARGUMENT));
96 } else {
97 mDemuxes[in_demuxId]->getDemuxInfo(_aidl_return);
98 return ::ndk::ScopedAStatus::ok();
99 }
100}
101
102::ndk::ScopedAStatus Tuner::getDemuxIds(std::vector<int32_t>* _aidl_return) {
103 ALOGV("%s", __FUNCTION__);
104
105 int numOfDemuxes = mDemuxes.size();
106 _aidl_return->resize(numOfDemuxes);
107 int i = 0;
108 for (auto e = mDemuxes.begin(); e != mDemuxes.end(); e++) {
109 (*_aidl_return)[i++] = e->first;
110 }
111 return ::ndk::ScopedAStatus::ok();
112}
113
Hongguang4092f2f2021-07-08 18:49:12 -0700114::ndk::ScopedAStatus Tuner::openFrontendById(int32_t in_frontendId,
115 std::shared_ptr<IFrontend>* _aidl_return) {
116 ALOGV("%s", __FUNCTION__);
117
118 if (in_frontendId >= mFrontendSize || in_frontendId < 0) {
119 ALOGW("[ WARN ] Frontend with id %d isn't available", in_frontendId);
120 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700121 return ::ndk::ScopedAStatus::fromServiceSpecificError(
122 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700123 }
124
Hongguang4a8ac292022-08-09 14:02:03 -0700125 mFrontends[in_frontendId]->setTunerService(this->ref<Tuner>());
Hongguang4092f2f2021-07-08 18:49:12 -0700126 *_aidl_return = mFrontends[in_frontendId];
127 return ::ndk::ScopedAStatus::ok();
128}
129
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800130::ndk::ScopedAStatus Tuner::openDemuxById(int32_t in_demuxId,
131 std::shared_ptr<IDemux>* _aidl_return) {
132 ALOGV("%s", __FUNCTION__);
133
134 if (mDemuxes.find(in_demuxId) == mDemuxes.end()) {
135 ALOGW("[ WARN ] Demux with id %d isn't available", in_demuxId);
136 *_aidl_return = nullptr;
137 return ::ndk::ScopedAStatus::fromServiceSpecificError(
138 static_cast<int32_t>(Result::INVALID_ARGUMENT));
139 }
140
141 if (mDemuxes[in_demuxId]->isInUse()) {
142 return ::ndk::ScopedAStatus::fromServiceSpecificError(
143 static_cast<int32_t>(Result::UNAVAILABLE));
144 } else {
145 mDemuxes[in_demuxId]->setTunerService(this->ref<Tuner>());
146 mDemuxes[in_demuxId]->setInUse(true);
147
148 *_aidl_return = mDemuxes[in_demuxId];
149 return ::ndk::ScopedAStatus::ok();
150 }
151}
152
Hongguang4092f2f2021-07-08 18:49:12 -0700153::ndk::ScopedAStatus Tuner::openDemux(std::vector<int32_t>* out_demuxId,
154 std::shared_ptr<IDemux>* _aidl_return) {
155 ALOGV("%s", __FUNCTION__);
156
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800157 bool found = false;
158 int32_t demuxId = 0;
159 for (auto e = mDemuxes.begin(); e != mDemuxes.end(); e++) {
160 if (!e->second->isInUse()) {
161 found = true;
162 demuxId = e->second->getDemuxId();
163 }
164 }
Hongguang4092f2f2021-07-08 18:49:12 -0700165
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800166 if (found) {
167 out_demuxId->push_back(demuxId);
168 return openDemuxById(demuxId, _aidl_return);
169 } else {
170 return ::ndk::ScopedAStatus::fromServiceSpecificError(
171 static_cast<int32_t>(Result::UNAVAILABLE));
172 }
Hongguang4092f2f2021-07-08 18:49:12 -0700173}
174
175::ndk::ScopedAStatus Tuner::getDemuxCaps(DemuxCapabilities* _aidl_return) {
176 ALOGV("%s", __FUNCTION__);
177
178 // IP filter can be an MMTP filter's data source.
179 _aidl_return->linkCaps = {0x00, 0x00, 0x02, 0x00, 0x00};
180 // Support time filter testing
181 _aidl_return->bTimeFilter = true;
182
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800183 // set filterCaps as the bitwize OR of all the demux' caps
184 std::vector<int32_t> demuxIds;
185 getDemuxIds(&demuxIds);
186 int32_t filterCaps = 0;
187
188 for (int i = 0; i < demuxIds.size(); i++) {
189 DemuxInfo demuxInfo;
190 getDemuxInfo(demuxIds[i], &demuxInfo);
191 filterCaps |= demuxInfo.filterTypes;
192 }
193 _aidl_return->filterCaps = filterCaps;
194
Hongguang4092f2f2021-07-08 18:49:12 -0700195 return ::ndk::ScopedAStatus::ok();
196}
197
198::ndk::ScopedAStatus Tuner::openDescrambler(std::shared_ptr<IDescrambler>* _aidl_return) {
199 ALOGV("%s", __FUNCTION__);
200
201 *_aidl_return = ndk::SharedRefBase::make<Descrambler>();
202
203 return ndk::ScopedAStatus::ok();
204}
205
206::ndk::ScopedAStatus Tuner::getFrontendInfo(int32_t in_frontendId, FrontendInfo* _aidl_return) {
207 ALOGV("%s", __FUNCTION__);
208
Hongguang881190f2022-01-14 13:23:37 -0800209 if (in_frontendId < 0 || in_frontendId >= mFrontendSize) {
Hongguange423acd2021-07-27 16:56:47 -0700210 return ::ndk::ScopedAStatus::fromServiceSpecificError(
211 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700212 }
213
Hongguang881190f2022-01-14 13:23:37 -0800214 mFrontends[in_frontendId]->getFrontendInfo(_aidl_return);
Hongguang4092f2f2021-07-08 18:49:12 -0700215 return ::ndk::ScopedAStatus::ok();
216}
217
218::ndk::ScopedAStatus Tuner::getLnbIds(std::vector<int32_t>* _aidl_return) {
219 ALOGV("%s", __FUNCTION__);
220
221 _aidl_return->resize(mLnbs.size());
222 for (int i = 0; i < mLnbs.size(); i++) {
223 (*_aidl_return)[i] = mLnbs[i]->getId();
224 }
225
226 return ::ndk::ScopedAStatus::ok();
227}
228
229::ndk::ScopedAStatus Tuner::openLnbById(int32_t in_lnbId, std::shared_ptr<ILnb>* _aidl_return) {
230 ALOGV("%s", __FUNCTION__);
231
232 if (in_lnbId >= mLnbs.size()) {
233 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700234 return ::ndk::ScopedAStatus::fromServiceSpecificError(
235 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700236 }
237
238 *_aidl_return = mLnbs[in_lnbId];
239 return ::ndk::ScopedAStatus::ok();
240}
241
242std::shared_ptr<Frontend> Tuner::getFrontendById(int32_t frontendId) {
243 ALOGV("%s", __FUNCTION__);
244
245 return mFrontends[frontendId];
246}
247
248::ndk::ScopedAStatus Tuner::openLnbByName(const std::string& /* in_lnbName */,
249 std::vector<int32_t>* out_lnbId,
250 std::shared_ptr<ILnb>* _aidl_return) {
251 ALOGV("%s", __FUNCTION__);
252
253 out_lnbId->push_back(1234);
254 *_aidl_return = ndk::SharedRefBase::make<Lnb>();
255
256 return ::ndk::ScopedAStatus::ok();
257}
258
Hongguangfcedda02021-12-13 17:08:02 -0800259::ndk::ScopedAStatus Tuner::setLna(bool /* in_bEnable */) {
260 ALOGV("%s", __FUNCTION__);
261
262 return ::ndk::ScopedAStatus::ok();
263}
264
Hongguang5766ddf2021-12-23 11:40:37 -0800265::ndk::ScopedAStatus Tuner::setMaxNumberOfFrontends(FrontendType in_frontendType,
266 int32_t in_maxNumber) {
267 ALOGV("%s", __FUNCTION__);
268
269 // In the default implementation, every type only has one frontend.
270 if (in_maxNumber < 0 || in_maxNumber > 1) {
271 return ::ndk::ScopedAStatus::fromServiceSpecificError(
272 static_cast<int32_t>(Result::INVALID_ARGUMENT));
273 }
274 mMaxUsableFrontends[in_frontendType] = in_maxNumber;
275 return ::ndk::ScopedAStatus::ok();
276}
277
278::ndk::ScopedAStatus Tuner::getMaxNumberOfFrontends(FrontendType in_frontendType,
279 int32_t* _aidl_return) {
280 *_aidl_return = mMaxUsableFrontends[in_frontendType];
281 return ::ndk::ScopedAStatus::ok();
282}
283
Ray Chin8fe32b22022-11-01 11:51:23 +0800284::ndk::ScopedAStatus Tuner::isLnaSupported(bool* _aidl_return) {
285 ALOGV("%s", __FUNCTION__);
286
287 *_aidl_return = true;
288 return ::ndk::ScopedAStatus::ok();
289}
290
Hongguang2ecfc392021-11-23 10:29:15 -0800291binder_status_t Tuner::dump(int fd, const char** args, uint32_t numArgs) {
292 ALOGV("%s", __FUNCTION__);
293 {
294 dprintf(fd, "Frontends:\n");
295 for (int i = 0; i < mFrontendSize; i++) {
296 mFrontends[i]->dump(fd, args, numArgs);
Hongguang2ecfc392021-11-23 10:29:15 -0800297 }
298 }
299 {
300 dprintf(fd, "Demuxs:\n");
301 map<int32_t, std::shared_ptr<Demux>>::iterator it;
302 for (it = mDemuxes.begin(); it != mDemuxes.end(); it++) {
303 it->second->dump(fd, args, numArgs);
304 }
305 }
306 {
307 dprintf(fd, "Lnbs:\n");
308 for (int i = 0; i < mLnbs.size(); i++) {
309 mLnbs[i]->dump(fd, args, numArgs);
310 }
311 }
312 return STATUS_OK;
313}
314
Hongguang4092f2f2021-07-08 18:49:12 -0700315void Tuner::setFrontendAsDemuxSource(int32_t frontendId, int32_t demuxId) {
316 mFrontendToDemux[frontendId] = demuxId;
317 if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) {
318 mDemuxes[demuxId]->startFrontendInputLoop();
319 }
320}
321
322void Tuner::removeDemux(int32_t demuxId) {
323 map<int32_t, int32_t>::iterator it;
324 for (it = mFrontendToDemux.begin(); it != mFrontendToDemux.end(); it++) {
325 if (it->second == demuxId) {
326 it = mFrontendToDemux.erase(it);
327 break;
328 }
329 }
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800330 mDemuxes[demuxId]->setInUse(false);
Hongguang4092f2f2021-07-08 18:49:12 -0700331}
332
333void Tuner::removeFrontend(int32_t frontendId) {
Hongguang2ecfc392021-11-23 10:29:15 -0800334 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
335 if (it != mFrontendToDemux.end()) {
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800336 mDemuxes[it->second]->setInUse(false);
Hongguang2ecfc392021-11-23 10:29:15 -0800337 }
Hongguang4092f2f2021-07-08 18:49:12 -0700338 mFrontendToDemux.erase(frontendId);
339}
340
341void Tuner::frontendStopTune(int32_t frontendId) {
342 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
343 int32_t demuxId;
344 if (it != mFrontendToDemux.end()) {
345 demuxId = it->second;
346 mDemuxes[demuxId]->stopFrontendInput();
347 }
348}
349
350void Tuner::frontendStartTune(int32_t frontendId) {
351 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
352 int32_t demuxId;
353 if (it != mFrontendToDemux.end()) {
354 demuxId = it->second;
355 mDemuxes[demuxId]->startFrontendInputLoop();
356 }
357}
358
359} // namespace tuner
360} // namespace tv
361} // namespace hardware
362} // namespace android
363} // namespace aidl