blob: 069456dde5970c56dc3a586dc8f4b023074d877d [file] [log] [blame]
Amy Zhangbb94eeb2020-07-09 22:48:04 -07001/*
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 "android.hardware.tv.tuner@1.1-Frontend"
18
19#include "Frontend.h"
Amy Zhang19ed17b2020-08-04 10:23:52 -070020#include <android/hardware/tv/tuner/1.1/IFrontendCallback.h>
Amy Zhangbb94eeb2020-07-09 22:48:04 -070021#include <utils/Log.h>
22
23namespace android {
24namespace hardware {
25namespace tv {
26namespace tuner {
27namespace V1_0 {
28namespace implementation {
29
30Frontend::Frontend(FrontendType type, FrontendId id, sp<Tuner> tuner) {
31 mType = type;
32 mId = id;
33 mTunerService = tuner;
34 // Init callback to nullptr
35 mCallback = nullptr;
36}
37
38Frontend::~Frontend() {}
39
40Return<Result> Frontend::close() {
41 ALOGV("%s", __FUNCTION__);
42 // Reset callback
43 mCallback = nullptr;
44 mIsLocked = false;
Amy Zhang80cb9602020-07-15 13:06:39 -070045 mTunerService->removeFrontend(mId);
Amy Zhangbb94eeb2020-07-09 22:48:04 -070046
47 return Result::SUCCESS;
48}
49
50Return<Result> Frontend::setCallback(const sp<IFrontendCallback>& callback) {
51 ALOGV("%s", __FUNCTION__);
52 if (callback == nullptr) {
53 ALOGW("[ WARN ] Set Frontend callback with nullptr");
54 return Result::INVALID_ARGUMENT;
55 }
56
57 mCallback = callback;
58 return Result::SUCCESS;
59}
60
61Return<Result> Frontend::tune(const FrontendSettings& /* settings */) {
62 ALOGV("%s", __FUNCTION__);
63 if (mCallback == nullptr) {
64 ALOGW("[ WARN ] Frontend callback is not set when tune");
65 return Result::INVALID_STATE;
66 }
67
68 mTunerService->frontendStartTune(mId);
69 mCallback->onEvent(FrontendEventType::LOCKED);
70 mIsLocked = true;
71 return Result::SUCCESS;
72}
73
Amy Zhang3ea25a62020-08-04 10:23:52 -070074Return<Result> Frontend::tune_1_1(const FrontendSettings& settings,
Amy Zhangbc15b592020-09-25 15:35:55 -070075 const V1_1::FrontendSettingsExt1_1& /*settingsExt1_1*/) {
Amy Zhang3ea25a62020-08-04 10:23:52 -070076 ALOGV("%s", __FUNCTION__);
77 return tune(settings);
78}
79
Amy Zhangbb94eeb2020-07-09 22:48:04 -070080Return<Result> Frontend::stopTune() {
81 ALOGV("%s", __FUNCTION__);
82
83 mTunerService->frontendStopTune(mId);
84 mIsLocked = false;
85
86 return Result::SUCCESS;
87}
88
89Return<Result> Frontend::scan(const FrontendSettings& settings, FrontendScanType type) {
90 ALOGV("%s", __FUNCTION__);
91
92 if (mType == FrontendType::ATSC) {
93 FrontendScanMessage msg;
94 msg.isLocked(true);
95 mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
96 mIsLocked = true;
97 return Result::SUCCESS;
98 }
99 if (mType != FrontendType::DVBT) {
100 return Result::UNAVAILABLE;
101 }
102
103 FrontendScanMessage msg;
104
105 if (mIsLocked) {
106 msg.isEnd(true);
107 mCallback->onScanMessage(FrontendScanMessageType::END, msg);
108 return Result::SUCCESS;
109 }
110
111 uint32_t frequency = settings.dvbt().frequency;
112 if (type == FrontendScanType::SCAN_BLIND) {
113 frequency += 100;
114 }
115 msg.frequencies({frequency});
116 mCallback->onScanMessage(FrontendScanMessageType::FREQUENCY, msg);
117 msg.isLocked(true);
118 mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
119 mIsLocked = true;
120
Amy Zhang19ed17b2020-08-04 10:23:52 -0700121 sp<V1_1::IFrontendCallback> frontendCallback_v1_1 =
122 V1_1::IFrontendCallback::castFrom(mCallback);
123 if (frontendCallback_v1_1 != NULL) {
124 V1_1::FrontendScanMessageExt1_1 msg;
Amy Zhang7ec2b702020-10-05 18:07:20 -0700125 msg.modulation().dvbc(FrontendDvbcModulation::MOD_16QAM);
Amy Zhang19ed17b2020-08-04 10:23:52 -0700126 frontendCallback_v1_1->onScanMessageExt1_1(V1_1::FrontendScanMessageTypeExt1_1::MODULATION,
127 msg);
Amy Zhang7ec2b702020-10-05 18:07:20 -0700128 msg.isHighPriority(true);
129 frontendCallback_v1_1->onScanMessageExt1_1(
130 V1_1::FrontendScanMessageTypeExt1_1::HIGH_PRIORITY, msg);
Amy Zhang19ed17b2020-08-04 10:23:52 -0700131 } else {
132 ALOGD("[Filter] Couldn't cast to V1_1 IFrontendCallback");
133 }
134
Amy Zhangbb94eeb2020-07-09 22:48:04 -0700135 return Result::SUCCESS;
136}
137
Amy Zhang3ea25a62020-08-04 10:23:52 -0700138Return<Result> Frontend::scan_1_1(const FrontendSettings& settings, FrontendScanType type,
Amy Zhangbc15b592020-09-25 15:35:55 -0700139 const V1_1::FrontendSettingsExt1_1& /*settingsExt1_1*/) {
Amy Zhang3ea25a62020-08-04 10:23:52 -0700140 ALOGV("%s", __FUNCTION__);
141 return scan(settings, type);
142}
143
Amy Zhangbb94eeb2020-07-09 22:48:04 -0700144Return<Result> Frontend::stopScan() {
145 ALOGV("%s", __FUNCTION__);
146
147 mIsLocked = false;
148 return Result::SUCCESS;
149}
150
151Return<void> Frontend::getStatus(const hidl_vec<FrontendStatusType>& statusTypes,
152 getStatus_cb _hidl_cb) {
153 ALOGV("%s", __FUNCTION__);
154
155 vector<FrontendStatus> statuses;
156 for (int i = 0; i < statusTypes.size(); i++) {
157 FrontendStatusType type = statusTypes[i];
158 FrontendStatus status;
159 // assign randomly selected values for testing.
160 switch (type) {
161 case FrontendStatusType::DEMOD_LOCK: {
162 status.isDemodLocked(true);
163 break;
164 }
165 case FrontendStatusType::SNR: {
166 status.snr(221);
167 break;
168 }
169 case FrontendStatusType::BER: {
170 status.ber(1);
171 break;
172 }
173 case FrontendStatusType::PER: {
174 status.per(2);
175 break;
176 }
177 case FrontendStatusType::PRE_BER: {
178 status.preBer(3);
179 break;
180 }
181 case FrontendStatusType::SIGNAL_QUALITY: {
182 status.signalQuality(4);
183 break;
184 }
185 case FrontendStatusType::SIGNAL_STRENGTH: {
186 status.signalStrength(5);
187 break;
188 }
189 case FrontendStatusType::SYMBOL_RATE: {
190 status.symbolRate(6);
191 break;
192 }
193 case FrontendStatusType::FEC: {
194 status.innerFec(FrontendInnerFec::FEC_2_9); // value = 1 << 7
195 break;
196 }
197 case FrontendStatusType::MODULATION: {
198 FrontendModulationStatus modulationStatus;
199 modulationStatus.isdbt(FrontendIsdbtModulation::MOD_16QAM); // value = 1 << 3
200 status.modulation(modulationStatus);
201 break;
202 }
203 case FrontendStatusType::SPECTRAL: {
204 status.inversion(FrontendDvbcSpectralInversion::NORMAL);
205 break;
206 }
207 case FrontendStatusType::LNB_VOLTAGE: {
208 status.lnbVoltage(LnbVoltage::VOLTAGE_5V);
209 break;
210 }
211 case FrontendStatusType::PLP_ID: {
212 status.plpId(101); // type uint8_t
213 break;
214 }
215 case FrontendStatusType::EWBS: {
216 status.isEWBS(false);
217 break;
218 }
219 case FrontendStatusType::AGC: {
220 status.agc(7);
221 break;
222 }
223 case FrontendStatusType::LNA: {
224 status.isLnaOn(false);
225 break;
226 }
227 case FrontendStatusType::LAYER_ERROR: {
228 vector<bool> v = {false, true, true};
229 status.isLayerError(v);
230 break;
231 }
232 case FrontendStatusType::MER: {
233 status.mer(8);
234 break;
235 }
236 case FrontendStatusType::FREQ_OFFSET: {
237 status.freqOffset(9);
238 break;
239 }
240 case FrontendStatusType::HIERARCHY: {
241 status.hierarchy(FrontendDvbtHierarchy::HIERARCHY_1_NATIVE);
242 break;
243 }
244 case FrontendStatusType::RF_LOCK: {
245 status.isRfLocked(false);
246 break;
247 }
248 case FrontendStatusType::ATSC3_PLP_INFO: {
249 vector<FrontendStatusAtsc3PlpInfo> v;
250 FrontendStatusAtsc3PlpInfo info1{
251 .plpId = 3,
252 .isLocked = false,
253 .uec = 313,
254 };
255 FrontendStatusAtsc3PlpInfo info2{
256 .plpId = 5,
257 .isLocked = true,
258 .uec = 515,
259 };
260 v.push_back(info1);
261 v.push_back(info2);
262 status.plpInfo(v);
263 break;
264 }
265 default: {
266 continue;
267 }
268 }
269 statuses.push_back(status);
270 }
271 _hidl_cb(Result::SUCCESS, statuses);
272
273 return Void();
274}
275
Amy Zhang422bb112020-08-12 15:21:44 -0700276Return<void> Frontend::getStatusExt1_1(const hidl_vec<V1_1::FrontendStatusTypeExt1_1>& statusTypes,
277 V1_1::IFrontend::getStatusExt1_1_cb _hidl_cb) {
278 ALOGV("%s", __FUNCTION__);
279
280 vector<V1_1::FrontendStatusExt1_1> statuses;
281 for (int i = 0; i < statusTypes.size(); i++) {
282 V1_1::FrontendStatusTypeExt1_1 type = statusTypes[i];
283 V1_1::FrontendStatusExt1_1 status;
284 // assign randomly selected values for testing.
285 switch (type) {
286 case V1_1::FrontendStatusTypeExt1_1::MODULATIONS: {
287 vector<V1_1::FrontendModulation> modulations;
288 V1_1::FrontendModulation modulation;
289 modulation.isdbt(FrontendIsdbtModulation::MOD_16QAM); // value = 1 << 3
290 modulations.push_back(modulation);
291 status.modulations(modulations);
292 break;
293 }
294 case V1_1::FrontendStatusTypeExt1_1::BERS: {
295 vector<uint32_t> bers = {1};
296 status.bers(bers);
297 break;
298 }
299 case V1_1::FrontendStatusTypeExt1_1::CODERATES: {
300 // value = 1 << 39
301 vector<V1_1::FrontendInnerFec> codeRates = {V1_1::FrontendInnerFec::FEC_6_15};
302 status.codeRates(codeRates);
303 break;
304 }
305 case V1_1::FrontendStatusTypeExt1_1::GUARD_INTERVAL: {
306 V1_1::FrontendGuardInterval interval;
307 interval.dvbt(FrontendDvbtGuardInterval::INTERVAL_1_32); // value = 1 << 1
308 status.interval(interval);
309 break;
310 }
311 case V1_1::FrontendStatusTypeExt1_1::TRANSMISSION_MODE: {
312 V1_1::FrontendTransmissionMode transMode;
313 transMode.dvbt(V1_1::FrontendDvbtTransmissionMode::AUTO); // value = 1 << 0
314 status.transmissionMode(transMode);
315 break;
316 }
317 case V1_1::FrontendStatusTypeExt1_1::UEC: {
318 status.uec(4);
319 break;
320 }
321 case V1_1::FrontendStatusTypeExt1_1::T2_SYSTEM_ID: {
322 status.systemId(5);
323 break;
324 }
325 case V1_1::FrontendStatusTypeExt1_1::INTERLEAVINGS: {
326 V1_1::FrontendInterleaveMode interleave;
327 interleave.atsc3(FrontendAtsc3TimeInterleaveMode::AUTO);
328 vector<V1_1::FrontendInterleaveMode> interleaving = {interleave};
329 status.interleaving(interleaving);
330 break;
331 }
332 case V1_1::FrontendStatusTypeExt1_1::ISDBT_SEGMENTS: {
333 vector<uint8_t> segments = {2, 3};
334 status.isdbtSegment(segments);
335 break;
336 }
337 case V1_1::FrontendStatusTypeExt1_1::TS_DATA_RATES: {
338 vector<uint32_t> dataRates = {4, 5};
339 status.tsDataRate(dataRates);
340 break;
341 }
342 default: {
343 continue;
344 }
345 }
346 statuses.push_back(status);
347 }
348 _hidl_cb(Result::SUCCESS, statuses);
349
350 return Void();
351}
352
Amy Zhangbb94eeb2020-07-09 22:48:04 -0700353Return<Result> Frontend::setLna(bool /* bEnable */) {
354 ALOGV("%s", __FUNCTION__);
355
356 return Result::SUCCESS;
357}
358
359Return<Result> Frontend::setLnb(uint32_t /* lnb */) {
360 ALOGV("%s", __FUNCTION__);
361 if (!supportsSatellite()) {
362 return Result::INVALID_STATE;
363 }
364 return Result::SUCCESS;
365}
366
Amy Zhange8a57372020-10-07 12:24:48 -0700367Return<void> Frontend::linkCiCam(uint32_t ciCamId, linkCiCam_cb _hidl_cb) {
Amy Zhang17f8eac2020-08-17 16:52:13 -0700368 ALOGV("%s", __FUNCTION__);
369
370 mCiCamId = ciCamId;
Amy Zhange8a57372020-10-07 12:24:48 -0700371 _hidl_cb(Result::SUCCESS, 0 /*ltsId*/);
372
373 return Void();
374}
375
376Return<Result> Frontend::unlinkCiCam(uint32_t /*ciCamId*/) {
377 ALOGV("%s", __FUNCTION__);
378
379 mCiCamId = -1;
Amy Zhang17f8eac2020-08-17 16:52:13 -0700380
381 return Result::SUCCESS;
382}
383
Amy Zhangbb94eeb2020-07-09 22:48:04 -0700384FrontendType Frontend::getFrontendType() {
385 return mType;
386}
387
388FrontendId Frontend::getFrontendId() {
389 return mId;
390}
391
392bool Frontend::supportsSatellite() {
393 return mType == FrontendType::DVBS || mType == FrontendType::ISDBS ||
394 mType == FrontendType::ISDBS3;
395}
396
397bool Frontend::isLocked() {
398 return mIsLocked;
399}
400} // namespace implementation
401} // namespace V1_0
402} // namespace tuner
403} // namespace tv
404} // namespace hardware
405} // namespace android