blob: 3bc7114b17aa2081f56e43a1f9b983b103e0cda5 [file] [log] [blame]
Amy Zhang45cc57a2020-07-09 22:56:25 -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#include "FrontendTests.h"
18
Amy Zhang68afca62020-07-20 18:28:58 -070019Return<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 }
Amy Zhang45cc57a2020-07-09 22:56:25 -070033}
34
Amy Zhang3ea25a62020-08-04 10:23:52 -070035Return<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();
Amy Zhang45cc57a2020-07-09 22:56:25 -070047 return Void();
48}
49
Amy Zhang19ed17b2020-08-04 10:23:52 -070050Return<void> FrontendCallback::onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type,
51 const FrontendScanMessageExt1_1& message) {
52 android::Mutex::Autolock autoLock(mMsgLock);
53 ALOGD("[vts] frontend ext1_1 scan message. Type: %d", type);
54 switch (type) {
55 case FrontendScanMessageTypeExt1_1::MODULATION:
56 readFrontendScanMessageExt1_1Modulation(message);
57 break;
58 default:
59 break;
60 }
61 return Void();
62}
63
64void FrontendCallback::readFrontendScanMessageExt1_1Modulation(FrontendModulation modulation) {
65 switch (modulation.getDiscriminator()) {
66 case FrontendModulation::hidl_discriminator::dvbc:
67 ALOGD("[vts] frontend ext1_1 scan message modulation dvbc: %d", modulation.dvbc());
68 break;
69 case FrontendModulation::hidl_discriminator::dvbs:
70 ALOGD("[vts] frontend ext1_1 scan message modulation dvbs: %d", modulation.dvbs());
71 break;
72 case FrontendModulation::hidl_discriminator::isdbs:
73 ALOGD("[vts] frontend ext1_1 scan message modulation isdbs: %d", modulation.isdbs());
74 break;
75 case FrontendModulation::hidl_discriminator::isdbs3:
76 ALOGD("[vts] frontend ext1_1 scan message modulation isdbs3: %d", modulation.isdbs3());
77 break;
78 case FrontendModulation::hidl_discriminator::isdbt:
79 ALOGD("[vts] frontend ext1_1 scan message modulation isdbt: %d", modulation.isdbt());
80 break;
81 case FrontendModulation::hidl_discriminator::atsc:
82 ALOGD("[vts] frontend ext1_1 scan message modulation atsc: %d", modulation.atsc());
83 break;
84 case FrontendModulation::hidl_discriminator::atsc3:
85 ALOGD("[vts] frontend ext1_1 scan message modulation atsc3: %d", modulation.atsc3());
86 break;
87 case FrontendModulation::hidl_discriminator::dvbt:
88 ALOGD("[vts] frontend ext1_1 scan message modulation dvbt: %d", modulation.dvbt());
89 break;
90 default:
91 break;
92 }
93}
94
Amy Zhang3ea25a62020-08-04 10:23:52 -070095void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings,
Amy Zhangbc15b592020-09-25 15:35:55 -070096 FrontendSettingsExt1_1 settingsExt1_1) {
Amy Zhang3ea25a62020-08-04 10:23:52 -070097 sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
98 frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(frontend);
99 if (frontend_1_1 == nullptr) {
100 EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
101 return;
102 }
103
Amy Zhangbc15b592020-09-25 15:35:55 -0700104 Result result = frontend_1_1->tune_1_1(settings, settingsExt1_1);
Amy Zhang68afca62020-07-20 18:28:58 -0700105 EXPECT_TRUE(result == Result::SUCCESS);
106
107 android::Mutex::Autolock autoLock(mMsgLock);
108 while (!mLockMsgReceived) {
109 if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
110 EXPECT_TRUE(false) << "Event LOCKED not received within timeout";
111 mLockMsgReceived = false;
112 return;
113 }
114 }
115 mLockMsgReceived = false;
116}
117
Amy Zhang3ea25a62020-08-04 10:23:52 -0700118void FrontendCallback::scanTest(sp<IFrontend>& frontend, FrontendConfig config,
119 FrontendScanType type) {
120 sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
121 frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(frontend);
122 if (frontend_1_1 == nullptr) {
123 EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
124 return;
125 }
126
127 uint32_t targetFrequency = getTargetFrequency(config.settings, config.type);
128 if (type == FrontendScanType::SCAN_BLIND) {
129 // reset the frequency in the scan configuration to test blind scan. The settings param of
130 // passed in means the real input config on the transponder connected to the DUT.
131 // We want the blind the test to start from lower frequency than this to check the blind
132 // scan implementation.
133 resetBlindScanStartingFrequency(config, targetFrequency - 100);
134 }
135
Amy Zhangbc15b592020-09-25 15:35:55 -0700136 Result result = frontend_1_1->scan_1_1(config.settings, type, config.settingsExt1_1);
Amy Zhang3ea25a62020-08-04 10:23:52 -0700137 EXPECT_TRUE(result == Result::SUCCESS);
138
139 bool scanMsgLockedReceived = false;
140 bool targetFrequencyReceived = false;
141
142 android::Mutex::Autolock autoLock(mMsgLock);
143wait:
144 while (!mScanMessageReceived) {
145 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
146 EXPECT_TRUE(false) << "Scan message not received within timeout";
147 mScanMessageReceived = false;
148 mScanMsgProcessed = true;
149 return;
150 }
151 }
152
153 if (mScanMessageType != FrontendScanMessageType::END) {
154 if (mScanMessageType == FrontendScanMessageType::LOCKED) {
155 scanMsgLockedReceived = true;
Amy Zhangbc15b592020-09-25 15:35:55 -0700156 Result result = frontend_1_1->scan_1_1(config.settings, type, config.settingsExt1_1);
Amy Zhang3ea25a62020-08-04 10:23:52 -0700157 EXPECT_TRUE(result == Result::SUCCESS);
158 }
159
160 if (mScanMessageType == FrontendScanMessageType::FREQUENCY) {
161 targetFrequencyReceived = mScanMessage.frequencies().size() > 0 &&
162 mScanMessage.frequencies()[0] == targetFrequency;
163 }
164
165 if (mScanMessageType == FrontendScanMessageType::PROGRESS_PERCENT) {
166 ALOGD("[vts] Scan in progress...[%d%%]", mScanMessage.progressPercent());
167 }
168
169 mScanMessageReceived = false;
170 mScanMsgProcessed = true;
171 mMsgCondition.signal();
172 goto wait;
173 }
174
175 EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END";
176 EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
177 mScanMessageReceived = false;
178 mScanMsgProcessed = true;
179}
180
181uint32_t FrontendCallback::getTargetFrequency(FrontendSettings settings, FrontendType type) {
182 switch (type) {
183 case FrontendType::ANALOG:
184 return settings.analog().frequency;
185 case FrontendType::ATSC:
186 return settings.atsc().frequency;
187 case FrontendType::ATSC3:
188 return settings.atsc3().frequency;
189 case FrontendType::DVBC:
190 return settings.dvbc().frequency;
191 case FrontendType::DVBS:
192 return settings.dvbs().frequency;
193 case FrontendType::DVBT:
194 return settings.dvbt().frequency;
195 case FrontendType::ISDBS:
196 return settings.isdbs().frequency;
197 case FrontendType::ISDBS3:
198 return settings.isdbs3().frequency;
199 case FrontendType::ISDBT:
200 return settings.isdbt().frequency;
201 default:
202 return 0;
203 }
204}
205
206void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig& config,
207 uint32_t resetingFreq) {
208 switch (config.type) {
209 case FrontendType::ANALOG:
210 config.settings.analog().frequency = resetingFreq;
211 break;
212 case FrontendType::ATSC:
213 config.settings.atsc().frequency = resetingFreq;
214 break;
215 case FrontendType::ATSC3:
216 config.settings.atsc3().frequency = resetingFreq;
217 break;
218 case FrontendType::DVBC:
219 config.settings.dvbc().frequency = resetingFreq;
220 break;
221 case FrontendType::DVBS:
222 config.settings.dvbs().frequency = resetingFreq;
223 break;
224 case FrontendType::DVBT:
225 config.settings.dvbt().frequency = resetingFreq;
226 break;
227 case FrontendType::ISDBS:
228 config.settings.isdbs().frequency = resetingFreq;
229 break;
230 case FrontendType::ISDBS3:
231 config.settings.isdbs3().frequency = resetingFreq;
232 break;
233 case FrontendType::ISDBT:
234 config.settings.isdbt().frequency = resetingFreq;
235 break;
236 default:
237 // do nothing
238 return;
239 }
240}
241
Amy Zhang45cc57a2020-07-09 22:56:25 -0700242AssertionResult FrontendTests::getFrontendIds() {
243 Result status;
244 mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
245 status = result;
246 mFeIds = frontendIds;
247 });
248 return AssertionResult(status == Result::SUCCESS);
249}
250
251AssertionResult FrontendTests::getFrontendInfo(uint32_t frontendId) {
252 Result status;
253 mService->getFrontendInfo(frontendId, [&](Result result, const FrontendInfo& frontendInfo) {
254 mFrontendInfo = frontendInfo;
255 status = result;
256 });
257 return AssertionResult(status == Result::SUCCESS);
258}
259
260AssertionResult FrontendTests::openFrontendById(uint32_t frontendId) {
261 Result status;
262 mService->openFrontendById(frontendId, [&](Result result, const sp<IFrontend>& frontend) {
263 mFrontend = frontend;
264 status = result;
265 });
266 return AssertionResult(status == Result::SUCCESS);
267}
268
269AssertionResult FrontendTests::setFrontendCallback() {
270 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
271 mFrontendCallback = new FrontendCallback();
272 auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
273 return AssertionResult(callbackStatus.isOk());
274}
275
Amy Zhang3ea25a62020-08-04 10:23:52 -0700276AssertionResult FrontendTests::scanFrontend(FrontendConfig config, FrontendScanType type) {
277 EXPECT_TRUE(mFrontendCallback)
278 << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
279
280 EXPECT_TRUE(mFrontendInfo.type == config.type)
281 << "FrontendConfig does not match the frontend info of the given id.";
282
283 mFrontendCallback->scanTest(mFrontend, config, type);
284 return AssertionResult(true);
285}
286
287AssertionResult FrontendTests::stopScanFrontend() {
288 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
289 Result status;
290 status = mFrontend->stopScan();
Amy Zhang4c49c152020-08-25 21:08:19 -0700291
292 return AssertionResult(status == Result::SUCCESS);
293}
294
295AssertionResult FrontendTests::getFrontendDtmbCaps(uint32_t id) {
296 Result status;
297 mService->getFrontendDtmbCapabilities(
298 id, [&](Result result, const FrontendDtmbCapabilities& /*caps*/) { status = result; });
Amy Zhang3ea25a62020-08-04 10:23:52 -0700299 return AssertionResult(status == Result::SUCCESS);
300}
301
Amy Zhang422bb112020-08-12 15:21:44 -0700302void FrontendTests::verifyFrontendStatusExt1_1(vector<FrontendStatusTypeExt1_1> statusTypes,
303 vector<FrontendStatusExt1_1> expectStatuses) {
Amy Zhang3ea25a62020-08-04 10:23:52 -0700304 ASSERT_TRUE(mFrontend) << "Frontend is not opened yet.";
305 Result status;
Amy Zhang422bb112020-08-12 15:21:44 -0700306 vector<FrontendStatusExt1_1> realStatuses;
Amy Zhang3ea25a62020-08-04 10:23:52 -0700307
Amy Zhang422bb112020-08-12 15:21:44 -0700308 sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
309 frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend);
310 if (frontend_1_1 == nullptr) {
311 EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
312 return;
313 }
314
315 frontend_1_1->getStatusExt1_1(
316 statusTypes, [&](Result result, const hidl_vec<FrontendStatusExt1_1>& statuses) {
317 status = result;
318 realStatuses = statuses;
319 });
Amy Zhang3ea25a62020-08-04 10:23:52 -0700320
321 ASSERT_TRUE(realStatuses.size() == statusTypes.size());
322 for (int i = 0; i < statusTypes.size(); i++) {
Amy Zhang422bb112020-08-12 15:21:44 -0700323 FrontendStatusTypeExt1_1 type = statusTypes[i];
Amy Zhang3ea25a62020-08-04 10:23:52 -0700324 switch (type) {
Amy Zhang422bb112020-08-12 15:21:44 -0700325 case FrontendStatusTypeExt1_1::MODULATIONS: {
326 // TODO: verify modulations
Amy Zhang3ea25a62020-08-04 10:23:52 -0700327 break;
328 }
Amy Zhang422bb112020-08-12 15:21:44 -0700329 case FrontendStatusTypeExt1_1::BERS: {
330 ASSERT_TRUE(std::equal(realStatuses[i].bers().begin(), realStatuses[i].bers().end(),
331 expectStatuses[i].bers().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700332 break;
333 }
Amy Zhang422bb112020-08-12 15:21:44 -0700334 case FrontendStatusTypeExt1_1::CODERATES: {
335 ASSERT_TRUE(std::equal(realStatuses[i].codeRates().begin(),
336 realStatuses[i].codeRates().end(),
337 expectStatuses[i].codeRates().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700338 break;
339 }
Amy Zhang422bb112020-08-12 15:21:44 -0700340 case FrontendStatusTypeExt1_1::GUARD_INTERVAL: {
341 // TODO: verify interval
Amy Zhang3ea25a62020-08-04 10:23:52 -0700342 break;
343 }
Amy Zhang422bb112020-08-12 15:21:44 -0700344 case FrontendStatusTypeExt1_1::TRANSMISSION_MODE: {
345 // TODO: verify tranmission mode
Amy Zhang3ea25a62020-08-04 10:23:52 -0700346 break;
347 }
Amy Zhang422bb112020-08-12 15:21:44 -0700348 case FrontendStatusTypeExt1_1::UEC: {
349 ASSERT_TRUE(realStatuses[i].uec() == expectStatuses[i].uec());
Amy Zhang3ea25a62020-08-04 10:23:52 -0700350 break;
351 }
Amy Zhang422bb112020-08-12 15:21:44 -0700352 case FrontendStatusTypeExt1_1::T2_SYSTEM_ID: {
353 ASSERT_TRUE(realStatuses[i].systemId() == expectStatuses[i].systemId());
Amy Zhang3ea25a62020-08-04 10:23:52 -0700354 break;
355 }
Amy Zhang422bb112020-08-12 15:21:44 -0700356 case FrontendStatusTypeExt1_1::INTERLEAVINGS: {
357 ASSERT_TRUE(std::equal(realStatuses[i].interleaving().begin(),
358 realStatuses[i].interleaving().end(),
359 expectStatuses[i].interleaving().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700360 break;
361 }
Amy Zhang422bb112020-08-12 15:21:44 -0700362 case FrontendStatusTypeExt1_1::ISDBT_SEGMENTS: {
363 ASSERT_TRUE(std::equal(realStatuses[i].isdbtSegment().begin(),
364 realStatuses[i].isdbtSegment().end(),
365 expectStatuses[i].isdbtSegment().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700366 break;
367 }
Amy Zhang422bb112020-08-12 15:21:44 -0700368 case FrontendStatusTypeExt1_1::TS_DATA_RATES: {
369 ASSERT_TRUE(std::equal(realStatuses[i].tsDataRate().begin(),
370 realStatuses[i].tsDataRate().end(),
371 expectStatuses[i].tsDataRate().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700372 break;
373 }
Amy Zhang422bb112020-08-12 15:21:44 -0700374 default: {
Amy Zhang3ea25a62020-08-04 10:23:52 -0700375 continue;
Amy Zhang422bb112020-08-12 15:21:44 -0700376 }
Amy Zhang3ea25a62020-08-04 10:23:52 -0700377 }
378 }
379 ASSERT_TRUE(status == Result::SUCCESS);
380}
381
Amy Zhang68afca62020-07-20 18:28:58 -0700382AssertionResult FrontendTests::tuneFrontend(FrontendConfig config, bool testWithDemux) {
383 EXPECT_TRUE(mFrontendCallback)
384 << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
385
386 EXPECT_TRUE(mFrontendInfo.type == config.type)
387 << "FrontendConfig does not match the frontend info of the given id.";
388
389 mIsSoftwareFe = config.isSoftwareFe;
390 bool result = true;
391 if (mIsSoftwareFe && testWithDemux) {
392 result &= mDvrTests.openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
393 result &= mDvrTests.configDvrPlayback(mDvrConfig.settings) == success();
394 result &= mDvrTests.getDvrPlaybackMQDescriptor() == success();
395 mDvrTests.startPlaybackInputThread(mDvrConfig.playbackInputFile,
396 mDvrConfig.settings.playback());
397 if (!result) {
398 ALOGW("[vts] Software frontend dvr configure failed.");
399 return failure();
400 }
401 }
Amy Zhangbc15b592020-09-25 15:35:55 -0700402 mFrontendCallback->tuneTestOnLock(mFrontend, config.settings, config.settingsExt1_1);
Amy Zhang68afca62020-07-20 18:28:58 -0700403 return AssertionResult(true);
404}
405
406AssertionResult FrontendTests::stopTuneFrontend(bool testWithDemux) {
407 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
408 Result status;
409 status = mFrontend->stopTune();
410 if (mIsSoftwareFe && testWithDemux) {
411 mDvrTests.stopPlaybackThread();
412 mDvrTests.closeDvrPlayback();
413 }
414 return AssertionResult(status == Result::SUCCESS);
415}
416
Amy Zhang45cc57a2020-07-09 22:56:25 -0700417AssertionResult FrontendTests::closeFrontend() {
418 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
419 Result status;
420 status = mFrontend->close();
421 mFrontend = nullptr;
422 mFrontendCallback = nullptr;
423 return AssertionResult(status == Result::SUCCESS);
424}
425
426void FrontendTests::getFrontendIdByType(FrontendType feType, uint32_t& feId) {
427 ASSERT_TRUE(getFrontendIds());
428 ASSERT_TRUE(mFeIds.size() > 0);
429 for (size_t i = 0; i < mFeIds.size(); i++) {
430 ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
431 if (mFrontendInfo.type != feType) {
432 continue;
433 }
434 feId = mFeIds[i];
435 return;
436 }
437 feId = INVALID_ID;
Amy Zhang68afca62020-07-20 18:28:58 -0700438}
Amy Zhang3ea25a62020-08-04 10:23:52 -0700439
440void FrontendTests::tuneTest(FrontendConfig frontendConf) {
441 uint32_t feId;
442 getFrontendIdByType(frontendConf.type, feId);
443 ASSERT_TRUE(feId != INVALID_ID);
444 ASSERT_TRUE(openFrontendById(feId));
445 ASSERT_TRUE(setFrontendCallback());
446 ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
Amy Zhang422bb112020-08-12 15:21:44 -0700447 verifyFrontendStatusExt1_1(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
Amy Zhang3ea25a62020-08-04 10:23:52 -0700448 ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
449 ASSERT_TRUE(closeFrontend());
450}
451
452void FrontendTests::scanTest(FrontendConfig frontendConf, FrontendScanType scanType) {
453 uint32_t feId;
454 getFrontendIdByType(frontendConf.type, feId);
455 ASSERT_TRUE(feId != INVALID_ID);
456 ASSERT_TRUE(openFrontendById(feId));
457 ASSERT_TRUE(setFrontendCallback());
458 ASSERT_TRUE(scanFrontend(frontendConf, scanType));
459 ASSERT_TRUE(stopScanFrontend());
460 ASSERT_TRUE(closeFrontend());
461}
Amy Zhang4c49c152020-08-25 21:08:19 -0700462
463void FrontendTests::getFrontendDtmbCapsTest() {
464 uint32_t feId;
465 getFrontendIdByType(
466 static_cast<FrontendType>(android::hardware::tv::tuner::V1_1::FrontendType::DTMB),
467 feId);
468 if (feId != INVALID_ID) {
469 ALOGD("[vts] Found DTMB Frontend");
470 ASSERT_TRUE(getFrontendDtmbCaps(feId));
471 }
472}