blob: 14393a1081c6fa87f2843eaa7b0731eb761b811e [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
Amy Zhangb5809be2021-01-26 16:27:23 -0800238 return NULL;
239}
Amy Zhangb0f63ab2021-01-06 17:19:27 -0800240
Amy Zhangd3d57b42021-01-07 11:14:43 -0800241sp<LnbClient> TunerClient::openLnb(int lnbHandle) {
242 if (mTunerService != NULL) {
Amy Zhang3ac0a3e2021-01-14 18:55:10 -0800243 shared_ptr<ITunerLnb> tunerLnb;
Amy Zhang4a07e802021-01-21 17:10:21 -0800244 Status s = mTunerService->openLnb(lnbHandle, &tunerLnb);
245 if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
246 return NULL;
247 }
Amy Zhang3ac0a3e2021-01-14 18:55:10 -0800248 return new LnbClient(tunerLnb);
Amy Zhangd3d57b42021-01-07 11:14:43 -0800249 }
250
251 if (mTuner != NULL) {
252 int id = getResourceIdFromHandle(lnbHandle, LNB);
Amy Zhang3ac0a3e2021-01-14 18:55:10 -0800253 sp<LnbClient> lnbClient = new LnbClient(NULL);
Amy Zhangd3d57b42021-01-07 11:14:43 -0800254 sp<ILnb> hidlLnb = openHidlLnbById(id);
255 if (hidlLnb != NULL) {
256 lnbClient->setHidlLnb(hidlLnb);
257 lnbClient->setId(id);
258 return lnbClient;
259 }
260 }
261
Amy Zhangb0f63ab2021-01-06 17:19:27 -0800262 return NULL;
263}
264
Amy Zhangd3d57b42021-01-07 11:14:43 -0800265sp<LnbClient> TunerClient::openLnbByName(string lnbName) {
266 if (mTunerService != NULL) {
Amy Zhang3ac0a3e2021-01-14 18:55:10 -0800267 shared_ptr<ITunerLnb> tunerLnb;
Amy Zhang4a07e802021-01-21 17:10:21 -0800268 Status s = mTunerService->openLnbByName(lnbName, &tunerLnb);
269 if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
270 return NULL;
271 }
Amy Zhang3ac0a3e2021-01-14 18:55:10 -0800272 return new LnbClient(tunerLnb);
Amy Zhangd3d57b42021-01-07 11:14:43 -0800273 }
274
275 if (mTuner != NULL) {
Amy Zhang3ac0a3e2021-01-14 18:55:10 -0800276 sp<LnbClient> lnbClient = new LnbClient(NULL);
Amy Zhangd3d57b42021-01-07 11:14:43 -0800277 LnbId id;
278 sp<ILnb> hidlLnb = openHidlLnbByName(lnbName, id);
279 if (hidlLnb != NULL) {
280 lnbClient->setHidlLnb(hidlLnb);
281 lnbClient->setId(id);
282 return lnbClient;
283 }
284 }
285
Amy Zhangb0f63ab2021-01-06 17:19:27 -0800286 return NULL;
287}
288
Amy Zhangbf68a162020-11-23 17:42:40 -0800289/////////////// TunerClient Helper Methods ///////////////////////
290
Amy Zhang39a3fa42020-12-21 16:56:03 -0800291void TunerClient::updateTunerResources() {
292 if (mTuner == NULL) {
293 return;
294 }
295
296 // Connect with Tuner Resource Manager.
297 ::ndk::SpAIBinder binder(AServiceManager_getService("tv_tuner_resource_mgr"));
298 mTunerResourceManager = ITunerResourceManager::fromBinder(binder);
299
300 updateFrontendResources();
301 updateLnbResources();
302 // TODO: update Demux, Descrambler.
303}
304
305void TunerClient::updateFrontendResources() {
306 vector<FrontendId> ids = getFrontendIds();
307 if (ids.size() == 0) {
308 return;
309 }
310 vector<TunerFrontendInfo> infos;
311 for (int i = 0; i < ids.size(); i++) {
312 shared_ptr<FrontendInfo> frontendInfo = getFrontendInfo((int)ids[i]);
313 if (frontendInfo == NULL) {
314 continue;
315 }
316 TunerFrontendInfo tunerFrontendInfo{
317 .handle = getResourceHandleFromId((int)ids[i], FRONTEND),
Amy Zhangd1fd5ac2021-01-13 16:30:24 -0800318 .type = static_cast<int>(frontendInfo->type),
Amy Zhang39a3fa42020-12-21 16:56:03 -0800319 .exclusiveGroupId = static_cast<int>(frontendInfo->exclusiveGroupId),
320 };
321 infos.push_back(tunerFrontendInfo);
322 }
323 mTunerResourceManager->setFrontendInfoList(infos);
324}
325
326void TunerClient::updateLnbResources() {
327 vector<int> handles = getLnbHandles();
328 if (handles.size() == 0) {
329 return;
330 }
331 mTunerResourceManager->setLnbInfoList(handles);
332}
333
Amy Zhangbf68a162020-11-23 17:42:40 -0800334sp<ITuner> TunerClient::getHidlTuner() {
335 if (mTuner == NULL) {
336 mTunerVersion = 0;
337 mTuner_1_1 = ::android::hardware::tv::tuner::V1_1::ITuner::getService();
338
339 if (mTuner_1_1 == NULL) {
340 ALOGW("Failed to get tuner 1.1 service.");
341 mTuner = ITuner::getService();
342 if (mTuner == NULL) {
343 ALOGW("Failed to get tuner 1.0 service.");
344 } else {
345 mTunerVersion = 1 << 16;
346 }
347 } else {
348 mTuner = static_cast<sp<ITuner>>(mTuner_1_1);
349 mTunerVersion = ((1 << 16) | 1);
350 }
351 }
352 return mTuner;
353}
354
Amy Zhang210c26a2021-01-12 11:25:27 -0800355sp<IFrontend> TunerClient::openHidlFrontendById(int id) {
Amy Zhangbf68a162020-11-23 17:42:40 -0800356 sp<IFrontend> fe;
357 Result res;
Amy Zhangbf68a162020-11-23 17:42:40 -0800358 mTuner->openFrontendById(id, [&](Result r, const sp<IFrontend>& frontend) {
359 fe = frontend;
360 res = r;
361 });
362 if (res != Result::SUCCESS || fe == nullptr) {
363 ALOGE("Failed to open frontend");
364 return NULL;
365 }
366 return fe;
367}
368
369Result TunerClient::getHidlFrontendInfo(int id, FrontendInfo& feInfo) {
370 Result res;
371 mTuner->getFrontendInfo(id, [&](Result r, const FrontendInfo& info) {
372 feInfo = info;
373 res = r;
374 });
375 return res;
376}
377
Amy Zhang921fd432021-01-07 13:18:27 -0800378sp<IDemux> TunerClient::openHidlDemux(int& demuxId) {
Amy Zhang6bfeaa02020-11-30 15:16:39 -0800379 sp<IDemux> demux;
380 Result res;
381
Amy Zhang921fd432021-01-07 13:18:27 -0800382 mTuner->openDemux([&](Result result, uint32_t id, const sp<IDemux>& demuxSp) {
Amy Zhang6bfeaa02020-11-30 15:16:39 -0800383 demux = demuxSp;
Amy Zhang921fd432021-01-07 13:18:27 -0800384 demuxId = id;
Amy Zhang6bfeaa02020-11-30 15:16:39 -0800385 res = result;
386 });
387 if (res != Result::SUCCESS || demux == nullptr) {
388 ALOGE("Failed to open demux");
389 return NULL;
390 }
391 return demux;
392}
393
Amy Zhangd3d57b42021-01-07 11:14:43 -0800394sp<ILnb> TunerClient::openHidlLnbById(int id) {
395 sp<ILnb> lnb;
396 Result res;
397
398 mTuner->openLnbById(id, [&](Result r, const sp<ILnb>& lnbSp) {
399 res = r;
400 lnb = lnbSp;
401 });
402 if (res != Result::SUCCESS || lnb == nullptr) {
403 ALOGE("Failed to open lnb by id");
404 return NULL;
405 }
406 return lnb;
407}
408
409sp<ILnb> TunerClient::openHidlLnbByName(string name, LnbId& lnbId) {
410 sp<ILnb> lnb;
411 Result res;
412
413 mTuner->openLnbByName(name, [&](Result r, LnbId id, const sp<ILnb>& lnbSp) {
414 res = r;
415 lnb = lnbSp;
416 lnbId = id;
417 });
418 if (res != Result::SUCCESS || lnb == nullptr) {
419 ALOGE("Failed to open lnb by name");
420 return NULL;
421 }
422 return lnb;
423}
424
Amy Zhang39a3fa42020-12-21 16:56:03 -0800425vector<int> TunerClient::getLnbHandles() {
426 vector<int> lnbHandles;
Amy Zhang39a3fa42020-12-21 16:56:03 -0800427 if (mTuner != NULL) {
428 Result res;
429 vector<LnbId> lnbIds;
430 mTuner->getLnbIds([&](Result r, const hardware::hidl_vec<LnbId>& ids) {
431 lnbIds = ids;
432 res = r;
433 });
434 if (res != Result::SUCCESS || lnbIds.size() == 0) {
435 ALOGW("Lnb isn't available");
436 } else {
437 for (int i = 0; i < lnbIds.size(); i++) {
438 lnbHandles.push_back(getResourceHandleFromId((int)lnbIds[i], LNB));
439 }
440 }
441 }
442
443 return lnbHandles;
444}
445
Amy Zhang4a07e802021-01-21 17:10:21 -0800446sp<IDescrambler> TunerClient::openHidlDescrambler() {
447 sp<IDescrambler> descrambler;
448 Result res;
449
450 mTuner->openDescrambler([&](Result r, const sp<IDescrambler>& descramblerSp) {
451 res = r;
452 descrambler = descramblerSp;
453 });
454
455 if (res != Result::SUCCESS || descrambler == NULL) {
456 return NULL;
457 }
458
459 return descrambler;
460}
461
Amy Zhangd1fd5ac2021-01-13 16:30:24 -0800462FrontendInfo TunerClient::FrontendInfoAidlToHidl(TunerFrontendInfo aidlFrontendInfo) {
Amy Zhangbf68a162020-11-23 17:42:40 -0800463 FrontendInfo hidlFrontendInfo {
464 .type = static_cast<FrontendType>(aidlFrontendInfo.type),
465 .minFrequency = static_cast<uint32_t>(aidlFrontendInfo.minFrequency),
466 .maxFrequency = static_cast<uint32_t>(aidlFrontendInfo.maxFrequency),
467 .minSymbolRate = static_cast<uint32_t>(aidlFrontendInfo.minSymbolRate),
468 .maxSymbolRate = static_cast<uint32_t>(aidlFrontendInfo.maxSymbolRate),
469 .acquireRange = static_cast<uint32_t>(aidlFrontendInfo.acquireRange),
470 .exclusiveGroupId = static_cast<uint32_t>(aidlFrontendInfo.exclusiveGroupId),
471 };
472 // TODO: handle Frontend caps
473
474 return hidlFrontendInfo;
475}
Amy Zhang210c26a2021-01-12 11:25:27 -0800476
477int TunerClient::getResourceIdFromHandle(int handle, int /*resourceType*/) {
478 return (handle & 0x00ff0000) >> 16;
479}
480
481int TunerClient::getResourceHandleFromId(int id, int resourceType) {
482 // TODO: build up randomly generated id to handle mapping
483 return (resourceType & 0x000000ff) << 24
484 | (id << 16)
485 | (mResourceRequestCount++ & 0xffff);
486}
Amy Zhangbf68a162020-11-23 17:42:40 -0800487} // namespace android