• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 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 "TunerService"
19 
20 #include "TunerService.h"
21 
22 #include <aidl/android/hardware/tv/tuner/IDemux.h>
23 #include <aidl/android/hardware/tv/tuner/IDescrambler.h>
24 #include <aidl/android/hardware/tv/tuner/IFrontend.h>
25 #include <aidl/android/hardware/tv/tuner/ILnb.h>
26 #include <aidl/android/hardware/tv/tuner/Result.h>
27 #include <android/binder_manager.h>
28 #include <binder/IPCThreadState.h>
29 #include <binder/PermissionCache.h>
30 #include <utils/Log.h>
31 
32 #include <string>
33 
34 #include "TunerDemux.h"
35 #include "TunerDescrambler.h"
36 #include "TunerFrontend.h"
37 #include "TunerHelper.h"
38 #include "TunerLnb.h"
39 
40 using ::aidl::android::hardware::tv::tuner::IDemux;
41 using ::aidl::android::hardware::tv::tuner::IDescrambler;
42 using ::aidl::android::hardware::tv::tuner::IFrontend;
43 using ::aidl::android::hardware::tv::tuner::Result;
44 using ::android::IPCThreadState;
45 using ::android::PermissionCache;
46 using ::android::sp;
47 
48 namespace aidl {
49 namespace android {
50 namespace media {
51 namespace tv {
52 namespace tuner {
53 
54 shared_ptr<TunerService> TunerService::sTunerService = nullptr;
55 
TunerService()56 TunerService::TunerService() {
57     if (!TunerHelper::checkTunerFeature()) {
58         ALOGD("Device doesn't have tuner hardware.");
59         return;
60     }
61 
62     updateTunerResources();
63 }
64 
~TunerService()65 TunerService::~TunerService() {}
66 
instantiate()67 binder_status_t TunerService::instantiate() {
68     sTunerService = ::ndk::SharedRefBase::make<TunerService>();
69     return AServiceManager_addService(sTunerService->asBinder().get(), getServiceName());
70 }
71 
getTunerService()72 shared_ptr<TunerService> TunerService::getTunerService() {
73     return sTunerService;
74 }
75 
hasITuner()76 bool TunerService::hasITuner() {
77     ALOGV("hasITuner");
78     if (mTuner != nullptr) {
79         return true;
80     }
81     const string statsServiceName = string() + ITuner::descriptor + "/default";
82     if (AServiceManager_isDeclared(statsServiceName.c_str())) {
83         ::ndk::SpAIBinder binder(AServiceManager_waitForService(statsServiceName.c_str()));
84         mTuner = ITuner::fromBinder(binder);
85     } else {
86         mTuner = nullptr;
87         ALOGE("Failed to get Tuner HAL Service");
88         return false;
89     }
90 
91     mTunerVersion = TUNER_HAL_VERSION_2_0;
92     // TODO: Enable this after Tuner HAL is frozen.
93     // if (mTuner->getInterfaceVersion(&mTunerVersion).isOk()) {
94     //  // Tuner AIDL HAL version 1 will be Tuner HAL 2.0
95     //  mTunerVersion = (mTunerVersion + 1) << 16;
96     //}
97 
98     return true;
99 }
100 
openDemux(int32_t,shared_ptr<ITunerDemux> * _aidl_return)101 ::ndk::ScopedAStatus TunerService::openDemux(int32_t /* in_demuxHandle */,
102                                              shared_ptr<ITunerDemux>* _aidl_return) {
103     ALOGV("openDemux");
104     if (!hasITuner()) {
105         return ::ndk::ScopedAStatus::fromServiceSpecificError(
106                 static_cast<int32_t>(Result::UNAVAILABLE));
107     }
108     vector<int32_t> id;
109     shared_ptr<IDemux> demux;
110     auto status = mTuner->openDemux(&id, &demux);
111     if (status.isOk()) {
112         *_aidl_return = ::ndk::SharedRefBase::make<TunerDemux>(demux, id[0]);
113     }
114 
115     return status;
116 }
117 
getDemuxCaps(DemuxCapabilities * _aidl_return)118 ::ndk::ScopedAStatus TunerService::getDemuxCaps(DemuxCapabilities* _aidl_return) {
119     ALOGV("getDemuxCaps");
120     if (!hasITuner()) {
121         return ::ndk::ScopedAStatus::fromServiceSpecificError(
122                 static_cast<int32_t>(Result::UNAVAILABLE));
123     }
124 
125     return mTuner->getDemuxCaps(_aidl_return);
126 }
127 
getFrontendIds(vector<int32_t> * ids)128 ::ndk::ScopedAStatus TunerService::getFrontendIds(vector<int32_t>* ids) {
129     if (!hasITuner()) {
130         return ::ndk::ScopedAStatus::fromServiceSpecificError(
131                 static_cast<int32_t>(Result::UNAVAILABLE));
132     }
133 
134     return mTuner->getFrontendIds(ids);
135 }
136 
getFrontendInfo(int32_t id,FrontendInfo * _aidl_return)137 ::ndk::ScopedAStatus TunerService::getFrontendInfo(int32_t id, FrontendInfo* _aidl_return) {
138     if (!hasITuner()) {
139         ALOGE("ITuner service is not init.");
140         return ::ndk::ScopedAStatus::fromServiceSpecificError(
141                 static_cast<int32_t>(Result::UNAVAILABLE));
142     }
143 
144     return mTuner->getFrontendInfo(id, _aidl_return);
145 }
146 
openFrontend(int32_t frontendHandle,shared_ptr<ITunerFrontend> * _aidl_return)147 ::ndk::ScopedAStatus TunerService::openFrontend(int32_t frontendHandle,
148                                                 shared_ptr<ITunerFrontend>* _aidl_return) {
149     if (!hasITuner()) {
150         ALOGE("ITuner service is not init.");
151         return ::ndk::ScopedAStatus::fromServiceSpecificError(
152                 static_cast<int32_t>(Result::UNAVAILABLE));
153     }
154 
155     int id = TunerHelper::getResourceIdFromHandle(frontendHandle, FRONTEND);
156     shared_ptr<IFrontend> frontend;
157     auto status = mTuner->openFrontendById(id, &frontend);
158     if (status.isOk()) {
159         *_aidl_return = ::ndk::SharedRefBase::make<TunerFrontend>(frontend, id);
160     }
161 
162     return status;
163 }
164 
openLnb(int lnbHandle,shared_ptr<ITunerLnb> * _aidl_return)165 ::ndk::ScopedAStatus TunerService::openLnb(int lnbHandle, shared_ptr<ITunerLnb>* _aidl_return) {
166     if (!hasITuner()) {
167         ALOGD("get ITuner failed");
168         return ::ndk::ScopedAStatus::fromServiceSpecificError(
169                 static_cast<int32_t>(Result::UNAVAILABLE));
170     }
171 
172     shared_ptr<ILnb> lnb;
173     int id = TunerHelper::getResourceIdFromHandle(lnbHandle, LNB);
174     auto status = mTuner->openLnbById(id, &lnb);
175     if (status.isOk()) {
176         *_aidl_return = ::ndk::SharedRefBase::make<TunerLnb>(lnb, id);
177     }
178 
179     return status;
180 }
181 
openLnbByName(const string & lnbName,shared_ptr<ITunerLnb> * _aidl_return)182 ::ndk::ScopedAStatus TunerService::openLnbByName(const string& lnbName,
183                                                  shared_ptr<ITunerLnb>* _aidl_return) {
184     if (!hasITuner()) {
185         ALOGE("get ITuner failed");
186         return ::ndk::ScopedAStatus::fromServiceSpecificError(
187                 static_cast<int32_t>(Result::UNAVAILABLE));
188     }
189 
190     vector<int32_t> id;
191     shared_ptr<ILnb> lnb;
192     auto status = mTuner->openLnbByName(lnbName, &id, &lnb);
193     if (status.isOk()) {
194         *_aidl_return = ::ndk::SharedRefBase::make<TunerLnb>(lnb, id[0]);
195     }
196 
197     return ::ndk::ScopedAStatus::ok();
198 }
199 
openDescrambler(int32_t,shared_ptr<ITunerDescrambler> * _aidl_return)200 ::ndk::ScopedAStatus TunerService::openDescrambler(int32_t /*descramblerHandle*/,
201                                                    shared_ptr<ITunerDescrambler>* _aidl_return) {
202     if (!hasITuner()) {
203         ALOGD("get ITuner failed");
204         return ::ndk::ScopedAStatus::fromServiceSpecificError(
205                 static_cast<int32_t>(Result::UNAVAILABLE));
206     }
207 
208     shared_ptr<IDescrambler> descrambler;
209     // int id = TunerHelper::getResourceIdFromHandle(descramblerHandle, DESCRAMBLER);
210     auto status = mTuner->openDescrambler(&descrambler);
211     if (status.isOk()) {
212         *_aidl_return = ::ndk::SharedRefBase::make<TunerDescrambler>(descrambler);
213     }
214 
215     return status;
216 }
217 
getTunerHalVersion(int * _aidl_return)218 ::ndk::ScopedAStatus TunerService::getTunerHalVersion(int* _aidl_return) {
219     hasITuner();
220     *_aidl_return = mTunerVersion;
221     return ::ndk::ScopedAStatus::ok();
222 }
223 
openSharedFilter(const string & in_filterToken,const shared_ptr<ITunerFilterCallback> & in_cb,shared_ptr<ITunerFilter> * _aidl_return)224 ::ndk::ScopedAStatus TunerService::openSharedFilter(const string& in_filterToken,
225                                                     const shared_ptr<ITunerFilterCallback>& in_cb,
226                                                     shared_ptr<ITunerFilter>* _aidl_return) {
227     if (!hasITuner()) {
228         ALOGE("get ITuner failed");
229         return ::ndk::ScopedAStatus::fromServiceSpecificError(
230                 static_cast<int32_t>(Result::UNAVAILABLE));
231     }
232 
233     if (!PermissionCache::checkCallingPermission(sSharedFilterPermission)) {
234         ALOGE("Request requires android.permission.ACCESS_TV_SHARED_FILTER");
235         return ::ndk::ScopedAStatus::fromServiceSpecificError(
236                 static_cast<int32_t>(Result::UNAVAILABLE));
237     }
238 
239     Mutex::Autolock _l(mSharedFiltersLock);
240     if (mSharedFilters.find(in_filterToken) == mSharedFilters.end()) {
241         *_aidl_return = nullptr;
242         ALOGD("fail to find %s", in_filterToken.c_str());
243         return ::ndk::ScopedAStatus::fromServiceSpecificError(
244                 static_cast<int32_t>(Result::INVALID_STATE));
245     }
246 
247     shared_ptr<TunerFilter> filter = mSharedFilters.at(in_filterToken);
248     IPCThreadState* ipc = IPCThreadState::self();
249     const int pid = ipc->getCallingPid();
250     if (!filter->isSharedFilterAllowed(pid)) {
251         *_aidl_return = nullptr;
252         ALOGD("shared filter %s is opened in the same process", in_filterToken.c_str());
253         return ::ndk::ScopedAStatus::fromServiceSpecificError(
254                 static_cast<int32_t>(Result::INVALID_STATE));
255     }
256 
257     filter->attachSharedFilterCallback(in_cb);
258 
259     *_aidl_return = filter;
260     return ::ndk::ScopedAStatus::ok();
261 }
262 
setLna(bool bEnable)263 ::ndk::ScopedAStatus TunerService::setLna(bool bEnable) {
264     if (!hasITuner()) {
265         ALOGD("get ITuner failed");
266         return ::ndk::ScopedAStatus::fromServiceSpecificError(
267                 static_cast<int32_t>(Result::UNAVAILABLE));
268     }
269 
270     return mTuner->setLna(bEnable);
271 }
272 
setMaxNumberOfFrontends(FrontendType in_frontendType,int32_t in_maxNumber)273 ::ndk::ScopedAStatus TunerService::setMaxNumberOfFrontends(FrontendType in_frontendType,
274                                                            int32_t in_maxNumber) {
275     if (!hasITuner()) {
276         ALOGD("get ITuner failed");
277         return ::ndk::ScopedAStatus::fromServiceSpecificError(
278                 static_cast<int32_t>(Result::UNAVAILABLE));
279     }
280 
281     return mTuner->setMaxNumberOfFrontends(in_frontendType, in_maxNumber);
282 }
283 
getMaxNumberOfFrontends(FrontendType in_frontendType,int32_t * _aidl_return)284 ::ndk::ScopedAStatus TunerService::getMaxNumberOfFrontends(FrontendType in_frontendType,
285                                                            int32_t* _aidl_return) {
286     if (!hasITuner()) {
287         ALOGD("get ITuner failed");
288         return ::ndk::ScopedAStatus::fromServiceSpecificError(
289                 static_cast<int32_t>(Result::UNAVAILABLE));
290     }
291 
292     return mTuner->getMaxNumberOfFrontends(in_frontendType, _aidl_return);
293 }
294 
addFilterToShared(const shared_ptr<TunerFilter> & sharedFilter)295 string TunerService::addFilterToShared(const shared_ptr<TunerFilter>& sharedFilter) {
296     Mutex::Autolock _l(mSharedFiltersLock);
297 
298     // Use sharedFilter address as token.
299     string token = to_string(reinterpret_cast<std::uintptr_t>(sharedFilter.get()));
300     mSharedFilters[token] = sharedFilter;
301     return token;
302 }
303 
removeSharedFilter(const shared_ptr<TunerFilter> & sharedFilter)304 void TunerService::removeSharedFilter(const shared_ptr<TunerFilter>& sharedFilter) {
305     Mutex::Autolock _l(mSharedFiltersLock);
306 
307     // Use sharedFilter address as token.
308     mSharedFilters.erase(to_string(reinterpret_cast<std::uintptr_t>(sharedFilter.get())));
309 }
310 
updateTunerResources()311 void TunerService::updateTunerResources() {
312     if (!hasITuner()) {
313         ALOGE("Failed to updateTunerResources");
314         return;
315     }
316 
317     TunerHelper::updateTunerResources(getTRMFrontendInfos(), getTRMLnbHandles());
318 }
319 
getTRMFrontendInfos()320 vector<TunerFrontendInfo> TunerService::getTRMFrontendInfos() {
321     vector<TunerFrontendInfo> infos;
322     vector<int32_t> ids;
323     auto status = mTuner->getFrontendIds(&ids);
324     if (!status.isOk()) {
325         return infos;
326     }
327 
328     for (int i = 0; i < ids.size(); i++) {
329         FrontendInfo frontendInfo;
330         auto res = mTuner->getFrontendInfo(ids[i], &frontendInfo);
331         if (!res.isOk()) {
332             continue;
333         }
334         TunerFrontendInfo tunerFrontendInfo{
335                 .handle = TunerHelper::getResourceHandleFromId((int)ids[i], FRONTEND),
336                 .type = static_cast<int>(frontendInfo.type),
337                 .exclusiveGroupId = frontendInfo.exclusiveGroupId,
338         };
339         infos.push_back(tunerFrontendInfo);
340     }
341 
342     return infos;
343 }
344 
getTRMLnbHandles()345 vector<int32_t> TunerService::getTRMLnbHandles() {
346     vector<int32_t> lnbHandles;
347     if (mTuner != nullptr) {
348         vector<int32_t> lnbIds;
349         auto res = mTuner->getLnbIds(&lnbIds);
350         if (res.isOk()) {
351             for (int i = 0; i < lnbIds.size(); i++) {
352                 lnbHandles.push_back(TunerHelper::getResourceHandleFromId(lnbIds[i], LNB));
353             }
354         }
355     }
356 
357     return lnbHandles;
358 }
359 
360 }  // namespace tuner
361 }  // namespace tv
362 }  // namespace media
363 }  // namespace android
364 }  // namespace aidl
365