blob: e5793c1f345d959412248ef0d7fac4b2013df167 [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);
Amy Zhang7ec2b702020-10-05 18:07:20 -070054 switch (message.getDiscriminator()) {
55 case FrontendScanMessageExt1_1::hidl_discriminator::modulation:
56 readFrontendScanMessageExt1_1Modulation(message.modulation());
57 break;
58 case FrontendScanMessageExt1_1::hidl_discriminator::isHighPriority:
59 ALOGD("[vts] frontend ext1_1 scan message high priority: %d", message.isHighPriority());
Amy Zhang19ed17b2020-08-04 10:23:52 -070060 break;
61 default:
62 break;
63 }
64 return Void();
65}
66
67void FrontendCallback::readFrontendScanMessageExt1_1Modulation(FrontendModulation modulation) {
68 switch (modulation.getDiscriminator()) {
69 case FrontendModulation::hidl_discriminator::dvbc:
70 ALOGD("[vts] frontend ext1_1 scan message modulation dvbc: %d", modulation.dvbc());
71 break;
72 case FrontendModulation::hidl_discriminator::dvbs:
73 ALOGD("[vts] frontend ext1_1 scan message modulation dvbs: %d", modulation.dvbs());
74 break;
75 case FrontendModulation::hidl_discriminator::isdbs:
76 ALOGD("[vts] frontend ext1_1 scan message modulation isdbs: %d", modulation.isdbs());
77 break;
78 case FrontendModulation::hidl_discriminator::isdbs3:
79 ALOGD("[vts] frontend ext1_1 scan message modulation isdbs3: %d", modulation.isdbs3());
80 break;
81 case FrontendModulation::hidl_discriminator::isdbt:
82 ALOGD("[vts] frontend ext1_1 scan message modulation isdbt: %d", modulation.isdbt());
83 break;
84 case FrontendModulation::hidl_discriminator::atsc:
85 ALOGD("[vts] frontend ext1_1 scan message modulation atsc: %d", modulation.atsc());
86 break;
87 case FrontendModulation::hidl_discriminator::atsc3:
88 ALOGD("[vts] frontend ext1_1 scan message modulation atsc3: %d", modulation.atsc3());
89 break;
90 case FrontendModulation::hidl_discriminator::dvbt:
91 ALOGD("[vts] frontend ext1_1 scan message modulation dvbt: %d", modulation.dvbt());
92 break;
93 default:
94 break;
95 }
96}
97
Amy Zhang3ea25a62020-08-04 10:23:52 -070098void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings,
Amy Zhangbc15b592020-09-25 15:35:55 -070099 FrontendSettingsExt1_1 settingsExt1_1) {
Amy Zhang3ea25a62020-08-04 10:23:52 -0700100 sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
101 frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(frontend);
102 if (frontend_1_1 == nullptr) {
103 EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
104 return;
105 }
106
Amy Zhangbc15b592020-09-25 15:35:55 -0700107 Result result = frontend_1_1->tune_1_1(settings, settingsExt1_1);
Amy Zhang68afca62020-07-20 18:28:58 -0700108 EXPECT_TRUE(result == Result::SUCCESS);
109
110 android::Mutex::Autolock autoLock(mMsgLock);
111 while (!mLockMsgReceived) {
112 if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
113 EXPECT_TRUE(false) << "Event LOCKED not received within timeout";
114 mLockMsgReceived = false;
115 return;
116 }
117 }
118 mLockMsgReceived = false;
119}
120
Amy Zhang3ea25a62020-08-04 10:23:52 -0700121void FrontendCallback::scanTest(sp<IFrontend>& frontend, FrontendConfig config,
122 FrontendScanType type) {
123 sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
124 frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(frontend);
125 if (frontend_1_1 == nullptr) {
126 EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
127 return;
128 }
129
130 uint32_t targetFrequency = getTargetFrequency(config.settings, config.type);
131 if (type == FrontendScanType::SCAN_BLIND) {
132 // reset the frequency in the scan configuration to test blind scan. The settings param of
133 // passed in means the real input config on the transponder connected to the DUT.
134 // We want the blind the test to start from lower frequency than this to check the blind
135 // scan implementation.
136 resetBlindScanStartingFrequency(config, targetFrequency - 100);
137 }
138
Amy Zhangbc15b592020-09-25 15:35:55 -0700139 Result result = frontend_1_1->scan_1_1(config.settings, type, config.settingsExt1_1);
Amy Zhang3ea25a62020-08-04 10:23:52 -0700140 EXPECT_TRUE(result == Result::SUCCESS);
141
142 bool scanMsgLockedReceived = false;
143 bool targetFrequencyReceived = false;
144
145 android::Mutex::Autolock autoLock(mMsgLock);
146wait:
147 while (!mScanMessageReceived) {
148 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
149 EXPECT_TRUE(false) << "Scan message not received within timeout";
150 mScanMessageReceived = false;
151 mScanMsgProcessed = true;
152 return;
153 }
154 }
155
156 if (mScanMessageType != FrontendScanMessageType::END) {
157 if (mScanMessageType == FrontendScanMessageType::LOCKED) {
158 scanMsgLockedReceived = true;
Amy Zhangbc15b592020-09-25 15:35:55 -0700159 Result result = frontend_1_1->scan_1_1(config.settings, type, config.settingsExt1_1);
Amy Zhang3ea25a62020-08-04 10:23:52 -0700160 EXPECT_TRUE(result == Result::SUCCESS);
161 }
162
163 if (mScanMessageType == FrontendScanMessageType::FREQUENCY) {
164 targetFrequencyReceived = mScanMessage.frequencies().size() > 0 &&
165 mScanMessage.frequencies()[0] == targetFrequency;
166 }
167
168 if (mScanMessageType == FrontendScanMessageType::PROGRESS_PERCENT) {
169 ALOGD("[vts] Scan in progress...[%d%%]", mScanMessage.progressPercent());
170 }
171
172 mScanMessageReceived = false;
173 mScanMsgProcessed = true;
174 mMsgCondition.signal();
175 goto wait;
176 }
177
178 EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END";
179 EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
180 mScanMessageReceived = false;
181 mScanMsgProcessed = true;
182}
183
184uint32_t FrontendCallback::getTargetFrequency(FrontendSettings settings, FrontendType type) {
185 switch (type) {
186 case FrontendType::ANALOG:
187 return settings.analog().frequency;
188 case FrontendType::ATSC:
189 return settings.atsc().frequency;
190 case FrontendType::ATSC3:
191 return settings.atsc3().frequency;
192 case FrontendType::DVBC:
193 return settings.dvbc().frequency;
194 case FrontendType::DVBS:
195 return settings.dvbs().frequency;
196 case FrontendType::DVBT:
197 return settings.dvbt().frequency;
198 case FrontendType::ISDBS:
199 return settings.isdbs().frequency;
200 case FrontendType::ISDBS3:
201 return settings.isdbs3().frequency;
202 case FrontendType::ISDBT:
203 return settings.isdbt().frequency;
204 default:
205 return 0;
206 }
207}
208
209void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig& config,
210 uint32_t resetingFreq) {
211 switch (config.type) {
212 case FrontendType::ANALOG:
213 config.settings.analog().frequency = resetingFreq;
214 break;
215 case FrontendType::ATSC:
216 config.settings.atsc().frequency = resetingFreq;
217 break;
218 case FrontendType::ATSC3:
219 config.settings.atsc3().frequency = resetingFreq;
220 break;
221 case FrontendType::DVBC:
222 config.settings.dvbc().frequency = resetingFreq;
223 break;
224 case FrontendType::DVBS:
225 config.settings.dvbs().frequency = resetingFreq;
226 break;
227 case FrontendType::DVBT:
228 config.settings.dvbt().frequency = resetingFreq;
229 break;
230 case FrontendType::ISDBS:
231 config.settings.isdbs().frequency = resetingFreq;
232 break;
233 case FrontendType::ISDBS3:
234 config.settings.isdbs3().frequency = resetingFreq;
235 break;
236 case FrontendType::ISDBT:
237 config.settings.isdbt().frequency = resetingFreq;
238 break;
239 default:
240 // do nothing
241 return;
242 }
243}
244
Amy Zhang45cc57a2020-07-09 22:56:25 -0700245AssertionResult FrontendTests::getFrontendIds() {
246 Result status;
247 mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
248 status = result;
249 mFeIds = frontendIds;
250 });
251 return AssertionResult(status == Result::SUCCESS);
252}
253
254AssertionResult FrontendTests::getFrontendInfo(uint32_t frontendId) {
255 Result status;
256 mService->getFrontendInfo(frontendId, [&](Result result, const FrontendInfo& frontendInfo) {
257 mFrontendInfo = frontendInfo;
258 status = result;
259 });
260 return AssertionResult(status == Result::SUCCESS);
261}
262
263AssertionResult FrontendTests::openFrontendById(uint32_t frontendId) {
264 Result status;
265 mService->openFrontendById(frontendId, [&](Result result, const sp<IFrontend>& frontend) {
266 mFrontend = frontend;
267 status = result;
268 });
269 return AssertionResult(status == Result::SUCCESS);
270}
271
272AssertionResult FrontendTests::setFrontendCallback() {
273 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
274 mFrontendCallback = new FrontendCallback();
275 auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
276 return AssertionResult(callbackStatus.isOk());
277}
278
Amy Zhang3ea25a62020-08-04 10:23:52 -0700279AssertionResult FrontendTests::scanFrontend(FrontendConfig config, FrontendScanType type) {
280 EXPECT_TRUE(mFrontendCallback)
281 << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
282
283 EXPECT_TRUE(mFrontendInfo.type == config.type)
284 << "FrontendConfig does not match the frontend info of the given id.";
285
286 mFrontendCallback->scanTest(mFrontend, config, type);
287 return AssertionResult(true);
288}
289
290AssertionResult FrontendTests::stopScanFrontend() {
291 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
292 Result status;
293 status = mFrontend->stopScan();
Amy Zhang4c49c152020-08-25 21:08:19 -0700294
295 return AssertionResult(status == Result::SUCCESS);
296}
297
298AssertionResult FrontendTests::getFrontendDtmbCaps(uint32_t id) {
299 Result status;
300 mService->getFrontendDtmbCapabilities(
301 id, [&](Result result, const FrontendDtmbCapabilities& /*caps*/) { status = result; });
Amy Zhang3ea25a62020-08-04 10:23:52 -0700302 return AssertionResult(status == Result::SUCCESS);
303}
304
Amy Zhang422bb112020-08-12 15:21:44 -0700305void FrontendTests::verifyFrontendStatusExt1_1(vector<FrontendStatusTypeExt1_1> statusTypes,
306 vector<FrontendStatusExt1_1> expectStatuses) {
Amy Zhang3ea25a62020-08-04 10:23:52 -0700307 ASSERT_TRUE(mFrontend) << "Frontend is not opened yet.";
308 Result status;
Amy Zhang422bb112020-08-12 15:21:44 -0700309 vector<FrontendStatusExt1_1> realStatuses;
Amy Zhang3ea25a62020-08-04 10:23:52 -0700310
Amy Zhang422bb112020-08-12 15:21:44 -0700311 sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
312 frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend);
313 if (frontend_1_1 == nullptr) {
314 EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
315 return;
316 }
317
318 frontend_1_1->getStatusExt1_1(
319 statusTypes, [&](Result result, const hidl_vec<FrontendStatusExt1_1>& statuses) {
320 status = result;
321 realStatuses = statuses;
322 });
Amy Zhang3ea25a62020-08-04 10:23:52 -0700323
324 ASSERT_TRUE(realStatuses.size() == statusTypes.size());
325 for (int i = 0; i < statusTypes.size(); i++) {
Amy Zhang422bb112020-08-12 15:21:44 -0700326 FrontendStatusTypeExt1_1 type = statusTypes[i];
Amy Zhang3ea25a62020-08-04 10:23:52 -0700327 switch (type) {
Amy Zhang422bb112020-08-12 15:21:44 -0700328 case FrontendStatusTypeExt1_1::MODULATIONS: {
329 // TODO: verify modulations
Amy Zhang3ea25a62020-08-04 10:23:52 -0700330 break;
331 }
Amy Zhang422bb112020-08-12 15:21:44 -0700332 case FrontendStatusTypeExt1_1::BERS: {
333 ASSERT_TRUE(std::equal(realStatuses[i].bers().begin(), realStatuses[i].bers().end(),
334 expectStatuses[i].bers().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700335 break;
336 }
Amy Zhang422bb112020-08-12 15:21:44 -0700337 case FrontendStatusTypeExt1_1::CODERATES: {
338 ASSERT_TRUE(std::equal(realStatuses[i].codeRates().begin(),
339 realStatuses[i].codeRates().end(),
340 expectStatuses[i].codeRates().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700341 break;
342 }
Amy Zhang422bb112020-08-12 15:21:44 -0700343 case FrontendStatusTypeExt1_1::GUARD_INTERVAL: {
344 // TODO: verify interval
Amy Zhang3ea25a62020-08-04 10:23:52 -0700345 break;
346 }
Amy Zhang422bb112020-08-12 15:21:44 -0700347 case FrontendStatusTypeExt1_1::TRANSMISSION_MODE: {
348 // TODO: verify tranmission mode
Amy Zhang3ea25a62020-08-04 10:23:52 -0700349 break;
350 }
Amy Zhang422bb112020-08-12 15:21:44 -0700351 case FrontendStatusTypeExt1_1::UEC: {
352 ASSERT_TRUE(realStatuses[i].uec() == expectStatuses[i].uec());
Amy Zhang3ea25a62020-08-04 10:23:52 -0700353 break;
354 }
Amy Zhang422bb112020-08-12 15:21:44 -0700355 case FrontendStatusTypeExt1_1::T2_SYSTEM_ID: {
356 ASSERT_TRUE(realStatuses[i].systemId() == expectStatuses[i].systemId());
Amy Zhang3ea25a62020-08-04 10:23:52 -0700357 break;
358 }
Amy Zhang422bb112020-08-12 15:21:44 -0700359 case FrontendStatusTypeExt1_1::INTERLEAVINGS: {
360 ASSERT_TRUE(std::equal(realStatuses[i].interleaving().begin(),
361 realStatuses[i].interleaving().end(),
362 expectStatuses[i].interleaving().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700363 break;
364 }
Amy Zhang422bb112020-08-12 15:21:44 -0700365 case FrontendStatusTypeExt1_1::ISDBT_SEGMENTS: {
366 ASSERT_TRUE(std::equal(realStatuses[i].isdbtSegment().begin(),
367 realStatuses[i].isdbtSegment().end(),
368 expectStatuses[i].isdbtSegment().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700369 break;
370 }
Amy Zhang422bb112020-08-12 15:21:44 -0700371 case FrontendStatusTypeExt1_1::TS_DATA_RATES: {
372 ASSERT_TRUE(std::equal(realStatuses[i].tsDataRate().begin(),
373 realStatuses[i].tsDataRate().end(),
374 expectStatuses[i].tsDataRate().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700375 break;
376 }
Amy Zhang422bb112020-08-12 15:21:44 -0700377 default: {
Amy Zhang3ea25a62020-08-04 10:23:52 -0700378 continue;
Amy Zhang422bb112020-08-12 15:21:44 -0700379 }
Amy Zhang3ea25a62020-08-04 10:23:52 -0700380 }
381 }
382 ASSERT_TRUE(status == Result::SUCCESS);
383}
384
Amy Zhang68afca62020-07-20 18:28:58 -0700385AssertionResult FrontendTests::tuneFrontend(FrontendConfig config, bool testWithDemux) {
386 EXPECT_TRUE(mFrontendCallback)
387 << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
388
389 EXPECT_TRUE(mFrontendInfo.type == config.type)
390 << "FrontendConfig does not match the frontend info of the given id.";
391
392 mIsSoftwareFe = config.isSoftwareFe;
393 bool result = true;
394 if (mIsSoftwareFe && testWithDemux) {
395 result &= mDvrTests.openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
396 result &= mDvrTests.configDvrPlayback(mDvrConfig.settings) == success();
397 result &= mDvrTests.getDvrPlaybackMQDescriptor() == success();
398 mDvrTests.startPlaybackInputThread(mDvrConfig.playbackInputFile,
399 mDvrConfig.settings.playback());
400 if (!result) {
401 ALOGW("[vts] Software frontend dvr configure failed.");
402 return failure();
403 }
404 }
Amy Zhangbc15b592020-09-25 15:35:55 -0700405 mFrontendCallback->tuneTestOnLock(mFrontend, config.settings, config.settingsExt1_1);
Amy Zhang68afca62020-07-20 18:28:58 -0700406 return AssertionResult(true);
407}
408
409AssertionResult FrontendTests::stopTuneFrontend(bool testWithDemux) {
410 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
411 Result status;
412 status = mFrontend->stopTune();
413 if (mIsSoftwareFe && testWithDemux) {
414 mDvrTests.stopPlaybackThread();
415 mDvrTests.closeDvrPlayback();
416 }
417 return AssertionResult(status == Result::SUCCESS);
418}
419
Amy Zhang45cc57a2020-07-09 22:56:25 -0700420AssertionResult FrontendTests::closeFrontend() {
421 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
422 Result status;
423 status = mFrontend->close();
424 mFrontend = nullptr;
425 mFrontendCallback = nullptr;
426 return AssertionResult(status == Result::SUCCESS);
427}
428
429void FrontendTests::getFrontendIdByType(FrontendType feType, uint32_t& feId) {
430 ASSERT_TRUE(getFrontendIds());
431 ASSERT_TRUE(mFeIds.size() > 0);
432 for (size_t i = 0; i < mFeIds.size(); i++) {
433 ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
434 if (mFrontendInfo.type != feType) {
435 continue;
436 }
437 feId = mFeIds[i];
438 return;
439 }
440 feId = INVALID_ID;
Amy Zhang68afca62020-07-20 18:28:58 -0700441}
Amy Zhang3ea25a62020-08-04 10:23:52 -0700442
443void FrontendTests::tuneTest(FrontendConfig frontendConf) {
444 uint32_t feId;
445 getFrontendIdByType(frontendConf.type, feId);
446 ASSERT_TRUE(feId != INVALID_ID);
447 ASSERT_TRUE(openFrontendById(feId));
448 ASSERT_TRUE(setFrontendCallback());
449 ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
Amy Zhang422bb112020-08-12 15:21:44 -0700450 verifyFrontendStatusExt1_1(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
Amy Zhang3ea25a62020-08-04 10:23:52 -0700451 ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
452 ASSERT_TRUE(closeFrontend());
453}
454
455void FrontendTests::scanTest(FrontendConfig frontendConf, FrontendScanType scanType) {
456 uint32_t feId;
457 getFrontendIdByType(frontendConf.type, feId);
458 ASSERT_TRUE(feId != INVALID_ID);
459 ASSERT_TRUE(openFrontendById(feId));
460 ASSERT_TRUE(setFrontendCallback());
461 ASSERT_TRUE(scanFrontend(frontendConf, scanType));
462 ASSERT_TRUE(stopScanFrontend());
463 ASSERT_TRUE(closeFrontend());
464}
Amy Zhang4c49c152020-08-25 21:08:19 -0700465
466void FrontendTests::getFrontendDtmbCapsTest() {
467 uint32_t feId;
468 getFrontendIdByType(
469 static_cast<FrontendType>(android::hardware::tv::tuner::V1_1::FrontendType::DTMB),
470 feId);
471 if (feId != INVALID_ID) {
472 ALOGD("[vts] Found DTMB Frontend");
473 ASSERT_TRUE(getFrontendDtmbCaps(feId));
474 }
475}