• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 <aidl/android/hardware/tv/tuner/DemuxFilterMainType.h>
21 #include <aidl/android/hardware/tv/tuner/Result.h>
22 #include <utils/Log.h>
23 
24 #include "Demux.h"
25 #include "Descrambler.h"
26 #include "Frontend.h"
27 #include "Lnb.h"
28 #include "Tuner.h"
29 
30 namespace aidl {
31 namespace android {
32 namespace hardware {
33 namespace tv {
34 namespace tuner {
35 
Tuner()36 Tuner::Tuner() {}
37 
init()38 void Tuner::init() {
39     // Static Frontends array to maintain local frontends information
40     // Array index matches their FrontendId in the default impl
41     mFrontendSize = 11;
42     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);
52     mFrontends[10] = ndk::SharedRefBase::make<Frontend>(FrontendType::IPTV, 10);
53 
54     mMaxUsableFrontends[FrontendType::ISDBS] = 1;
55     mMaxUsableFrontends[FrontendType::ATSC3] = 1;
56     mMaxUsableFrontends[FrontendType::DVBC] = 1;
57     mMaxUsableFrontends[FrontendType::DVBS] = 1;
58     mMaxUsableFrontends[FrontendType::DVBT] = 1;
59     mMaxUsableFrontends[FrontendType::ISDBT] = 1;
60     mMaxUsableFrontends[FrontendType::ANALOG] = 1;
61     mMaxUsableFrontends[FrontendType::ATSC] = 1;
62     mMaxUsableFrontends[FrontendType::ISDBS3] = 1;
63     mMaxUsableFrontends[FrontendType::DTMB] = 1;
64     mMaxUsableFrontends[FrontendType::IPTV] = 1;
65 
66     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 
76     mLnbs.resize(2);
77     mLnbs[0] = ndk::SharedRefBase::make<Lnb>(0);
78     mLnbs[1] = ndk::SharedRefBase::make<Lnb>(1);
79 }
80 
~Tuner()81 Tuner::~Tuner() {}
82 
getFrontendIds(std::vector<int32_t> * _aidl_return)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 
getDemuxInfo(int32_t in_demuxId,DemuxInfo * _aidl_return)94 ::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 
getDemuxIds(std::vector<int32_t> * _aidl_return)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 
openFrontendById(int32_t in_frontendId,std::shared_ptr<IFrontend> * _aidl_return)116 ::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;
123         return ::ndk::ScopedAStatus::fromServiceSpecificError(
124                 static_cast<int32_t>(Result::INVALID_ARGUMENT));
125     }
126 
127     mFrontends[in_frontendId]->setTunerService(this->ref<Tuner>());
128     *_aidl_return = mFrontends[in_frontendId];
129     return ::ndk::ScopedAStatus::ok();
130 }
131 
openDemuxById(int32_t in_demuxId,std::shared_ptr<IDemux> * _aidl_return)132 ::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 
openDemux(std::vector<int32_t> * out_demuxId,std::shared_ptr<IDemux> * _aidl_return)155 ::ndk::ScopedAStatus Tuner::openDemux(std::vector<int32_t>* out_demuxId,
156                                       std::shared_ptr<IDemux>* _aidl_return) {
157     ALOGV("%s", __FUNCTION__);
158 
159     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     }
167 
168     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     }
175 }
176 
getDemuxCaps(DemuxCapabilities * _aidl_return)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 
185     // 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 
197     return ::ndk::ScopedAStatus::ok();
198 }
199 
openDescrambler(std::shared_ptr<IDescrambler> * _aidl_return)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 
getFrontendInfo(int32_t in_frontendId,FrontendInfo * _aidl_return)208 ::ndk::ScopedAStatus Tuner::getFrontendInfo(int32_t in_frontendId, FrontendInfo* _aidl_return) {
209     ALOGV("%s", __FUNCTION__);
210 
211     if (in_frontendId < 0 || in_frontendId >= mFrontendSize) {
212         return ::ndk::ScopedAStatus::fromServiceSpecificError(
213                 static_cast<int32_t>(Result::INVALID_ARGUMENT));
214     }
215 
216     mFrontends[in_frontendId]->getFrontendInfo(_aidl_return);
217     return ::ndk::ScopedAStatus::ok();
218 }
219 
getLnbIds(std::vector<int32_t> * _aidl_return)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 
openLnbById(int32_t in_lnbId,std::shared_ptr<ILnb> * _aidl_return)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;
236         return ::ndk::ScopedAStatus::fromServiceSpecificError(
237                 static_cast<int32_t>(Result::INVALID_ARGUMENT));
238     }
239 
240     *_aidl_return = mLnbs[in_lnbId];
241     return ::ndk::ScopedAStatus::ok();
242 }
243 
getFrontendById(int32_t frontendId)244 std::shared_ptr<Frontend> Tuner::getFrontendById(int32_t frontendId) {
245     ALOGV("%s", __FUNCTION__);
246 
247     return mFrontends[frontendId];
248 }
249 
openLnbByName(const std::string &,std::vector<int32_t> * out_lnbId,std::shared_ptr<ILnb> * _aidl_return)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 
setLna(bool)261 ::ndk::ScopedAStatus Tuner::setLna(bool /* in_bEnable */) {
262     ALOGV("%s", __FUNCTION__);
263 
264     return ::ndk::ScopedAStatus::ok();
265 }
266 
setMaxNumberOfFrontends(FrontendType in_frontendType,int32_t in_maxNumber)267 ::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 
getMaxNumberOfFrontends(FrontendType in_frontendType,int32_t * _aidl_return)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 
isLnaSupported(bool * _aidl_return)286 ::ndk::ScopedAStatus Tuner::isLnaSupported(bool* _aidl_return) {
287     ALOGV("%s", __FUNCTION__);
288 
289     *_aidl_return = true;
290     return ::ndk::ScopedAStatus::ok();
291 }
292 
dump(int fd,const char ** args,uint32_t numArgs)293 binder_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);
299         }
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 
setFrontendAsDemuxSource(int32_t frontendId,int32_t demuxId)317 void 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 
removeDemux(int32_t demuxId)324 void 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     }
332     mDemuxes[demuxId]->setInUse(false);
333 }
334 
removeFrontend(int32_t frontendId)335 void Tuner::removeFrontend(int32_t frontendId) {
336     map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
337     if (it != mFrontendToDemux.end()) {
338         mDemuxes[it->second]->setInUse(false);
339     }
340     mFrontendToDemux.erase(frontendId);
341 }
342 
frontendStopTune(int32_t frontendId)343 void 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 
frontendStartTune(int32_t frontendId)352 void 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
366