blob: 4498f54b71cc5f94485cf126952986c5d4fc61c1 [file] [log] [blame]
Amy Zhangbf68a162020-11-23 17:42:40 -08001/*
2 * Copyright 2020 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_TAG "TunerClient"
18
19#include <android/binder_manager.h>
20#include <android-base/logging.h>
21#include <utils/Log.h>
22
23#include "TunerClient.h"
24
25using ::android::hardware::tv::tuner::V1_0::FrontendId;
26using ::android::hardware::tv::tuner::V1_0::FrontendType;
27
28namespace android {
29
30sp<ITuner> TunerClient::mTuner;
31sp<::android::hardware::tv::tuner::V1_1::ITuner> TunerClient::mTuner_1_1;
32shared_ptr<ITunerService> TunerClient::mTunerService;
33int TunerClient::mTunerVersion;
34
35/////////////// TunerClient ///////////////////////
36
37TunerClient::TunerClient() {
38 // Get HIDL Tuner in migration stage.
39 getHidlTuner();
Amy Zhang9eeba432021-01-21 12:52:05 -080040 if (mTuner != NULL) {
41 updateTunerResources();
42 }
Amy Zhangbf68a162020-11-23 17:42:40 -080043 // Connect with Tuner Service.
44 ::ndk::SpAIBinder binder(AServiceManager_getService("media.tuner"));
45 mTunerService = ITunerService::fromBinder(binder);
Amy Zhang9a9ed602020-12-07 16:37:33 -080046 // TODO: Remove after JNI migration is done.
47 mTunerService = NULL;
Amy Zhangbf68a162020-11-23 17:42:40 -080048 if (mTunerService == NULL) {
49 ALOGE("Failed to get tuner service");
Amy Zhang9eeba432021-01-21 12:52:05 -080050 } else {
51 // TODO: b/178124017 update TRM in TunerService independently.
52 mTunerService->updateTunerResources();
Amy Zhangbf68a162020-11-23 17:42:40 -080053 }
54}
55
56TunerClient::~TunerClient() {
57 mTuner = NULL;
58 mTuner_1_1 = NULL;
59 mTunerVersion = 0;
60 mTunerService = NULL;
61}
62
63vector<FrontendId> TunerClient::getFrontendIds() {
64 vector<FrontendId> ids;
shubang68f32a32020-12-29 00:34:24 -080065
66 if (mTunerService != NULL) {
67 vector<int32_t> v;
Amy Zhang9eeba432021-01-21 12:52:05 -080068 Status s = mTunerService->getFrontendIds(&v);
Amy Zhang4a07e802021-01-21 17:10:21 -080069 if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS || v.size() == 0) {
shubang68f32a32020-12-29 00:34:24 -080070 ids.clear();
71 return ids;
72 }
73 for (int32_t id : v) {
74 ids.push_back(static_cast<FrontendId>(id));
75 }
76 return ids;
77 }
Amy Zhangbf68a162020-11-23 17:42:40 -080078
79 if (mTuner != NULL) {
80 Result res;
81 mTuner->getFrontendIds([&](Result r, const hardware::hidl_vec<FrontendId>& frontendIds) {
82 res = r;
83 ids = frontendIds;
84 });
85 if (res != Result::SUCCESS || ids.size() == 0) {
86 ALOGW("Frontend ids not available");
87 ids.clear();
88 return ids;
89 }
90 return ids;
91 }
92
93 return ids;
94}
95
96
97sp<FrontendClient> TunerClient::openFrontend(int frontendHandle) {
98 if (mTunerService != NULL) {
Amy Zhangbf68a162020-11-23 17:42:40 -080099 shared_ptr<ITunerFrontend> tunerFrontend;
Amy Zhang4a07e802021-01-21 17:10:21 -0800100 Status s = mTunerService->openFrontend(frontendHandle, &tunerFrontend);
101 if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS
102 || tunerFrontend == NULL) {
Amy Zhangb9f3cab2021-01-13 15:24:14 -0800103 return NULL;
104 }
105 int id;
Amy Zhang4a07e802021-01-21 17:10:21 -0800106 s = tunerFrontend->getFrontendId(&id);
107 if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
108 return NULL;
109 }
Amy Zhangd1fd5ac2021-01-13 16:30:24 -0800110 TunerFrontendInfo aidlFrontendInfo;
Amy Zhang4a07e802021-01-21 17:10:21 -0800111 s = mTunerService->getFrontendInfo(id, &aidlFrontendInfo);
112 if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
113 return NULL;
114 }
Amy Zhangb9f3cab2021-01-13 15:24:14 -0800115 return new FrontendClient(tunerFrontend, frontendHandle, aidlFrontendInfo.type);
Amy Zhangbf68a162020-11-23 17:42:40 -0800116 }
117
118 if (mTuner != NULL) {
Amy Zhang210c26a2021-01-12 11:25:27 -0800119 int id = getResourceIdFromHandle(frontendHandle, FRONTEND);
120 sp<IFrontend> hidlFrontend = openHidlFrontendById(id);
Amy Zhangbf68a162020-11-23 17:42:40 -0800121 if (hidlFrontend != NULL) {
Amy Zhangb9f3cab2021-01-13 15:24:14 -0800122 FrontendInfo hidlInfo;
123 Result res = getHidlFrontendInfo(id, hidlInfo);
124 if (res != Result::SUCCESS) {
125 return NULL;
126 }
127 sp<FrontendClient> frontendClient = new FrontendClient(NULL, id, (int)hidlInfo.type);
Amy Zhangbf68a162020-11-23 17:42:40 -0800128 frontendClient->setHidlFrontend(hidlFrontend);
129 return frontendClient;
130 }
131 }
132
133 return NULL;
134}
135
136shared_ptr<FrontendInfo> TunerClient::getFrontendInfo(int id) {
137 if (mTunerService != NULL) {
Amy Zhangd1fd5ac2021-01-13 16:30:24 -0800138 TunerFrontendInfo aidlFrontendInfo;
Amy Zhangbf68a162020-11-23 17:42:40 -0800139 // TODO: handle error code
Amy Zhang4a07e802021-01-21 17:10:21 -0800140 Status s = mTunerService->getFrontendInfo(id, &aidlFrontendInfo);
141 if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
142 return NULL;
143 }
Amy Zhangbf68a162020-11-23 17:42:40 -0800144 return make_shared<FrontendInfo>(FrontendInfoAidlToHidl(aidlFrontendInfo));
145 }
146
147 if (mTuner != NULL) {
148 FrontendInfo hidlInfo;
149 Result res = getHidlFrontendInfo(id, hidlInfo);
150 if (res != Result::SUCCESS) {
151 return NULL;
152 }
153 return make_shared<FrontendInfo>(hidlInfo);
154 }
155
156 return NULL;
157}
158
159shared_ptr<FrontendDtmbCapabilities> TunerClient::getFrontendDtmbCapabilities(int id) {
160 // pending aidl interface
161
162 if (mTuner_1_1 != NULL) {
163 Result result;
164 FrontendDtmbCapabilities dtmbCaps;
165 mTuner_1_1->getFrontendDtmbCapabilities(id,
166 [&](Result r, const FrontendDtmbCapabilities& caps) {
167 dtmbCaps = caps;
168 result = r;
169 });
170 if (result == Result::SUCCESS) {
171 return make_shared<FrontendDtmbCapabilities>(dtmbCaps);
172 }
173 }
174
175 return NULL;
176}
177
Amy Zhang4a07e802021-01-21 17:10:21 -0800178sp<DemuxClient> TunerClient::openDemux(int demuxHandle) {
Amy Zhang6bfeaa02020-11-30 15:16:39 -0800179 if (mTunerService != NULL) {
Amy Zhang4a07e802021-01-21 17:10:21 -0800180 shared_ptr<ITunerDemux> tunerDemux;
181 Status s = mTunerService->openDemux(demuxHandle, &tunerDemux);
182 if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
183 return NULL;
184 }
185 return new DemuxClient(tunerDemux);
Amy Zhang6bfeaa02020-11-30 15:16:39 -0800186 }
187
188 if (mTuner != NULL) {
Amy Zhang4a07e802021-01-21 17:10:21 -0800189 sp<DemuxClient> demuxClient = new DemuxClient(NULL);
Amy Zhang921fd432021-01-07 13:18:27 -0800190 int demuxId;
191 sp<IDemux> hidlDemux = openHidlDemux(demuxId);
Amy Zhang6bfeaa02020-11-30 15:16:39 -0800192 if (hidlDemux != NULL) {
193 demuxClient->setHidlDemux(hidlDemux);
Amy Zhang921fd432021-01-07 13:18:27 -0800194 demuxClient->setId(demuxId);
Amy Zhang6bfeaa02020-11-30 15:16:39 -0800195 return demuxClient;
196 }
197 }
198
199 return NULL;
200}
201
Amy Zhang90a50b42021-01-11 16:58:59 -0800202shared_ptr<DemuxCapabilities> TunerClient::getDemuxCaps() {
203 // pending aidl interface
204
205 if (mTuner != NULL) {
206 Result res;
207 DemuxCapabilities caps;
208 mTuner->getDemuxCaps([&](Result r, const DemuxCapabilities& demuxCaps) {
209 caps = demuxCaps;
210 res = r;
211 });
212 if (res == Result::SUCCESS) {
213 return make_shared<DemuxCapabilities>(caps);
214 }
215 }
216
217 return NULL;
Amy Zhangb0f63ab2021-01-06 17:19:27 -0800218}
219
220sp<DescramblerClient> TunerClient::openDescrambler(int /*descramblerHandle*/) {
Amy Zhang921fd432021-01-07 13:18:27 -0800221 if (mTunerService != NULL) {
222 // TODO: handle error code
223 /*shared_ptr<ITunerDescrambler> tunerDescrambler;
224 mTunerService->openDescrambler(demuxHandle, &tunerDescrambler);
225 return new DescramblerClient(tunerDescrambler);*/
226 }
227
228 if (mTuner != NULL) {
229 // TODO: pending aidl interface
230 sp<DescramblerClient> descramblerClient = new DescramblerClient();
231 sp<IDescrambler> hidlDescrambler = openHidlDescrambler();
232 if (hidlDescrambler != NULL) {
233 descramblerClient->setHidlDescrambler(hidlDescrambler);
234 return descramblerClient;
235 }
236 }
237
238 return NULL;}
Amy Zhangb0f63ab2021-01-06 17:19:27 -0800239
Amy Zhangd3d57b42021-01-07 11:14:43 -0800240sp<LnbClient> TunerClient::openLnb(int lnbHandle) {
241 if (mTunerService != NULL) {
Amy Zhang3ac0a3e2021-01-14 18:55:10 -0800242 shared_ptr<ITunerLnb> tunerLnb;
Amy Zhang4a07e802021-01-21 17:10:21 -0800243 Status s = mTunerService->openLnb(lnbHandle, &tunerLnb);
244 if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
245 return NULL;
246 }
Amy Zhang3ac0a3e2021-01-14 18:55:10 -0800247 return new LnbClient(tunerLnb);
Amy Zhangd3d57b42021-01-07 11:14:43 -0800248 }
249
250 if (mTuner != NULL) {
251 int id = getResourceIdFromHandle(lnbHandle, LNB);
Amy Zhang3ac0a3e2021-01-14 18:55:10 -0800252 sp<LnbClient> lnbClient = new LnbClient(NULL);
Amy Zhangd3d57b42021-01-07 11:14:43 -0800253 sp<ILnb> hidlLnb = openHidlLnbById(id);
254 if (hidlLnb != NULL) {
255 lnbClient->setHidlLnb(hidlLnb);
256 lnbClient->setId(id);
257 return lnbClient;
258 }
259 }
260
Amy Zhangb0f63ab2021-01-06 17:19:27 -0800261 return NULL;
262}
263
Amy Zhangd3d57b42021-01-07 11:14:43 -0800264sp<LnbClient> TunerClient::openLnbByName(string lnbName) {
265 if (mTunerService != NULL) {
Amy Zhang3ac0a3e2021-01-14 18:55:10 -0800266 shared_ptr<ITunerLnb> tunerLnb;
Amy Zhang4a07e802021-01-21 17:10:21 -0800267 Status s = mTunerService->openLnbByName(lnbName, &tunerLnb);
268 if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
269 return NULL;
270 }
Amy Zhang3ac0a3e2021-01-14 18:55:10 -0800271 return new LnbClient(tunerLnb);
Amy Zhangd3d57b42021-01-07 11:14:43 -0800272 }
273
274 if (mTuner != NULL) {
Amy Zhang3ac0a3e2021-01-14 18:55:10 -0800275 sp<LnbClient> lnbClient = new LnbClient(NULL);
Amy Zhangd3d57b42021-01-07 11:14:43 -0800276 LnbId id;
277 sp<ILnb> hidlLnb = openHidlLnbByName(lnbName, id);
278 if (hidlLnb != NULL) {
279 lnbClient->setHidlLnb(hidlLnb);
280 lnbClient->setId(id);
281 return lnbClient;
282 }
283 }
284
Amy Zhangb0f63ab2021-01-06 17:19:27 -0800285 return NULL;
286}
287
Amy Zhangbf68a162020-11-23 17:42:40 -0800288/////////////// TunerClient Helper Methods ///////////////////////
289
Amy Zhang39a3fa42020-12-21 16:56:03 -0800290void TunerClient::updateTunerResources() {
291 if (mTuner == NULL) {
292 return;
293 }
294
295 // Connect with Tuner Resource Manager.
296 ::ndk::SpAIBinder binder(AServiceManager_getService("tv_tuner_resource_mgr"));
297 mTunerResourceManager = ITunerResourceManager::fromBinder(binder);
298
299 updateFrontendResources();
300 updateLnbResources();
301 // TODO: update Demux, Descrambler.
302}
303
304void TunerClient::updateFrontendResources() {
305 vector<FrontendId> ids = getFrontendIds();
306 if (ids.size() == 0) {
307 return;
308 }
309 vector<TunerFrontendInfo> infos;
310 for (int i = 0; i < ids.size(); i++) {
311 shared_ptr<FrontendInfo> frontendInfo = getFrontendInfo((int)ids[i]);
312 if (frontendInfo == NULL) {
313 continue;
314 }
315 TunerFrontendInfo tunerFrontendInfo{
316 .handle = getResourceHandleFromId((int)ids[i], FRONTEND),
Amy Zhangd1fd5ac2021-01-13 16:30:24 -0800317 .type = static_cast<int>(frontendInfo->type),
Amy Zhang39a3fa42020-12-21 16:56:03 -0800318 .exclusiveGroupId = static_cast<int>(frontendInfo->exclusiveGroupId),
319 };
320 infos.push_back(tunerFrontendInfo);
321 }
322 mTunerResourceManager->setFrontendInfoList(infos);
323}
324
325void TunerClient::updateLnbResources() {
326 vector<int> handles = getLnbHandles();
327 if (handles.size() == 0) {
328 return;
329 }
330 mTunerResourceManager->setLnbInfoList(handles);
331}
332
Amy Zhangbf68a162020-11-23 17:42:40 -0800333sp<ITuner> TunerClient::getHidlTuner() {
334 if (mTuner == NULL) {
335 mTunerVersion = 0;
336 mTuner_1_1 = ::android::hardware::tv::tuner::V1_1::ITuner::getService();
337
338 if (mTuner_1_1 == NULL) {
339 ALOGW("Failed to get tuner 1.1 service.");
340 mTuner = ITuner::getService();
341 if (mTuner == NULL) {
342 ALOGW("Failed to get tuner 1.0 service.");
343 } else {
344 mTunerVersion = 1 << 16;
345 }
346 } else {
347 mTuner = static_cast<sp<ITuner>>(mTuner_1_1);
348 mTunerVersion = ((1 << 16) | 1);
349 }
350 }
351 return mTuner;
352}
353
Amy Zhang210c26a2021-01-12 11:25:27 -0800354sp<IFrontend> TunerClient::openHidlFrontendById(int id) {
Amy Zhangbf68a162020-11-23 17:42:40 -0800355 sp<IFrontend> fe;
356 Result res;
Amy Zhangbf68a162020-11-23 17:42:40 -0800357 mTuner->openFrontendById(id, [&](Result r, const sp<IFrontend>& frontend) {
358 fe = frontend;
359 res = r;
360 });
361 if (res != Result::SUCCESS || fe == nullptr) {
362 ALOGE("Failed to open frontend");
363 return NULL;
364 }
365 return fe;
366}
367
368Result TunerClient::getHidlFrontendInfo(int id, FrontendInfo& feInfo) {
369 Result res;
370 mTuner->getFrontendInfo(id, [&](Result r, const FrontendInfo& info) {
371 feInfo = info;
372 res = r;
373 });
374 return res;
375}
376
Amy Zhang921fd432021-01-07 13:18:27 -0800377sp<IDemux> TunerClient::openHidlDemux(int& demuxId) {
Amy Zhang6bfeaa02020-11-30 15:16:39 -0800378 sp<IDemux> demux;
379 Result res;
380
Amy Zhang921fd432021-01-07 13:18:27 -0800381 mTuner->openDemux([&](Result result, uint32_t id, const sp<IDemux>& demuxSp) {
Amy Zhang6bfeaa02020-11-30 15:16:39 -0800382 demux = demuxSp;
Amy Zhang921fd432021-01-07 13:18:27 -0800383 demuxId = id;
Amy Zhang6bfeaa02020-11-30 15:16:39 -0800384 res = result;
385 });
386 if (res != Result::SUCCESS || demux == nullptr) {
387 ALOGE("Failed to open demux");
388 return NULL;
389 }
390 return demux;
391}
392
Amy Zhangd3d57b42021-01-07 11:14:43 -0800393sp<ILnb> TunerClient::openHidlLnbById(int id) {
394 sp<ILnb> lnb;
395 Result res;
396
397 mTuner->openLnbById(id, [&](Result r, const sp<ILnb>& lnbSp) {
398 res = r;
399 lnb = lnbSp;
400 });
401 if (res != Result::SUCCESS || lnb == nullptr) {
402 ALOGE("Failed to open lnb by id");
403 return NULL;
404 }
405 return lnb;
406}
407
408sp<ILnb> TunerClient::openHidlLnbByName(string name, LnbId& lnbId) {
409 sp<ILnb> lnb;
410 Result res;
411
412 mTuner->openLnbByName(name, [&](Result r, LnbId id, const sp<ILnb>& lnbSp) {
413 res = r;
414 lnb = lnbSp;
415 lnbId = id;
416 });
417 if (res != Result::SUCCESS || lnb == nullptr) {
418 ALOGE("Failed to open lnb by name");
419 return NULL;
420 }
421 return lnb;
422}
423
Amy Zhang39a3fa42020-12-21 16:56:03 -0800424vector<int> TunerClient::getLnbHandles() {
425 vector<int> lnbHandles;
Amy Zhang39a3fa42020-12-21 16:56:03 -0800426 if (mTuner != NULL) {
427 Result res;
428 vector<LnbId> lnbIds;
429 mTuner->getLnbIds([&](Result r, const hardware::hidl_vec<LnbId>& ids) {
430 lnbIds = ids;
431 res = r;
432 });
433 if (res != Result::SUCCESS || lnbIds.size() == 0) {
434 ALOGW("Lnb isn't available");
435 } else {
436 for (int i = 0; i < lnbIds.size(); i++) {
437 lnbHandles.push_back(getResourceHandleFromId((int)lnbIds[i], LNB));
438 }
439 }
440 }
441
442 return lnbHandles;
443}
444
Amy Zhang4a07e802021-01-21 17:10:21 -0800445sp<IDescrambler> TunerClient::openHidlDescrambler() {
446 sp<IDescrambler> descrambler;
447 Result res;
448
449 mTuner->openDescrambler([&](Result r, const sp<IDescrambler>& descramblerSp) {
450 res = r;
451 descrambler = descramblerSp;
452 });
453
454 if (res != Result::SUCCESS || descrambler == NULL) {
455 return NULL;
456 }
457
458 return descrambler;
459}
460
Amy Zhangd1fd5ac2021-01-13 16:30:24 -0800461FrontendInfo TunerClient::FrontendInfoAidlToHidl(TunerFrontendInfo aidlFrontendInfo) {
Amy Zhangbf68a162020-11-23 17:42:40 -0800462 FrontendInfo hidlFrontendInfo {
463 .type = static_cast<FrontendType>(aidlFrontendInfo.type),
464 .minFrequency = static_cast<uint32_t>(aidlFrontendInfo.minFrequency),
465 .maxFrequency = static_cast<uint32_t>(aidlFrontendInfo.maxFrequency),
466 .minSymbolRate = static_cast<uint32_t>(aidlFrontendInfo.minSymbolRate),
467 .maxSymbolRate = static_cast<uint32_t>(aidlFrontendInfo.maxSymbolRate),
468 .acquireRange = static_cast<uint32_t>(aidlFrontendInfo.acquireRange),
469 .exclusiveGroupId = static_cast<uint32_t>(aidlFrontendInfo.exclusiveGroupId),
470 };
471 // TODO: handle Frontend caps
472
473 return hidlFrontendInfo;
474}
Amy Zhang210c26a2021-01-12 11:25:27 -0800475
476int TunerClient::getResourceIdFromHandle(int handle, int /*resourceType*/) {
477 return (handle & 0x00ff0000) >> 16;
478}
479
480int TunerClient::getResourceHandleFromId(int id, int resourceType) {
481 // TODO: build up randomly generated id to handle mapping
482 return (resourceType & 0x000000ff) << 24
483 | (id << 16)
484 | (mResourceRequestCount++ & 0xffff);
485}
Amy Zhangbf68a162020-11-23 17:42:40 -0800486} // namespace android