blob: 197d866b28fca7afb4c61dc77ac5a1a3b48e8340 [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
sadiqsada8441c0d2022-12-12 12:16:33 -080041 mFrontendSize = 11;
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);
sadiqsada8441c0d2022-12-12 12:16:33 -080052 mFrontends[10] = ndk::SharedRefBase::make<Frontend>(FrontendType::IPTV, 10);
Hongguang4092f2f2021-07-08 18:49:12 -070053
Hongguang5766ddf2021-12-23 11:40:37 -080054 mMaxUsableFrontends[FrontendType::ISDBS] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080055 mMaxUsableFrontends[FrontendType::ATSC3] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080056 mMaxUsableFrontends[FrontendType::DVBC] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080057 mMaxUsableFrontends[FrontendType::DVBS] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080058 mMaxUsableFrontends[FrontendType::DVBT] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080059 mMaxUsableFrontends[FrontendType::ISDBT] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080060 mMaxUsableFrontends[FrontendType::ANALOG] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080061 mMaxUsableFrontends[FrontendType::ATSC] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080062 mMaxUsableFrontends[FrontendType::ISDBS3] = 1;
Hongguang5766ddf2021-12-23 11:40:37 -080063 mMaxUsableFrontends[FrontendType::DTMB] = 1;
sadiqsada8441c0d2022-12-12 12:16:33 -080064 mMaxUsableFrontends[FrontendType::IPTV] = 1;
Hongguang4092f2f2021-07-08 18:49:12 -070065
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -080066 mDemuxes[0] =
67 ndk::SharedRefBase::make<Demux>(0, (static_cast<int32_t>(DemuxFilterMainType::TS) |
68 static_cast<int32_t>(DemuxFilterMainType::MMTP) |
69 static_cast<int32_t>(DemuxFilterMainType::TLV)));
70 mDemuxes[1] =
71 ndk::SharedRefBase::make<Demux>(1, (static_cast<int32_t>(DemuxFilterMainType::MMTP) |
72 static_cast<int32_t>(DemuxFilterMainType::TLV)));
73 mDemuxes[2] = ndk::SharedRefBase::make<Demux>(2, static_cast<int32_t>(DemuxFilterMainType::IP));
74 mDemuxes[3] = ndk::SharedRefBase::make<Demux>(3, static_cast<int32_t>(DemuxFilterMainType::TS));
75
Hongguang4092f2f2021-07-08 18:49:12 -070076 mLnbs.resize(2);
77 mLnbs[0] = ndk::SharedRefBase::make<Lnb>(0);
78 mLnbs[1] = ndk::SharedRefBase::make<Lnb>(1);
79}
80
81Tuner::~Tuner() {}
82
83::ndk::ScopedAStatus Tuner::getFrontendIds(std::vector<int32_t>* _aidl_return) {
84 ALOGV("%s", __FUNCTION__);
85
86 _aidl_return->resize(mFrontendSize);
87 for (int i = 0; i < mFrontendSize; i++) {
88 (*_aidl_return)[i] = mFrontends[i]->getFrontendId();
89 }
90
91 return ::ndk::ScopedAStatus::ok();
92}
93
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -080094::ndk::ScopedAStatus Tuner::getDemuxInfo(int32_t in_demuxId, DemuxInfo* _aidl_return) {
95 if (mDemuxes.find(in_demuxId) == mDemuxes.end()) {
96 return ::ndk::ScopedAStatus::fromServiceSpecificError(
97 static_cast<int32_t>(Result::INVALID_ARGUMENT));
98 } else {
99 mDemuxes[in_demuxId]->getDemuxInfo(_aidl_return);
100 return ::ndk::ScopedAStatus::ok();
101 }
102}
103
104::ndk::ScopedAStatus Tuner::getDemuxIds(std::vector<int32_t>* _aidl_return) {
105 ALOGV("%s", __FUNCTION__);
106
107 int numOfDemuxes = mDemuxes.size();
108 _aidl_return->resize(numOfDemuxes);
109 int i = 0;
110 for (auto e = mDemuxes.begin(); e != mDemuxes.end(); e++) {
111 (*_aidl_return)[i++] = e->first;
112 }
113 return ::ndk::ScopedAStatus::ok();
114}
115
Hongguang4092f2f2021-07-08 18:49:12 -0700116::ndk::ScopedAStatus Tuner::openFrontendById(int32_t in_frontendId,
117 std::shared_ptr<IFrontend>* _aidl_return) {
118 ALOGV("%s", __FUNCTION__);
119
120 if (in_frontendId >= mFrontendSize || in_frontendId < 0) {
121 ALOGW("[ WARN ] Frontend with id %d isn't available", in_frontendId);
122 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700123 return ::ndk::ScopedAStatus::fromServiceSpecificError(
124 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700125 }
126
Hongguang4a8ac292022-08-09 14:02:03 -0700127 mFrontends[in_frontendId]->setTunerService(this->ref<Tuner>());
Hongguang4092f2f2021-07-08 18:49:12 -0700128 *_aidl_return = mFrontends[in_frontendId];
129 return ::ndk::ScopedAStatus::ok();
130}
131
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800132::ndk::ScopedAStatus Tuner::openDemuxById(int32_t in_demuxId,
133 std::shared_ptr<IDemux>* _aidl_return) {
134 ALOGV("%s", __FUNCTION__);
135
136 if (mDemuxes.find(in_demuxId) == mDemuxes.end()) {
137 ALOGW("[ WARN ] Demux with id %d isn't available", in_demuxId);
138 *_aidl_return = nullptr;
139 return ::ndk::ScopedAStatus::fromServiceSpecificError(
140 static_cast<int32_t>(Result::INVALID_ARGUMENT));
141 }
142
143 if (mDemuxes[in_demuxId]->isInUse()) {
144 return ::ndk::ScopedAStatus::fromServiceSpecificError(
145 static_cast<int32_t>(Result::UNAVAILABLE));
146 } else {
147 mDemuxes[in_demuxId]->setTunerService(this->ref<Tuner>());
148 mDemuxes[in_demuxId]->setInUse(true);
149
150 *_aidl_return = mDemuxes[in_demuxId];
151 return ::ndk::ScopedAStatus::ok();
152 }
153}
154
Hongguang4092f2f2021-07-08 18:49:12 -0700155::ndk::ScopedAStatus Tuner::openDemux(std::vector<int32_t>* out_demuxId,
156 std::shared_ptr<IDemux>* _aidl_return) {
157 ALOGV("%s", __FUNCTION__);
158
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800159 bool found = false;
160 int32_t demuxId = 0;
161 for (auto e = mDemuxes.begin(); e != mDemuxes.end(); e++) {
162 if (!e->second->isInUse()) {
163 found = true;
164 demuxId = e->second->getDemuxId();
165 }
166 }
Hongguang4092f2f2021-07-08 18:49:12 -0700167
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800168 if (found) {
169 out_demuxId->push_back(demuxId);
170 return openDemuxById(demuxId, _aidl_return);
171 } else {
172 return ::ndk::ScopedAStatus::fromServiceSpecificError(
173 static_cast<int32_t>(Result::UNAVAILABLE));
174 }
Hongguang4092f2f2021-07-08 18:49:12 -0700175}
176
177::ndk::ScopedAStatus Tuner::getDemuxCaps(DemuxCapabilities* _aidl_return) {
178 ALOGV("%s", __FUNCTION__);
179
180 // IP filter can be an MMTP filter's data source.
181 _aidl_return->linkCaps = {0x00, 0x00, 0x02, 0x00, 0x00};
182 // Support time filter testing
183 _aidl_return->bTimeFilter = true;
184
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800185 // set filterCaps as the bitwize OR of all the demux' caps
186 std::vector<int32_t> demuxIds;
187 getDemuxIds(&demuxIds);
188 int32_t filterCaps = 0;
189
190 for (int i = 0; i < demuxIds.size(); i++) {
191 DemuxInfo demuxInfo;
192 getDemuxInfo(demuxIds[i], &demuxInfo);
193 filterCaps |= demuxInfo.filterTypes;
194 }
195 _aidl_return->filterCaps = filterCaps;
196
Hongguang4092f2f2021-07-08 18:49:12 -0700197 return ::ndk::ScopedAStatus::ok();
198}
199
200::ndk::ScopedAStatus Tuner::openDescrambler(std::shared_ptr<IDescrambler>* _aidl_return) {
201 ALOGV("%s", __FUNCTION__);
202
203 *_aidl_return = ndk::SharedRefBase::make<Descrambler>();
204
205 return ndk::ScopedAStatus::ok();
206}
207
208::ndk::ScopedAStatus Tuner::getFrontendInfo(int32_t in_frontendId, FrontendInfo* _aidl_return) {
209 ALOGV("%s", __FUNCTION__);
210
Hongguang881190f2022-01-14 13:23:37 -0800211 if (in_frontendId < 0 || in_frontendId >= mFrontendSize) {
Hongguange423acd2021-07-27 16:56:47 -0700212 return ::ndk::ScopedAStatus::fromServiceSpecificError(
213 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700214 }
215
Hongguang881190f2022-01-14 13:23:37 -0800216 mFrontends[in_frontendId]->getFrontendInfo(_aidl_return);
Hongguang4092f2f2021-07-08 18:49:12 -0700217 return ::ndk::ScopedAStatus::ok();
218}
219
220::ndk::ScopedAStatus Tuner::getLnbIds(std::vector<int32_t>* _aidl_return) {
221 ALOGV("%s", __FUNCTION__);
222
223 _aidl_return->resize(mLnbs.size());
224 for (int i = 0; i < mLnbs.size(); i++) {
225 (*_aidl_return)[i] = mLnbs[i]->getId();
226 }
227
228 return ::ndk::ScopedAStatus::ok();
229}
230
231::ndk::ScopedAStatus Tuner::openLnbById(int32_t in_lnbId, std::shared_ptr<ILnb>* _aidl_return) {
232 ALOGV("%s", __FUNCTION__);
233
234 if (in_lnbId >= mLnbs.size()) {
235 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700236 return ::ndk::ScopedAStatus::fromServiceSpecificError(
237 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700238 }
239
240 *_aidl_return = mLnbs[in_lnbId];
241 return ::ndk::ScopedAStatus::ok();
242}
243
244std::shared_ptr<Frontend> Tuner::getFrontendById(int32_t frontendId) {
245 ALOGV("%s", __FUNCTION__);
246
247 return mFrontends[frontendId];
248}
249
250::ndk::ScopedAStatus Tuner::openLnbByName(const std::string& /* in_lnbName */,
251 std::vector<int32_t>* out_lnbId,
252 std::shared_ptr<ILnb>* _aidl_return) {
253 ALOGV("%s", __FUNCTION__);
254
255 out_lnbId->push_back(1234);
256 *_aidl_return = ndk::SharedRefBase::make<Lnb>();
257
258 return ::ndk::ScopedAStatus::ok();
259}
260
Hongguangfcedda02021-12-13 17:08:02 -0800261::ndk::ScopedAStatus Tuner::setLna(bool /* in_bEnable */) {
262 ALOGV("%s", __FUNCTION__);
263
264 return ::ndk::ScopedAStatus::ok();
265}
266
Hongguang5766ddf2021-12-23 11:40:37 -0800267::ndk::ScopedAStatus Tuner::setMaxNumberOfFrontends(FrontendType in_frontendType,
268 int32_t in_maxNumber) {
269 ALOGV("%s", __FUNCTION__);
270
271 // In the default implementation, every type only has one frontend.
272 if (in_maxNumber < 0 || in_maxNumber > 1) {
273 return ::ndk::ScopedAStatus::fromServiceSpecificError(
274 static_cast<int32_t>(Result::INVALID_ARGUMENT));
275 }
276 mMaxUsableFrontends[in_frontendType] = in_maxNumber;
277 return ::ndk::ScopedAStatus::ok();
278}
279
280::ndk::ScopedAStatus Tuner::getMaxNumberOfFrontends(FrontendType in_frontendType,
281 int32_t* _aidl_return) {
282 *_aidl_return = mMaxUsableFrontends[in_frontendType];
283 return ::ndk::ScopedAStatus::ok();
284}
285
Ray Chin8fe32b22022-11-01 11:51:23 +0800286::ndk::ScopedAStatus Tuner::isLnaSupported(bool* _aidl_return) {
287 ALOGV("%s", __FUNCTION__);
288
289 *_aidl_return = true;
290 return ::ndk::ScopedAStatus::ok();
291}
292
Hongguang2ecfc392021-11-23 10:29:15 -0800293binder_status_t Tuner::dump(int fd, const char** args, uint32_t numArgs) {
294 ALOGV("%s", __FUNCTION__);
295 {
296 dprintf(fd, "Frontends:\n");
297 for (int i = 0; i < mFrontendSize; i++) {
298 mFrontends[i]->dump(fd, args, numArgs);
Hongguang2ecfc392021-11-23 10:29:15 -0800299 }
300 }
301 {
302 dprintf(fd, "Demuxs:\n");
303 map<int32_t, std::shared_ptr<Demux>>::iterator it;
304 for (it = mDemuxes.begin(); it != mDemuxes.end(); it++) {
305 it->second->dump(fd, args, numArgs);
306 }
307 }
308 {
309 dprintf(fd, "Lnbs:\n");
310 for (int i = 0; i < mLnbs.size(); i++) {
311 mLnbs[i]->dump(fd, args, numArgs);
312 }
313 }
314 return STATUS_OK;
315}
316
Hongguang4092f2f2021-07-08 18:49:12 -0700317void Tuner::setFrontendAsDemuxSource(int32_t frontendId, int32_t demuxId) {
318 mFrontendToDemux[frontendId] = demuxId;
319 if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) {
320 mDemuxes[demuxId]->startFrontendInputLoop();
321 }
322}
323
324void Tuner::removeDemux(int32_t demuxId) {
325 map<int32_t, int32_t>::iterator it;
326 for (it = mFrontendToDemux.begin(); it != mFrontendToDemux.end(); it++) {
327 if (it->second == demuxId) {
328 it = mFrontendToDemux.erase(it);
329 break;
330 }
331 }
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800332 mDemuxes[demuxId]->setInUse(false);
Hongguang4092f2f2021-07-08 18:49:12 -0700333}
334
335void Tuner::removeFrontend(int32_t frontendId) {
Hongguang2ecfc392021-11-23 10:29:15 -0800336 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
337 if (it != mFrontendToDemux.end()) {
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800338 mDemuxes[it->second]->setInUse(false);
Hongguang2ecfc392021-11-23 10:29:15 -0800339 }
Hongguang4092f2f2021-07-08 18:49:12 -0700340 mFrontendToDemux.erase(frontendId);
341}
342
343void Tuner::frontendStopTune(int32_t frontendId) {
344 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
345 int32_t demuxId;
346 if (it != mFrontendToDemux.end()) {
347 demuxId = it->second;
348 mDemuxes[demuxId]->stopFrontendInput();
349 }
350}
351
352void Tuner::frontendStartTune(int32_t frontendId) {
353 map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
354 int32_t demuxId;
355 if (it != mFrontendToDemux.end()) {
356 demuxId = it->second;
357 mDemuxes[demuxId]->startFrontendInputLoop();
358 }
359}
360
361} // namespace tuner
362} // namespace tv
363} // namespace hardware
364} // namespace android
365} // namespace aidl