blob: 1700e43553261c9a3ef54c4fbf8c4a591b78bde5 [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 Zhang3ea25a62020-08-04 10:23:52 -070050void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings,
Amy Zhangbc15b592020-09-25 15:35:55 -070051 FrontendSettingsExt1_1 settingsExt1_1) {
Amy Zhang3ea25a62020-08-04 10:23:52 -070052 sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
53 frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(frontend);
54 if (frontend_1_1 == nullptr) {
55 EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
56 return;
57 }
58
Amy Zhangbc15b592020-09-25 15:35:55 -070059 Result result = frontend_1_1->tune_1_1(settings, settingsExt1_1);
Amy Zhang68afca62020-07-20 18:28:58 -070060 EXPECT_TRUE(result == Result::SUCCESS);
61
62 android::Mutex::Autolock autoLock(mMsgLock);
63 while (!mLockMsgReceived) {
64 if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
65 EXPECT_TRUE(false) << "Event LOCKED not received within timeout";
66 mLockMsgReceived = false;
67 return;
68 }
69 }
70 mLockMsgReceived = false;
71}
72
Amy Zhang3ea25a62020-08-04 10:23:52 -070073void FrontendCallback::scanTest(sp<IFrontend>& frontend, FrontendConfig config,
74 FrontendScanType type) {
75 sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
76 frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(frontend);
77 if (frontend_1_1 == nullptr) {
78 EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
79 return;
80 }
81
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);
89 }
90
Amy Zhangbc15b592020-09-25 15:35:55 -070091 Result result = frontend_1_1->scan_1_1(config.settings, type, config.settingsExt1_1);
Amy Zhang3ea25a62020-08-04 10:23:52 -070092 EXPECT_TRUE(result == Result::SUCCESS);
93
94 bool scanMsgLockedReceived = false;
95 bool targetFrequencyReceived = false;
96
97 android::Mutex::Autolock autoLock(mMsgLock);
98wait:
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;
Amy Zhangbc15b592020-09-25 15:35:55 -0700111 Result result = frontend_1_1->scan_1_1(config.settings, type, config.settingsExt1_1);
Amy Zhang3ea25a62020-08-04 10:23:52 -0700112 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 EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
132 mScanMessageReceived = false;
133 mScanMsgProcessed = true;
134}
135
136uint32_t FrontendCallback::getTargetFrequency(FrontendSettings settings, FrontendType type) {
137 switch (type) {
138 case FrontendType::ANALOG:
139 return settings.analog().frequency;
140 case FrontendType::ATSC:
141 return settings.atsc().frequency;
142 case FrontendType::ATSC3:
143 return settings.atsc3().frequency;
144 case FrontendType::DVBC:
145 return settings.dvbc().frequency;
146 case FrontendType::DVBS:
147 return settings.dvbs().frequency;
148 case FrontendType::DVBT:
149 return settings.dvbt().frequency;
150 case FrontendType::ISDBS:
151 return settings.isdbs().frequency;
152 case FrontendType::ISDBS3:
153 return settings.isdbs3().frequency;
154 case FrontendType::ISDBT:
155 return settings.isdbt().frequency;
156 default:
157 return 0;
158 }
159}
160
161void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig& config,
162 uint32_t resetingFreq) {
163 switch (config.type) {
164 case FrontendType::ANALOG:
165 config.settings.analog().frequency = resetingFreq;
166 break;
167 case FrontendType::ATSC:
168 config.settings.atsc().frequency = resetingFreq;
169 break;
170 case FrontendType::ATSC3:
171 config.settings.atsc3().frequency = resetingFreq;
172 break;
173 case FrontendType::DVBC:
174 config.settings.dvbc().frequency = resetingFreq;
175 break;
176 case FrontendType::DVBS:
177 config.settings.dvbs().frequency = resetingFreq;
178 break;
179 case FrontendType::DVBT:
180 config.settings.dvbt().frequency = resetingFreq;
181 break;
182 case FrontendType::ISDBS:
183 config.settings.isdbs().frequency = resetingFreq;
184 break;
185 case FrontendType::ISDBS3:
186 config.settings.isdbs3().frequency = resetingFreq;
187 break;
188 case FrontendType::ISDBT:
189 config.settings.isdbt().frequency = resetingFreq;
190 break;
191 default:
192 // do nothing
193 return;
194 }
195}
196
Amy Zhang45cc57a2020-07-09 22:56:25 -0700197AssertionResult FrontendTests::getFrontendIds() {
198 Result status;
199 mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
200 status = result;
201 mFeIds = frontendIds;
202 });
203 return AssertionResult(status == Result::SUCCESS);
204}
205
206AssertionResult FrontendTests::getFrontendInfo(uint32_t frontendId) {
207 Result status;
208 mService->getFrontendInfo(frontendId, [&](Result result, const FrontendInfo& frontendInfo) {
209 mFrontendInfo = frontendInfo;
210 status = result;
211 });
212 return AssertionResult(status == Result::SUCCESS);
213}
214
215AssertionResult FrontendTests::openFrontendById(uint32_t frontendId) {
216 Result status;
217 mService->openFrontendById(frontendId, [&](Result result, const sp<IFrontend>& frontend) {
218 mFrontend = frontend;
219 status = result;
220 });
221 return AssertionResult(status == Result::SUCCESS);
222}
223
224AssertionResult FrontendTests::setFrontendCallback() {
225 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
226 mFrontendCallback = new FrontendCallback();
227 auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
228 return AssertionResult(callbackStatus.isOk());
229}
230
Amy Zhang3ea25a62020-08-04 10:23:52 -0700231AssertionResult FrontendTests::scanFrontend(FrontendConfig config, FrontendScanType type) {
232 EXPECT_TRUE(mFrontendCallback)
233 << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
234
235 EXPECT_TRUE(mFrontendInfo.type == config.type)
236 << "FrontendConfig does not match the frontend info of the given id.";
237
238 mFrontendCallback->scanTest(mFrontend, config, type);
239 return AssertionResult(true);
240}
241
242AssertionResult FrontendTests::stopScanFrontend() {
243 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
244 Result status;
245 status = mFrontend->stopScan();
Amy Zhang4c49c152020-08-25 21:08:19 -0700246
247 return AssertionResult(status == Result::SUCCESS);
248}
249
250AssertionResult FrontendTests::getFrontendDtmbCaps(uint32_t id) {
251 Result status;
252 mService->getFrontendDtmbCapabilities(
253 id, [&](Result result, const FrontendDtmbCapabilities& /*caps*/) { status = result; });
Amy Zhang3ea25a62020-08-04 10:23:52 -0700254 return AssertionResult(status == Result::SUCCESS);
255}
256
Amy Zhang422bb112020-08-12 15:21:44 -0700257void FrontendTests::verifyFrontendStatusExt1_1(vector<FrontendStatusTypeExt1_1> statusTypes,
258 vector<FrontendStatusExt1_1> expectStatuses) {
Amy Zhang3ea25a62020-08-04 10:23:52 -0700259 ASSERT_TRUE(mFrontend) << "Frontend is not opened yet.";
260 Result status;
Amy Zhang422bb112020-08-12 15:21:44 -0700261 vector<FrontendStatusExt1_1> realStatuses;
Amy Zhang3ea25a62020-08-04 10:23:52 -0700262
Amy Zhang422bb112020-08-12 15:21:44 -0700263 sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
264 frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend);
265 if (frontend_1_1 == nullptr) {
266 EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
267 return;
268 }
269
270 frontend_1_1->getStatusExt1_1(
271 statusTypes, [&](Result result, const hidl_vec<FrontendStatusExt1_1>& statuses) {
272 status = result;
273 realStatuses = statuses;
274 });
Amy Zhang3ea25a62020-08-04 10:23:52 -0700275
276 ASSERT_TRUE(realStatuses.size() == statusTypes.size());
277 for (int i = 0; i < statusTypes.size(); i++) {
Amy Zhang422bb112020-08-12 15:21:44 -0700278 FrontendStatusTypeExt1_1 type = statusTypes[i];
Amy Zhang3ea25a62020-08-04 10:23:52 -0700279 switch (type) {
Amy Zhang422bb112020-08-12 15:21:44 -0700280 case FrontendStatusTypeExt1_1::MODULATIONS: {
281 // TODO: verify modulations
Amy Zhang3ea25a62020-08-04 10:23:52 -0700282 break;
283 }
Amy Zhang422bb112020-08-12 15:21:44 -0700284 case FrontendStatusTypeExt1_1::BERS: {
285 ASSERT_TRUE(std::equal(realStatuses[i].bers().begin(), realStatuses[i].bers().end(),
286 expectStatuses[i].bers().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700287 break;
288 }
Amy Zhang422bb112020-08-12 15:21:44 -0700289 case FrontendStatusTypeExt1_1::CODERATES: {
290 ASSERT_TRUE(std::equal(realStatuses[i].codeRates().begin(),
291 realStatuses[i].codeRates().end(),
292 expectStatuses[i].codeRates().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700293 break;
294 }
Amy Zhang422bb112020-08-12 15:21:44 -0700295 case FrontendStatusTypeExt1_1::GUARD_INTERVAL: {
296 // TODO: verify interval
Amy Zhang3ea25a62020-08-04 10:23:52 -0700297 break;
298 }
Amy Zhang422bb112020-08-12 15:21:44 -0700299 case FrontendStatusTypeExt1_1::TRANSMISSION_MODE: {
300 // TODO: verify tranmission mode
Amy Zhang3ea25a62020-08-04 10:23:52 -0700301 break;
302 }
Amy Zhang422bb112020-08-12 15:21:44 -0700303 case FrontendStatusTypeExt1_1::UEC: {
304 ASSERT_TRUE(realStatuses[i].uec() == expectStatuses[i].uec());
Amy Zhang3ea25a62020-08-04 10:23:52 -0700305 break;
306 }
Amy Zhang422bb112020-08-12 15:21:44 -0700307 case FrontendStatusTypeExt1_1::T2_SYSTEM_ID: {
308 ASSERT_TRUE(realStatuses[i].systemId() == expectStatuses[i].systemId());
Amy Zhang3ea25a62020-08-04 10:23:52 -0700309 break;
310 }
Amy Zhang422bb112020-08-12 15:21:44 -0700311 case FrontendStatusTypeExt1_1::INTERLEAVINGS: {
312 ASSERT_TRUE(std::equal(realStatuses[i].interleaving().begin(),
313 realStatuses[i].interleaving().end(),
314 expectStatuses[i].interleaving().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700315 break;
316 }
Amy Zhang422bb112020-08-12 15:21:44 -0700317 case FrontendStatusTypeExt1_1::ISDBT_SEGMENTS: {
318 ASSERT_TRUE(std::equal(realStatuses[i].isdbtSegment().begin(),
319 realStatuses[i].isdbtSegment().end(),
320 expectStatuses[i].isdbtSegment().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700321 break;
322 }
Amy Zhang422bb112020-08-12 15:21:44 -0700323 case FrontendStatusTypeExt1_1::TS_DATA_RATES: {
324 ASSERT_TRUE(std::equal(realStatuses[i].tsDataRate().begin(),
325 realStatuses[i].tsDataRate().end(),
326 expectStatuses[i].tsDataRate().begin()));
Amy Zhang3ea25a62020-08-04 10:23:52 -0700327 break;
328 }
Amy Zhang422bb112020-08-12 15:21:44 -0700329 default: {
Amy Zhang3ea25a62020-08-04 10:23:52 -0700330 continue;
Amy Zhang422bb112020-08-12 15:21:44 -0700331 }
Amy Zhang3ea25a62020-08-04 10:23:52 -0700332 }
333 }
334 ASSERT_TRUE(status == Result::SUCCESS);
335}
336
Amy Zhang68afca62020-07-20 18:28:58 -0700337AssertionResult FrontendTests::tuneFrontend(FrontendConfig config, bool testWithDemux) {
338 EXPECT_TRUE(mFrontendCallback)
339 << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
340
341 EXPECT_TRUE(mFrontendInfo.type == config.type)
342 << "FrontendConfig does not match the frontend info of the given id.";
343
344 mIsSoftwareFe = config.isSoftwareFe;
345 bool result = true;
346 if (mIsSoftwareFe && testWithDemux) {
347 result &= mDvrTests.openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
348 result &= mDvrTests.configDvrPlayback(mDvrConfig.settings) == success();
349 result &= mDvrTests.getDvrPlaybackMQDescriptor() == success();
350 mDvrTests.startPlaybackInputThread(mDvrConfig.playbackInputFile,
351 mDvrConfig.settings.playback());
352 if (!result) {
353 ALOGW("[vts] Software frontend dvr configure failed.");
354 return failure();
355 }
356 }
Amy Zhangbc15b592020-09-25 15:35:55 -0700357 mFrontendCallback->tuneTestOnLock(mFrontend, config.settings, config.settingsExt1_1);
Amy Zhang68afca62020-07-20 18:28:58 -0700358 return AssertionResult(true);
359}
360
361AssertionResult FrontendTests::stopTuneFrontend(bool testWithDemux) {
362 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
363 Result status;
364 status = mFrontend->stopTune();
365 if (mIsSoftwareFe && testWithDemux) {
366 mDvrTests.stopPlaybackThread();
367 mDvrTests.closeDvrPlayback();
368 }
369 return AssertionResult(status == Result::SUCCESS);
370}
371
Amy Zhang45cc57a2020-07-09 22:56:25 -0700372AssertionResult FrontendTests::closeFrontend() {
373 EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
374 Result status;
375 status = mFrontend->close();
376 mFrontend = nullptr;
377 mFrontendCallback = nullptr;
378 return AssertionResult(status == Result::SUCCESS);
379}
380
381void FrontendTests::getFrontendIdByType(FrontendType feType, uint32_t& feId) {
382 ASSERT_TRUE(getFrontendIds());
383 ASSERT_TRUE(mFeIds.size() > 0);
384 for (size_t i = 0; i < mFeIds.size(); i++) {
385 ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
386 if (mFrontendInfo.type != feType) {
387 continue;
388 }
389 feId = mFeIds[i];
390 return;
391 }
392 feId = INVALID_ID;
Amy Zhang68afca62020-07-20 18:28:58 -0700393}
Amy Zhang3ea25a62020-08-04 10:23:52 -0700394
395void FrontendTests::tuneTest(FrontendConfig frontendConf) {
396 uint32_t feId;
397 getFrontendIdByType(frontendConf.type, feId);
398 ASSERT_TRUE(feId != INVALID_ID);
399 ASSERT_TRUE(openFrontendById(feId));
400 ASSERT_TRUE(setFrontendCallback());
401 ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
Amy Zhang422bb112020-08-12 15:21:44 -0700402 verifyFrontendStatusExt1_1(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
Amy Zhang3ea25a62020-08-04 10:23:52 -0700403 ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
404 ASSERT_TRUE(closeFrontend());
405}
406
407void FrontendTests::scanTest(FrontendConfig frontendConf, FrontendScanType scanType) {
408 uint32_t feId;
409 getFrontendIdByType(frontendConf.type, feId);
410 ASSERT_TRUE(feId != INVALID_ID);
411 ASSERT_TRUE(openFrontendById(feId));
412 ASSERT_TRUE(setFrontendCallback());
413 ASSERT_TRUE(scanFrontend(frontendConf, scanType));
414 ASSERT_TRUE(stopScanFrontend());
415 ASSERT_TRUE(closeFrontend());
416}
Amy Zhang4c49c152020-08-25 21:08:19 -0700417
418void FrontendTests::getFrontendDtmbCapsTest() {
419 uint32_t feId;
420 getFrontendIdByType(
421 static_cast<FrontendType>(android::hardware::tv::tuner::V1_1::FrontendType::DTMB),
422 feId);
423 if (feId != INVALID_ID) {
424 ALOGD("[vts] Found DTMB Frontend");
425 ASSERT_TRUE(getFrontendDtmbCaps(feId));
426 }
427}