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