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 
onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type,const FrontendScanMessageExt1_1 & message)50 Return<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 (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());
60             break;
61         case FrontendScanMessageExt1_1::hidl_discriminator::annex:
62             ALOGD("[vts] frontend ext1_1 scan message dvbc annex: %hhu", message.annex());
63             break;
64         default:
65             break;
66     }
67     return Void();
68 }
69 
readFrontendScanMessageExt1_1Modulation(FrontendModulation modulation)70 void FrontendCallback::readFrontendScanMessageExt1_1Modulation(FrontendModulation modulation) {
71     switch (modulation.getDiscriminator()) {
72         case FrontendModulation::hidl_discriminator::dvbc:
73             ALOGD("[vts] frontend ext1_1 scan message modulation dvbc: %d", modulation.dvbc());
74             break;
75         case FrontendModulation::hidl_discriminator::dvbs:
76             ALOGD("[vts] frontend ext1_1 scan message modulation dvbs: %d", modulation.dvbs());
77             break;
78         case FrontendModulation::hidl_discriminator::isdbs:
79             ALOGD("[vts] frontend ext1_1 scan message modulation isdbs: %d", modulation.isdbs());
80             break;
81         case FrontendModulation::hidl_discriminator::isdbs3:
82             ALOGD("[vts] frontend ext1_1 scan message modulation isdbs3: %d", modulation.isdbs3());
83             break;
84         case FrontendModulation::hidl_discriminator::isdbt:
85             ALOGD("[vts] frontend ext1_1 scan message modulation isdbt: %d", modulation.isdbt());
86             break;
87         case FrontendModulation::hidl_discriminator::atsc:
88             ALOGD("[vts] frontend ext1_1 scan message modulation atsc: %d", modulation.atsc());
89             break;
90         case FrontendModulation::hidl_discriminator::atsc3:
91             ALOGD("[vts] frontend ext1_1 scan message modulation atsc3: %d", modulation.atsc3());
92             break;
93         case FrontendModulation::hidl_discriminator::dvbt:
94             ALOGD("[vts] frontend ext1_1 scan message modulation dvbt: %d", modulation.dvbt());
95             break;
96         default:
97             break;
98     }
99 }
100 
tuneTestOnLock(sp<IFrontend> & frontend,FrontendSettings settings,FrontendSettingsExt1_1 settingsExt1_1)101 void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings,
102                                       FrontendSettingsExt1_1 settingsExt1_1) {
103     sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
104     frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(frontend);
105     if (frontend_1_1 == nullptr) {
106         EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
107         return;
108     }
109 
110     Result result = frontend_1_1->tune_1_1(settings, settingsExt1_1);
111     EXPECT_TRUE(result == Result::SUCCESS);
112 
113     android::Mutex::Autolock autoLock(mMsgLock);
114     while (!mLockMsgReceived) {
115         if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
116             EXPECT_TRUE(false) << "Event LOCKED not received within timeout";
117             mLockMsgReceived = false;
118             return;
119         }
120     }
121     mLockMsgReceived = false;
122 }
123 
scanTest(sp<IFrontend> & frontend,FrontendConfig1_1 config,FrontendScanType type)124 void FrontendCallback::scanTest(sp<IFrontend>& frontend, FrontendConfig1_1 config,
125                                 FrontendScanType type) {
126     sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
127     frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(frontend);
128     if (frontend_1_1 == nullptr) {
129         EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
130         return;
131     }
132 
133     uint32_t targetFrequency = getTargetFrequency(config.config1_0.settings);
134     if (type == FrontendScanType::SCAN_BLIND) {
135         // reset the frequency in the scan configuration to test blind scan. The settings param of
136         // passed in means the real input config on the transponder connected to the DUT.
137         // We want the blind the test to start from lower frequency than this to check the blind
138         // scan implementation.
139         resetBlindScanStartingFrequency(config, targetFrequency - 100 * 1000);
140     }
141 
142     Result result = frontend_1_1->scan_1_1(config.config1_0.settings, type, config.settingsExt1_1);
143     EXPECT_TRUE(result == Result::SUCCESS);
144 
145     bool scanMsgLockedReceived = false;
146     bool targetFrequencyReceived = false;
147 
148     android::Mutex::Autolock autoLock(mMsgLock);
149 wait:
150     while (!mScanMessageReceived) {
151         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
152             EXPECT_TRUE(false) << "Scan message not received within timeout";
153             mScanMessageReceived = false;
154             mScanMsgProcessed = true;
155             return;
156         }
157     }
158 
159     if (mScanMessageType != FrontendScanMessageType::END) {
160         if (mScanMessageType == FrontendScanMessageType::LOCKED) {
161             scanMsgLockedReceived = true;
162             Result result =
163                     frontend_1_1->scan_1_1(config.config1_0.settings, type, config.settingsExt1_1);
164             EXPECT_TRUE(result == Result::SUCCESS);
165         }
166 
167         if (mScanMessageType == FrontendScanMessageType::FREQUENCY) {
168             targetFrequencyReceived = mScanMessage.frequencies().size() > 0 &&
169                                       mScanMessage.frequencies()[0] == targetFrequency;
170         }
171 
172         if (mScanMessageType == FrontendScanMessageType::PROGRESS_PERCENT) {
173             ALOGD("[vts] Scan in progress...[%d%%]", mScanMessage.progressPercent());
174         }
175 
176         mScanMessageReceived = false;
177         mScanMsgProcessed = true;
178         mMsgCondition.signal();
179         goto wait;
180     }
181 
182     EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END";
183     if (type == FrontendScanType::SCAN_BLIND)
184         EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
185     mScanMessageReceived = false;
186     mScanMsgProcessed = true;
187 }
188 
getTargetFrequency(FrontendSettings settings)189 uint32_t FrontendCallback::getTargetFrequency(FrontendSettings settings) {
190     switch (settings.getDiscriminator()) {
191         case FrontendSettings::hidl_discriminator::analog:
192             return settings.analog().frequency;
193         case FrontendSettings::hidl_discriminator::atsc:
194             return settings.atsc().frequency;
195         case FrontendSettings::hidl_discriminator::atsc3:
196             return settings.atsc3().frequency;
197         case FrontendSettings::hidl_discriminator::dvbc:
198             return settings.dvbc().frequency;
199         case FrontendSettings::hidl_discriminator::dvbs:
200             return settings.dvbs().frequency;
201         case FrontendSettings::hidl_discriminator::dvbt:
202             return settings.dvbt().frequency;
203         case FrontendSettings::hidl_discriminator::isdbs:
204             return settings.isdbs().frequency;
205         case FrontendSettings::hidl_discriminator::isdbs3:
206             return settings.isdbs3().frequency;
207         case FrontendSettings::hidl_discriminator::isdbt:
208             return settings.isdbt().frequency;
209     }
210 }
211 
resetBlindScanStartingFrequency(FrontendConfig1_1 & config,uint32_t resetingFreq)212 void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig1_1& config,
213                                                        uint32_t resetingFreq) {
214     switch (config.config1_0.settings.getDiscriminator()) {
215         case FrontendSettings::hidl_discriminator::analog:
216             config.config1_0.settings.analog().frequency = resetingFreq;
217             break;
218         case FrontendSettings::hidl_discriminator::atsc:
219             config.config1_0.settings.atsc().frequency = resetingFreq;
220             break;
221         case FrontendSettings::hidl_discriminator::atsc3:
222             config.config1_0.settings.atsc3().frequency = resetingFreq;
223             break;
224         case FrontendSettings::hidl_discriminator::dvbc:
225             config.config1_0.settings.dvbc().frequency = resetingFreq;
226             break;
227         case FrontendSettings::hidl_discriminator::dvbs:
228             config.config1_0.settings.dvbs().frequency = resetingFreq;
229             break;
230         case FrontendSettings::hidl_discriminator::dvbt:
231             config.config1_0.settings.dvbt().frequency = resetingFreq;
232             break;
233         case FrontendSettings::hidl_discriminator::isdbs:
234             config.config1_0.settings.isdbs().frequency = resetingFreq;
235             break;
236         case FrontendSettings::hidl_discriminator::isdbs3:
237             config.config1_0.settings.isdbs3().frequency = resetingFreq;
238             break;
239         case FrontendSettings::hidl_discriminator::isdbt:
240             config.config1_0.settings.isdbt().frequency = resetingFreq;
241             break;
242     }
243 }
244 
getFrontendIds()245 AssertionResult 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 
getFrontendInfo(uint32_t frontendId)254 AssertionResult 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 
openFrontendById(uint32_t frontendId)263 AssertionResult 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 
setFrontendCallback()272 AssertionResult 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 
scanFrontend(FrontendConfig1_1 config,FrontendScanType type)279 AssertionResult FrontendTests::scanFrontend(FrontendConfig1_1 config, FrontendScanType type) {
280     EXPECT_TRUE(mFrontendCallback)
281             << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
282 
283     EXPECT_TRUE(mFrontendInfo.type == config.config1_0.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 
stopScanFrontend()290 AssertionResult FrontendTests::stopScanFrontend() {
291     EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
292     Result status;
293     status = mFrontend->stopScan();
294 
295     return AssertionResult(status == Result::SUCCESS);
296 }
297 
getFrontendDtmbCaps(uint32_t id)298 AssertionResult FrontendTests::getFrontendDtmbCaps(uint32_t id) {
299     Result status;
300     mService->getFrontendDtmbCapabilities(
301             id, [&](Result result, const FrontendDtmbCapabilities& /*caps*/) { status = result; });
302     return AssertionResult(status == Result::SUCCESS);
303 }
304 
linkCiCam(uint32_t ciCamId)305 AssertionResult FrontendTests::linkCiCam(uint32_t ciCamId) {
306     sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
307     frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend);
308     if (frontend_1_1 == nullptr) {
309         EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
310         return failure();
311     }
312 
313     Result status;
314     uint32_t ltsId;
315     frontend_1_1->linkCiCam(ciCamId, [&](Result r, uint32_t id) {
316         status = r;
317         ltsId = id;
318     });
319 
320     return AssertionResult(status == Result::SUCCESS);
321 }
322 
unlinkCiCam(uint32_t ciCamId)323 AssertionResult FrontendTests::unlinkCiCam(uint32_t ciCamId) {
324     sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
325     frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend);
326     if (frontend_1_1 == nullptr) {
327         EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
328         return failure();
329     }
330 
331     Result status = frontend_1_1->unlinkCiCam(ciCamId);
332     return AssertionResult(status == Result::SUCCESS);
333 }
334 
verifyFrontendStatusExt1_1(vector<FrontendStatusTypeExt1_1> statusTypes,vector<FrontendStatusExt1_1> expectStatuses)335 void FrontendTests::verifyFrontendStatusExt1_1(vector<FrontendStatusTypeExt1_1> statusTypes,
336                                                vector<FrontendStatusExt1_1> expectStatuses) {
337     ASSERT_TRUE(mFrontend) << "Frontend is not opened yet.";
338     Result status;
339     vector<FrontendStatusExt1_1> realStatuses;
340 
341     sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
342     frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend);
343     if (frontend_1_1 == nullptr) {
344         EXPECT_TRUE(false) << "Couldn't get 1.1 IFrontend from the Hal implementation.";
345         return;
346     }
347 
348     frontend_1_1->getStatusExt1_1(
349             statusTypes, [&](Result result, const hidl_vec<FrontendStatusExt1_1>& statuses) {
350                 status = result;
351                 realStatuses = statuses;
352             });
353 
354     ASSERT_TRUE(realStatuses.size() == statusTypes.size());
355     for (int i = 0; i < statusTypes.size(); i++) {
356         FrontendStatusTypeExt1_1 type = statusTypes[i];
357         switch (type) {
358             case FrontendStatusTypeExt1_1::MODULATIONS: {
359                 // TODO: verify modulations
360                 break;
361             }
362             case FrontendStatusTypeExt1_1::BERS: {
363                 ASSERT_TRUE(std::equal(realStatuses[i].bers().begin(), realStatuses[i].bers().end(),
364                                        expectStatuses[i].bers().begin()));
365                 break;
366             }
367             case FrontendStatusTypeExt1_1::CODERATES: {
368                 ASSERT_TRUE(std::equal(realStatuses[i].codeRates().begin(),
369                                        realStatuses[i].codeRates().end(),
370                                        expectStatuses[i].codeRates().begin()));
371                 break;
372             }
373             case FrontendStatusTypeExt1_1::GUARD_INTERVAL: {
374                 // TODO: verify interval
375                 break;
376             }
377             case FrontendStatusTypeExt1_1::TRANSMISSION_MODE: {
378                 // TODO: verify tranmission mode
379                 break;
380             }
381             case FrontendStatusTypeExt1_1::UEC: {
382                 ASSERT_TRUE(realStatuses[i].uec() >= 0 );
383                 break;
384             }
385             case FrontendStatusTypeExt1_1::T2_SYSTEM_ID: {
386                 ASSERT_TRUE(realStatuses[i].systemId() == expectStatuses[i].systemId());
387                 break;
388             }
389             case FrontendStatusTypeExt1_1::INTERLEAVINGS: {
390                 ASSERT_TRUE(std::equal(realStatuses[i].interleaving().begin(),
391                                        realStatuses[i].interleaving().end(),
392                                        expectStatuses[i].interleaving().begin()));
393                 break;
394             }
395             case FrontendStatusTypeExt1_1::ISDBT_SEGMENTS: {
396                 ASSERT_TRUE(std::equal(realStatuses[i].isdbtSegment().begin(),
397                                        realStatuses[i].isdbtSegment().end(),
398                                        expectStatuses[i].isdbtSegment().begin()));
399                 break;
400             }
401             case FrontendStatusTypeExt1_1::TS_DATA_RATES: {
402                 ASSERT_TRUE(std::equal(realStatuses[i].tsDataRate().begin(),
403                                        realStatuses[i].tsDataRate().end(),
404                                        expectStatuses[i].tsDataRate().begin()));
405                 break;
406             }
407             case FrontendStatusTypeExt1_1::ROLL_OFF: {
408                 // TODO: verify roll off
409                 break;
410             }
411             case FrontendStatusTypeExt1_1::IS_MISO: {
412                 ASSERT_TRUE(realStatuses[i].isMiso() == expectStatuses[i].isMiso());
413                 break;
414             }
415             case FrontendStatusTypeExt1_1::IS_LINEAR: {
416                 ASSERT_TRUE(realStatuses[i].isLinear() == expectStatuses[i].isLinear());
417                 break;
418             }
419             case FrontendStatusTypeExt1_1::IS_SHORT_FRAMES: {
420                 ASSERT_TRUE(realStatuses[i].isShortFrames() == expectStatuses[i].isShortFrames());
421                 break;
422             }
423             default: {
424                 continue;
425             }
426         }
427     }
428     ASSERT_TRUE(status == Result::SUCCESS);
429 }
430 
tuneFrontend(FrontendConfig1_1 config,bool testWithDemux)431 AssertionResult FrontendTests::tuneFrontend(FrontendConfig1_1 config, bool testWithDemux) {
432     EXPECT_TRUE(mFrontendCallback)
433             << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
434 
435     EXPECT_TRUE(mFrontendInfo.type == config.config1_0.type)
436             << "FrontendConfig does not match the frontend info of the given id.";
437 
438     mIsSoftwareFe = config.config1_0.isSoftwareFe;
439     bool result = true;
440     if (mIsSoftwareFe && testWithDemux) {
441         result &=
442                 getDvrTests()->openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
443         result &= getDvrTests()->configDvrPlayback(mDvrConfig.settings) == success();
444         result &= getDvrTests()->getDvrPlaybackMQDescriptor() == success();
445         getDvrTests()->startPlaybackInputThread(mDvrConfig.playbackInputFile,
446                                                 mDvrConfig.settings.playback());
447         getDvrTests()->startDvrPlayback();
448         if (!result) {
449             ALOGW("[vts] Software frontend dvr configure failed.");
450             return failure();
451         }
452     }
453     mFrontendCallback->tuneTestOnLock(mFrontend, config.config1_0.settings, config.settingsExt1_1);
454     return AssertionResult(true);
455 }
456 
stopTuneFrontend(bool testWithDemux)457 AssertionResult FrontendTests::stopTuneFrontend(bool testWithDemux) {
458     EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
459     Result status;
460     status = mFrontend->stopTune();
461     if (mIsSoftwareFe && testWithDemux) {
462         getDvrTests()->stopPlaybackThread();
463         getDvrTests()->stopDvrPlayback();
464         getDvrTests()->closeDvrPlayback();
465     }
466     return AssertionResult(status == Result::SUCCESS);
467 }
468 
closeFrontend()469 AssertionResult FrontendTests::closeFrontend() {
470     EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
471     Result status;
472     status = mFrontend->close();
473     mFrontend = nullptr;
474     mFrontendCallback = nullptr;
475     return AssertionResult(status == Result::SUCCESS);
476 }
477 
getFrontendIdByType(FrontendType feType,uint32_t & feId)478 void FrontendTests::getFrontendIdByType(FrontendType feType, uint32_t& feId) {
479     ASSERT_TRUE(getFrontendIds());
480     for (size_t i = 0; i < mFeIds.size(); i++) {
481         ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
482         if (mFrontendInfo.type != feType) {
483             continue;
484         }
485         feId = mFeIds[i];
486         return;
487     }
488     feId = INVALID_ID;
489 }
490 
tuneTest(FrontendConfig1_1 frontendConf)491 void FrontendTests::tuneTest(FrontendConfig1_1 frontendConf) {
492     uint32_t feId;
493     getFrontendIdByType(frontendConf.config1_0.type, feId);
494     ASSERT_TRUE(feId != INVALID_ID);
495     ASSERT_TRUE(openFrontendById(feId));
496     ASSERT_TRUE(setFrontendCallback());
497     if (frontendConf.canConnectToCiCam) {
498         ASSERT_TRUE(linkCiCam(frontendConf.ciCamId));
499         ASSERT_TRUE(unlinkCiCam(frontendConf.ciCamId));
500     }
501     ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
502     verifyFrontendStatusExt1_1(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
503     ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
504     ASSERT_TRUE(closeFrontend());
505 }
506 
scanTest(FrontendConfig1_1 frontendConf,FrontendScanType scanType)507 void FrontendTests::scanTest(FrontendConfig1_1 frontendConf, FrontendScanType scanType) {
508     uint32_t feId;
509     getFrontendIdByType(frontendConf.config1_0.type, feId);
510     ASSERT_TRUE(feId != INVALID_ID);
511     ASSERT_TRUE(openFrontendById(feId));
512     ASSERT_TRUE(setFrontendCallback());
513     ASSERT_TRUE(scanFrontend(frontendConf, scanType));
514     ASSERT_TRUE(stopScanFrontend());
515     ASSERT_TRUE(closeFrontend());
516 }
517 
getFrontendDtmbCapsTest()518 void FrontendTests::getFrontendDtmbCapsTest() {
519     uint32_t feId;
520     getFrontendIdByType(
521             static_cast<FrontendType>(android::hardware::tv::tuner::V1_1::FrontendType::DTMB),
522             feId);
523     if (feId != INVALID_ID) {
524         ALOGD("[vts] Found DTMB Frontend");
525         ASSERT_TRUE(getFrontendDtmbCaps(feId));
526     }
527 }
528