blob: c5aeace1b59a8c188b6b6d93339c133ccd6e8af6 [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"
20#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
21#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
121 return Result::SUCCESS;
122}
123
Amy Zhang3ea25a62020-08-04 10:23:52 -0700124Return<Result> Frontend::scan_1_1(const FrontendSettings& settings, FrontendScanType type,
Amy Zhangbc15b592020-09-25 15:35:55 -0700125 const V1_1::FrontendSettingsExt1_1& /*settingsExt1_1*/) {
Amy Zhang3ea25a62020-08-04 10:23:52 -0700126 ALOGV("%s", __FUNCTION__);
127 return scan(settings, type);
128}
129
Amy Zhangbb94eeb2020-07-09 22:48:04 -0700130Return<Result> Frontend::stopScan() {
131 ALOGV("%s", __FUNCTION__);
132
133 mIsLocked = false;
134 return Result::SUCCESS;
135}
136
137Return<void> Frontend::getStatus(const hidl_vec<FrontendStatusType>& statusTypes,
138 getStatus_cb _hidl_cb) {
139 ALOGV("%s", __FUNCTION__);
140
141 vector<FrontendStatus> statuses;
142 for (int i = 0; i < statusTypes.size(); i++) {
143 FrontendStatusType type = statusTypes[i];
144 FrontendStatus status;
145 // assign randomly selected values for testing.
146 switch (type) {
147 case FrontendStatusType::DEMOD_LOCK: {
148 status.isDemodLocked(true);
149 break;
150 }
151 case FrontendStatusType::SNR: {
152 status.snr(221);
153 break;
154 }
155 case FrontendStatusType::BER: {
156 status.ber(1);
157 break;
158 }
159 case FrontendStatusType::PER: {
160 status.per(2);
161 break;
162 }
163 case FrontendStatusType::PRE_BER: {
164 status.preBer(3);
165 break;
166 }
167 case FrontendStatusType::SIGNAL_QUALITY: {
168 status.signalQuality(4);
169 break;
170 }
171 case FrontendStatusType::SIGNAL_STRENGTH: {
172 status.signalStrength(5);
173 break;
174 }
175 case FrontendStatusType::SYMBOL_RATE: {
176 status.symbolRate(6);
177 break;
178 }
179 case FrontendStatusType::FEC: {
180 status.innerFec(FrontendInnerFec::FEC_2_9); // value = 1 << 7
181 break;
182 }
183 case FrontendStatusType::MODULATION: {
184 FrontendModulationStatus modulationStatus;
185 modulationStatus.isdbt(FrontendIsdbtModulation::MOD_16QAM); // value = 1 << 3
186 status.modulation(modulationStatus);
187 break;
188 }
189 case FrontendStatusType::SPECTRAL: {
190 status.inversion(FrontendDvbcSpectralInversion::NORMAL);
191 break;
192 }
193 case FrontendStatusType::LNB_VOLTAGE: {
194 status.lnbVoltage(LnbVoltage::VOLTAGE_5V);
195 break;
196 }
197 case FrontendStatusType::PLP_ID: {
198 status.plpId(101); // type uint8_t
199 break;
200 }
201 case FrontendStatusType::EWBS: {
202 status.isEWBS(false);
203 break;
204 }
205 case FrontendStatusType::AGC: {
206 status.agc(7);
207 break;
208 }
209 case FrontendStatusType::LNA: {
210 status.isLnaOn(false);
211 break;
212 }
213 case FrontendStatusType::LAYER_ERROR: {
214 vector<bool> v = {false, true, true};
215 status.isLayerError(v);
216 break;
217 }
218 case FrontendStatusType::MER: {
219 status.mer(8);
220 break;
221 }
222 case FrontendStatusType::FREQ_OFFSET: {
223 status.freqOffset(9);
224 break;
225 }
226 case FrontendStatusType::HIERARCHY: {
227 status.hierarchy(FrontendDvbtHierarchy::HIERARCHY_1_NATIVE);
228 break;
229 }
230 case FrontendStatusType::RF_LOCK: {
231 status.isRfLocked(false);
232 break;
233 }
234 case FrontendStatusType::ATSC3_PLP_INFO: {
235 vector<FrontendStatusAtsc3PlpInfo> v;
236 FrontendStatusAtsc3PlpInfo info1{
237 .plpId = 3,
238 .isLocked = false,
239 .uec = 313,
240 };
241 FrontendStatusAtsc3PlpInfo info2{
242 .plpId = 5,
243 .isLocked = true,
244 .uec = 515,
245 };
246 v.push_back(info1);
247 v.push_back(info2);
248 status.plpInfo(v);
249 break;
250 }
251 default: {
252 continue;
253 }
254 }
255 statuses.push_back(status);
256 }
257 _hidl_cb(Result::SUCCESS, statuses);
258
259 return Void();
260}
261
Amy Zhang422bb112020-08-12 15:21:44 -0700262Return<void> Frontend::getStatusExt1_1(const hidl_vec<V1_1::FrontendStatusTypeExt1_1>& statusTypes,
263 V1_1::IFrontend::getStatusExt1_1_cb _hidl_cb) {
264 ALOGV("%s", __FUNCTION__);
265
266 vector<V1_1::FrontendStatusExt1_1> statuses;
267 for (int i = 0; i < statusTypes.size(); i++) {
268 V1_1::FrontendStatusTypeExt1_1 type = statusTypes[i];
269 V1_1::FrontendStatusExt1_1 status;
270 // assign randomly selected values for testing.
271 switch (type) {
272 case V1_1::FrontendStatusTypeExt1_1::MODULATIONS: {
273 vector<V1_1::FrontendModulation> modulations;
274 V1_1::FrontendModulation modulation;
275 modulation.isdbt(FrontendIsdbtModulation::MOD_16QAM); // value = 1 << 3
276 modulations.push_back(modulation);
277 status.modulations(modulations);
278 break;
279 }
280 case V1_1::FrontendStatusTypeExt1_1::BERS: {
281 vector<uint32_t> bers = {1};
282 status.bers(bers);
283 break;
284 }
285 case V1_1::FrontendStatusTypeExt1_1::CODERATES: {
286 // value = 1 << 39
287 vector<V1_1::FrontendInnerFec> codeRates = {V1_1::FrontendInnerFec::FEC_6_15};
288 status.codeRates(codeRates);
289 break;
290 }
291 case V1_1::FrontendStatusTypeExt1_1::GUARD_INTERVAL: {
292 V1_1::FrontendGuardInterval interval;
293 interval.dvbt(FrontendDvbtGuardInterval::INTERVAL_1_32); // value = 1 << 1
294 status.interval(interval);
295 break;
296 }
297 case V1_1::FrontendStatusTypeExt1_1::TRANSMISSION_MODE: {
298 V1_1::FrontendTransmissionMode transMode;
299 transMode.dvbt(V1_1::FrontendDvbtTransmissionMode::AUTO); // value = 1 << 0
300 status.transmissionMode(transMode);
301 break;
302 }
303 case V1_1::FrontendStatusTypeExt1_1::UEC: {
304 status.uec(4);
305 break;
306 }
307 case V1_1::FrontendStatusTypeExt1_1::T2_SYSTEM_ID: {
308 status.systemId(5);
309 break;
310 }
311 case V1_1::FrontendStatusTypeExt1_1::INTERLEAVINGS: {
312 V1_1::FrontendInterleaveMode interleave;
313 interleave.atsc3(FrontendAtsc3TimeInterleaveMode::AUTO);
314 vector<V1_1::FrontendInterleaveMode> interleaving = {interleave};
315 status.interleaving(interleaving);
316 break;
317 }
318 case V1_1::FrontendStatusTypeExt1_1::ISDBT_SEGMENTS: {
319 vector<uint8_t> segments = {2, 3};
320 status.isdbtSegment(segments);
321 break;
322 }
323 case V1_1::FrontendStatusTypeExt1_1::TS_DATA_RATES: {
324 vector<uint32_t> dataRates = {4, 5};
325 status.tsDataRate(dataRates);
326 break;
327 }
328 default: {
329 continue;
330 }
331 }
332 statuses.push_back(status);
333 }
334 _hidl_cb(Result::SUCCESS, statuses);
335
336 return Void();
337}
338
Amy Zhangbb94eeb2020-07-09 22:48:04 -0700339Return<Result> Frontend::setLna(bool /* bEnable */) {
340 ALOGV("%s", __FUNCTION__);
341
342 return Result::SUCCESS;
343}
344
345Return<Result> Frontend::setLnb(uint32_t /* lnb */) {
346 ALOGV("%s", __FUNCTION__);
347 if (!supportsSatellite()) {
348 return Result::INVALID_STATE;
349 }
350 return Result::SUCCESS;
351}
352
Amy Zhang17f8eac2020-08-17 16:52:13 -0700353Return<Result> Frontend::linkCiCam(uint32_t ciCamId) {
354 ALOGV("%s", __FUNCTION__);
355
356 mCiCamId = ciCamId;
357
358 return Result::SUCCESS;
359}
360
Amy Zhangbb94eeb2020-07-09 22:48:04 -0700361FrontendType Frontend::getFrontendType() {
362 return mType;
363}
364
365FrontendId Frontend::getFrontendId() {
366 return mId;
367}
368
369bool Frontend::supportsSatellite() {
370 return mType == FrontendType::DVBS || mType == FrontendType::ISDBS ||
371 mType == FrontendType::ISDBS3;
372}
373
374bool Frontend::isLocked() {
375 return mIsLocked;
376}
377} // namespace implementation
378} // namespace V1_0
379} // namespace tuner
380} // namespace tv
381} // namespace hardware
382} // namespace android