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