1 /*
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 #include "FrontendTests.h"
18
onEvent(FrontendEventType frontendEventType)19 Return<void> FrontendCallback::onEvent(FrontendEventType frontendEventType) {
20 android::Mutex::Autolock autoLock(mMsgLock);
21 ALOGD("[vts] frontend event received. Type: %d", frontendEventType);
22 mEventReceived = true;
23 mMsgCondition.signal();
24 switch (frontendEventType) {
25 case FrontendEventType::LOCKED:
26 mLockMsgReceived = true;
27 mLockMsgCondition.signal();
28 return Void();
29 default:
30 // do nothing
31 return Void();
32 }
33 }
34
onScanMessage(FrontendScanMessageType type,const FrontendScanMessage & message)35 Return<void> FrontendCallback::onScanMessage(FrontendScanMessageType type,
36 const FrontendScanMessage& message) {
37 android::Mutex::Autolock autoLock(mMsgLock);
38 while (!mScanMsgProcessed) {
39 mMsgCondition.wait(mMsgLock);
40 }
41 ALOGD("[vts] frontend scan message. Type: %d", type);
42 mScanMessageReceived = true;
43 mScanMsgProcessed = false;
44 mScanMessageType = type;
45 mScanMessage = message;
46 mMsgCondition.signal();
47 return Void();
48 }
49
tuneTestOnEventReceive(sp<IFrontend> & frontend,FrontendSettings settings)50 void FrontendCallback::tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings) {
51 Result result = frontend->tune(settings);
52 EXPECT_TRUE(result == Result::SUCCESS);
53
54 android::Mutex::Autolock autoLock(mMsgLock);
55 while (!mEventReceived) {
56 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
57 EXPECT_TRUE(false) << "Event not received within timeout";
58 mLockMsgReceived = false;
59 return;
60 }
61 }
62 mEventReceived = false;
63 }
64
tuneTestOnLock(sp<IFrontend> & frontend,FrontendSettings settings)65 void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings) {
66 Result result = frontend->tune(settings);
67 EXPECT_TRUE(result == Result::SUCCESS);
68
69 android::Mutex::Autolock autoLock(mMsgLock);
70 while (!mLockMsgReceived) {
71 if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
72 EXPECT_TRUE(false) << "Event LOCKED not received within timeout";
73 mLockMsgReceived = false;
74 return;
75 }
76 }
77 mLockMsgReceived = false;
78 }
79
scanTest(sp<IFrontend> & frontend,FrontendConfig config,FrontendScanType type)80 void FrontendCallback::scanTest(sp<IFrontend>& frontend, FrontendConfig config,
81 FrontendScanType type) {
82 uint32_t targetFrequency = getTargetFrequency(config.settings, config.type);
83 if (type == FrontendScanType::SCAN_BLIND) {
84 // reset the frequency in the scan configuration to test blind scan. The settings param of
85 // passed in means the real input config on the transponder connected to the DUT.
86 // We want the blind the test to start from lower frequency than this to check the blind
87 // scan implementation.
88 resetBlindScanStartingFrequency(config, targetFrequency - 100 * 1000);
89 }
90
91 Result result = frontend->scan(config.settings, type);
92 EXPECT_TRUE(result == Result::SUCCESS);
93
94 bool scanMsgLockedReceived = false;
95 bool targetFrequencyReceived = false;
96
97 android::Mutex::Autolock autoLock(mMsgLock);
98 wait:
99 while (!mScanMessageReceived) {
100 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
101 EXPECT_TRUE(false) << "Scan message not received within timeout";
102 mScanMessageReceived = false;
103 mScanMsgProcessed = true;
104 return;
105 }
106 }
107
108 if (mScanMessageType != FrontendScanMessageType::END) {
109 if (mScanMessageType == FrontendScanMessageType::LOCKED) {
110 scanMsgLockedReceived = true;
111 Result result = frontend->scan(config.settings, type);
112 EXPECT_TRUE(result == Result::SUCCESS);
113 }
114
115 if (mScanMessageType == FrontendScanMessageType::FREQUENCY) {
116 targetFrequencyReceived = mScanMessage.frequencies().size() > 0 &&
117 mScanMessage.frequencies()[0] == targetFrequency;
118 }
119
120 if (mScanMessageType == FrontendScanMessageType::PROGRESS_PERCENT) {
121 ALOGD("[vts] Scan in progress...[%d%%]", mScanMessage.progressPercent());
122 }
123
124 mScanMessageReceived = false;
125 mScanMsgProcessed = true;
126 mMsgCondition.signal();
127 goto wait;
128 }
129
130 EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END";
131 if (type == FrontendScanType::SCAN_BLIND)
132 EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
133 mScanMessageReceived = false;
134 mScanMsgProcessed = true;
135 }
136
getTargetFrequency(FrontendSettings settings,FrontendType type)137 uint32_t FrontendCallback::getTargetFrequency(FrontendSettings settings, FrontendType type) {
138 switch (type) {
139 case FrontendType::ANALOG:
140 return settings.analog().frequency;
141 case FrontendType::ATSC:
142 return settings.atsc().frequency;
143 case FrontendType::ATSC3:
144 return settings.atsc3().frequency;
145 case FrontendType::DVBC:
146 return settings.dvbc().frequency;
147 case FrontendType::DVBS:
148 return settings.dvbs().frequency;
149 case FrontendType::DVBT:
150 return settings.dvbt().frequency;
151 case FrontendType::ISDBS:
152 return settings.isdbs().frequency;
153 case FrontendType::ISDBS3:
154 return settings.isdbs3().frequency;
155 case FrontendType::ISDBT:
156 return settings.isdbt().frequency;
157 default:
158 return 0;
159 }
160 }
161
resetBlindScanStartingFrequency(FrontendConfig & config,uint32_t resetingFreq)162 void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig& config,
163 uint32_t resetingFreq) {
164 switch (config.type) {
165 case FrontendType::ANALOG:
166 config.settings.analog().frequency = resetingFreq;
167 break;
168 case FrontendType::ATSC:
169 config.settings.atsc().frequency = resetingFreq;
170 break;
171 case FrontendType::ATSC3:
172 config.settings.atsc3().frequency = resetingFreq;
173 break;
174 case FrontendType::DVBC:
175 config.settings.dvbc().frequency = resetingFreq;
176 break;
177 case FrontendType::DVBS:
178 config.settings.dvbs().frequency = resetingFreq;
179 break;
180 case FrontendType::DVBT:
181 config.settings.dvbt().frequency = resetingFreq;
182 break;
183 case FrontendType::ISDBS:
184 config.settings.isdbs().frequency = resetingFreq;
185 break;
186 case FrontendType::ISDBS3:
187 config.settings.isdbs3().frequency = resetingFreq;
188 break;
189 case FrontendType::ISDBT:
190 config.settings.isdbt().frequency = resetingFreq;
191 break;
192 default:
193 // do nothing
194 return;
195 }
196 }
197
getFrontendIds()198 AssertionResult FrontendTests::getFrontendIds() {
199 Result status;
200 mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
201 status = result;
202 mFeIds = frontendIds;
203 });
204 return AssertionResult(status == Result::SUCCESS);
205 }
206
getFrontendInfo(uint32_t frontendId)207 AssertionResult FrontendTests::getFrontendInfo(uint32_t frontendId) {
208 Result status;
209 mService->getFrontendInfo(frontendId, [&](Result result, const FrontendInfo& frontendInfo) {
210 mFrontendInfo = frontendInfo;
211 status = result;
212 });
213 return AssertionResult(status == Result::SUCCESS);
214 }
215
openFrontendById(uint32_t frontendId)216 AssertionResult FrontendTests::openFrontendById(uint32_t frontendId) {
217 Result status;
218 mService->openFrontendById(frontendId, [&](Result result, const sp<IFrontend>& frontend) {
219 mFrontend = frontend;
220 status = result;
221 });
222 return AssertionResult(status == Result::SUCCESS);
223 }
224
setFrontendCallback()225 AssertionResult FrontendTests::setFrontendCallback() {
226 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
227 mFrontendCallback = new FrontendCallback();
228 auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
229 return AssertionResult(callbackStatus.isOk());
230 }
231
scanFrontend(FrontendConfig config,FrontendScanType type)232 AssertionResult FrontendTests::scanFrontend(FrontendConfig config, FrontendScanType type) {
233 EXPECT_TRUE(mFrontendCallback)
234 << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
235
236 EXPECT_TRUE(mFrontendInfo.type == config.type)
237 << "FrontendConfig does not match the frontend info of the given id.";
238
239 mFrontendCallback->scanTest(mFrontend, config, type);
240 return AssertionResult(true);
241 }
242
stopScanFrontend()243 AssertionResult FrontendTests::stopScanFrontend() {
244 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
245 Result status;
246 status = mFrontend->stopScan();
247 return AssertionResult(status == Result::SUCCESS);
248 }
249
verifyFrontendStatus(vector<FrontendStatusType> statusTypes,vector<FrontendStatus> expectStatuses)250 void FrontendTests::verifyFrontendStatus(vector<FrontendStatusType> statusTypes,
251 vector<FrontendStatus> expectStatuses) {
252 ASSERT_TRUE(mFrontend) << "Frontend is not opened yet.";
253 Result status;
254 vector<FrontendStatus> realStatuses;
255
256 mFrontend->getStatus(statusTypes, [&](Result result, const hidl_vec<FrontendStatus>& statuses) {
257 status = result;
258 realStatuses = statuses;
259 });
260
261 ASSERT_TRUE(realStatuses.size() == statusTypes.size());
262 for (int i = 0; i < statusTypes.size(); i++) {
263 FrontendStatusType type = statusTypes[i];
264 switch (type) {
265 case FrontendStatusType::DEMOD_LOCK: {
266 ASSERT_TRUE(realStatuses[i].isDemodLocked() == expectStatuses[i].isDemodLocked());
267 break;
268 }
269 case FrontendStatusType::SNR: {
270 ASSERT_TRUE(realStatuses[i].snr() == expectStatuses[i].snr());
271 break;
272 }
273 case FrontendStatusType::BER: {
274 ASSERT_TRUE(realStatuses[i].ber() == expectStatuses[i].ber());
275 break;
276 }
277 case FrontendStatusType::PER: {
278 ASSERT_TRUE(realStatuses[i].per() == expectStatuses[i].per());
279 break;
280 }
281 case FrontendStatusType::PRE_BER: {
282 ASSERT_TRUE(realStatuses[i].preBer() == expectStatuses[i].preBer());
283 break;
284 }
285 case FrontendStatusType::SIGNAL_QUALITY: {
286 ASSERT_TRUE(realStatuses[i].signalQuality() == expectStatuses[i].signalQuality());
287 break;
288 }
289 case FrontendStatusType::SIGNAL_STRENGTH: {
290 ASSERT_TRUE(realStatuses[i].signalStrength() == expectStatuses[i].signalStrength());
291 break;
292 }
293 case FrontendStatusType::SYMBOL_RATE: {
294 ASSERT_TRUE(realStatuses[i].symbolRate() == expectStatuses[i].symbolRate());
295 break;
296 }
297 case FrontendStatusType::FEC: {
298 ASSERT_TRUE(realStatuses[i].innerFec() == expectStatuses[i].innerFec());
299 break;
300 }
301 case FrontendStatusType::MODULATION: {
302 // TODO: check modulation status
303 break;
304 }
305 case FrontendStatusType::SPECTRAL: {
306 ASSERT_TRUE(realStatuses[i].inversion() == expectStatuses[i].inversion());
307 break;
308 }
309 case FrontendStatusType::LNB_VOLTAGE: {
310 ASSERT_TRUE(realStatuses[i].lnbVoltage() == expectStatuses[i].lnbVoltage());
311 break;
312 }
313 case FrontendStatusType::PLP_ID: {
314 ASSERT_TRUE(realStatuses[i].plpId() == expectStatuses[i].plpId());
315 break;
316 }
317 case FrontendStatusType::EWBS: {
318 ASSERT_TRUE(realStatuses[i].isEWBS() == expectStatuses[i].isEWBS());
319 break;
320 }
321 case FrontendStatusType::AGC: {
322 ASSERT_TRUE(realStatuses[i].agc() == expectStatuses[i].agc());
323 break;
324 }
325 case FrontendStatusType::LNA: {
326 ASSERT_TRUE(realStatuses[i].isLnaOn() == expectStatuses[i].isLnaOn());
327 break;
328 }
329 case FrontendStatusType::LAYER_ERROR: {
330 vector<bool> realLayberError = realStatuses[i].isLayerError();
331 vector<bool> expectLayerError = expectStatuses[i].isLayerError();
332 ASSERT_TRUE(realLayberError.size() == expectLayerError.size());
333 for (int i = 0; i < realLayberError.size(); i++) {
334 ASSERT_TRUE(realLayberError[i] == expectLayerError[i]);
335 }
336 break;
337 }
338 case FrontendStatusType::MER: {
339 ASSERT_TRUE(realStatuses[i].mer() == expectStatuses[i].mer());
340 break;
341 }
342 case FrontendStatusType::FREQ_OFFSET: {
343 ASSERT_TRUE(realStatuses[i].freqOffset() == expectStatuses[i].freqOffset());
344 break;
345 }
346 case FrontendStatusType::HIERARCHY: {
347 ASSERT_TRUE(realStatuses[i].hierarchy() == expectStatuses[i].hierarchy());
348 break;
349 }
350 case FrontendStatusType::RF_LOCK: {
351 ASSERT_TRUE(realStatuses[i].isRfLocked() == expectStatuses[i].isRfLocked());
352 break;
353 }
354 case FrontendStatusType::ATSC3_PLP_INFO:
355 // TODO: verify plpinfo
356 break;
357 default:
358 continue;
359 }
360 }
361 ASSERT_TRUE(status == Result::SUCCESS);
362 }
363
tuneFrontend(FrontendConfig config,bool testWithDemux)364 AssertionResult FrontendTests::tuneFrontend(FrontendConfig config, bool testWithDemux) {
365 EXPECT_TRUE(mFrontendCallback)
366 << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
367
368 EXPECT_TRUE(mFrontendInfo.type == config.type)
369 << "FrontendConfig does not match the frontend info of the given id.";
370
371 mIsSoftwareFe = config.isSoftwareFe;
372 bool result = true;
373 if (mIsSoftwareFe && testWithDemux) {
374 result &=
375 getDvrTests()->openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
376 result &= getDvrTests()->configDvrPlayback(mDvrConfig.settings) == success();
377 result &= getDvrTests()->getDvrPlaybackMQDescriptor() == success();
378 getDvrTests()->startPlaybackInputThread(mDvrConfig.playbackInputFile,
379 mDvrConfig.settings.playback());
380 getDvrTests()->startDvrPlayback();
381 if (!result) {
382 ALOGW("[vts] Software frontend dvr configure failed.");
383 return failure();
384 }
385 }
386 mFrontendCallback->tuneTestOnLock(mFrontend, config.settings);
387 return AssertionResult(true);
388 }
389
setLnb(uint32_t lnbId)390 AssertionResult FrontendTests::setLnb(uint32_t lnbId) {
391 if (!mFrontendCallback) {
392 ALOGW("[vts] open and set frontend callback first.");
393 return failure();
394 }
395 return AssertionResult(mFrontend->setLnb(lnbId) == Result::SUCCESS);
396 }
397
stopTuneFrontend(bool testWithDemux)398 AssertionResult FrontendTests::stopTuneFrontend(bool testWithDemux) {
399 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
400 Result status;
401 status = mFrontend->stopTune();
402 if (mIsSoftwareFe && testWithDemux) {
403 getDvrTests()->stopPlaybackThread();
404 getDvrTests()->stopDvrPlayback();
405 getDvrTests()->closeDvrPlayback();
406 }
407 return AssertionResult(status == Result::SUCCESS);
408 }
409
closeFrontend()410 AssertionResult FrontendTests::closeFrontend() {
411 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
412 Result status;
413 status = mFrontend->close();
414 mFrontend = nullptr;
415 mFrontendCallback = nullptr;
416 return AssertionResult(status == Result::SUCCESS);
417 }
418
getFrontendIdByType(FrontendType feType,uint32_t & feId)419 void FrontendTests::getFrontendIdByType(FrontendType feType, uint32_t& feId) {
420 ASSERT_TRUE(getFrontendIds());
421 for (size_t i = 0; i < mFeIds.size(); i++) {
422 ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
423 if (mFrontendInfo.type != feType) {
424 continue;
425 }
426 feId = mFeIds[i];
427 return;
428 }
429 feId = INVALID_ID;
430 }
431
tuneTest(FrontendConfig frontendConf)432 void FrontendTests::tuneTest(FrontendConfig frontendConf) {
433 uint32_t feId;
434 getFrontendIdByType(frontendConf.type, feId);
435 ASSERT_TRUE(feId != INVALID_ID);
436 ASSERT_TRUE(openFrontendById(feId));
437 ASSERT_TRUE(setFrontendCallback());
438 ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
439 verifyFrontendStatus(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
440 ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
441 ASSERT_TRUE(closeFrontend());
442 }
443
scanTest(FrontendConfig frontendConf,FrontendScanType scanType)444 void FrontendTests::scanTest(FrontendConfig frontendConf, FrontendScanType scanType) {
445 uint32_t feId;
446 getFrontendIdByType(frontendConf.type, feId);
447 ASSERT_TRUE(feId != INVALID_ID);
448 ASSERT_TRUE(openFrontendById(feId));
449 ASSERT_TRUE(setFrontendCallback());
450 ASSERT_TRUE(scanFrontend(frontendConf, scanType));
451 ASSERT_TRUE(stopScanFrontend());
452 ASSERT_TRUE(closeFrontend());
453 }
454