• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 
19 #include <aidl/android/hardware/tv/tuner/Result.h>
20 
onEvent(FrontendEventType frontendEventType)21 ndk::ScopedAStatus FrontendCallback::onEvent(FrontendEventType frontendEventType) {
22     android::Mutex::Autolock autoLock(mMsgLock);
23     ALOGD("[vts] frontend event received. Type: %d", frontendEventType);
24     mEventReceived = true;
25     mMsgCondition.signal();
26     switch (frontendEventType) {
27         case FrontendEventType::LOCKED:
28             mLockMsgReceived = true;
29             mLockMsgCondition.signal();
30             break;
31         default:
32             // do nothing
33             break;
34     }
35     return ndk::ScopedAStatus::ok();
36 }
37 
onScanMessage(FrontendScanMessageType type,const FrontendScanMessage & message)38 ndk::ScopedAStatus FrontendCallback::onScanMessage(FrontendScanMessageType type,
39                                                    const FrontendScanMessage& message) {
40     android::Mutex::Autolock autoLock(mMsgLock);
41     while (!mScanMsgProcessed) {
42         mMsgCondition.wait(mMsgLock);
43     }
44     ALOGD("[vts] frontend scan message. Type: %d", type);
45     switch (message.getTag()) {
46         case FrontendScanMessage::modulation:
47             readFrontendScanMessage_Modulation(message.get<FrontendScanMessage::Tag::modulation>());
48             break;
49         case FrontendScanMessage::Tag::isHighPriority:
50             ALOGD("[vts] frontend scan message high priority: %d",
51                   message.get<FrontendScanMessage::Tag::isHighPriority>());
52             break;
53         case FrontendScanMessage::Tag::annex:
54             ALOGD("[vts] frontend scan message dvbc annex: %hhu",
55                   message.get<FrontendScanMessage::Tag::annex>());
56             break;
57         default:
58             break;
59     }
60     mScanMessageReceived = true;
61     mScanMsgProcessed = false;
62     mScanMessageType = type;
63     mScanMessage = message;
64     mMsgCondition.signal();
65     return ndk::ScopedAStatus::ok();
66 }
67 
readFrontendScanMessage_Modulation(FrontendModulation modulation)68 void FrontendCallback::readFrontendScanMessage_Modulation(FrontendModulation modulation) {
69     switch (modulation.getTag()) {
70         case FrontendModulation::Tag::dvbc:
71             ALOGD("[vts] frontend scan message modulation dvbc: %d",
72                   modulation.get<FrontendModulation::Tag::dvbc>());
73             break;
74         case FrontendModulation::Tag::dvbs:
75             ALOGD("[vts] frontend scan message modulation dvbs: %d",
76                   modulation.get<FrontendModulation::Tag::dvbs>());
77             break;
78         case FrontendModulation::Tag::isdbs:
79             ALOGD("[vts] frontend scan message modulation isdbs: %d",
80                   modulation.get<FrontendModulation::Tag::isdbs>());
81             break;
82         case FrontendModulation::Tag::isdbs3:
83             ALOGD("[vts] frontend scan message modulation isdbs3: %d",
84                   modulation.get<FrontendModulation::Tag::isdbs3>());
85             break;
86         case FrontendModulation::Tag::isdbt:
87             ALOGD("[vts] frontend scan message modulation isdbt: %d",
88                   modulation.get<FrontendModulation::Tag::isdbt>());
89             break;
90         case FrontendModulation::Tag::atsc:
91             ALOGD("[vts] frontend scan message modulation atsc: %d",
92                   modulation.get<FrontendModulation::Tag::atsc>());
93             break;
94         case FrontendModulation::Tag::atsc3:
95             ALOGD("[vts] frontend scan message modulation atsc3: %d",
96                   modulation.get<FrontendModulation::Tag::atsc3>());
97             break;
98         case FrontendModulation::Tag::dvbt:
99             ALOGD("[vts] frontend scan message modulation dvbt: %d",
100                   modulation.get<FrontendModulation::Tag::dvbt>());
101             break;
102         default:
103             break;
104     }
105 }
106 
tuneTestOnLock(std::shared_ptr<IFrontend> & frontend,FrontendSettings settings)107 void FrontendCallback::tuneTestOnLock(std::shared_ptr<IFrontend>& frontend,
108                                       FrontendSettings settings) {
109     ndk::ScopedAStatus result = frontend->tune(settings);
110     EXPECT_TRUE(result.isOk());
111 
112     android::Mutex::Autolock autoLock(mMsgLock);
113     while (!mLockMsgReceived) {
114         if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
115             EXPECT_TRUE(false) << "Event LOCKED not received within timeout";
116             mLockMsgReceived = false;
117             return;
118         }
119     }
120     mLockMsgReceived = false;
121 }
122 
scanTest(std::shared_ptr<IFrontend> & frontend,FrontendConfig config,FrontendScanType type)123 void FrontendCallback::scanTest(std::shared_ptr<IFrontend>& frontend, FrontendConfig config,
124                                 FrontendScanType type) {
125     int64_t targetFrequency = getTargetFrequency(config.settings);
126     if (type == FrontendScanType::SCAN_BLIND) {
127         // reset the frequency in the scan configuration to test blind scan. The settings param of
128         // passed in means the real input config on the transponder connected to the DUT.
129         // We want the blind the test to start from lower frequency than this to check the blind
130         // scan implementation.
131         resetBlindScanStartingFrequency(config, targetFrequency - 100 * 1000);
132     }
133 
134     ndk::ScopedAStatus result = frontend->scan(config.settings, type);
135     EXPECT_TRUE(result.isOk());
136 
137     bool scanMsgLockedReceived = false;
138     bool targetFrequencyReceived = false;
139 
140     android::Mutex::Autolock autoLock(mMsgLock);
141 wait:
142     while (!mScanMessageReceived) {
143         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
144             EXPECT_TRUE(false) << "Scan message not received within timeout";
145             mScanMessageReceived = false;
146             mScanMsgProcessed = true;
147             return;
148         }
149     }
150 
151     if (mScanMessageType != FrontendScanMessageType::END) {
152         if (mScanMessageType == FrontendScanMessageType::LOCKED) {
153             scanMsgLockedReceived = true;
154             result = frontend->scan(config.settings, type);
155             EXPECT_TRUE(result.isOk());
156         }
157 
158         if (mScanMessageType == FrontendScanMessageType::FREQUENCY) {
159             targetFrequencyReceived =
160                     mScanMessage.get<FrontendScanMessage::Tag::frequencies>().size() > 0 &&
161                     mScanMessage.get<FrontendScanMessage::Tag::frequencies>()[0] == targetFrequency;
162         }
163 
164         if (mScanMessageType == FrontendScanMessageType::PROGRESS_PERCENT) {
165             ALOGD("[vts] Scan in progress...[%d%%]",
166                   mScanMessage.get<FrontendScanMessage::Tag::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     if (type == FrontendScanType::SCAN_BLIND)
177         EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
178     mScanMessageReceived = false;
179     mScanMsgProcessed = true;
180 }
181 
getTargetFrequency(FrontendSettings & settings)182 int64_t FrontendCallback::getTargetFrequency(FrontendSettings& settings) {
183     switch (settings.getTag()) {
184         case FrontendSettings::Tag::analog:
185             return settings.get<FrontendSettings::Tag::analog>().frequency;
186         case FrontendSettings::Tag::atsc:
187             return settings.get<FrontendSettings::Tag::atsc>().frequency;
188         case FrontendSettings::Tag::atsc3:
189             return settings.get<FrontendSettings::Tag::atsc3>().frequency;
190         case FrontendSettings::Tag::dvbc:
191             return settings.get<FrontendSettings::Tag::dvbc>().frequency;
192         case FrontendSettings::Tag::dvbs:
193             return settings.get<FrontendSettings::Tag::dvbs>().frequency;
194         case FrontendSettings::Tag::dvbt:
195             return settings.get<FrontendSettings::Tag::dvbt>().frequency;
196         case FrontendSettings::Tag::isdbs:
197             return settings.get<FrontendSettings::Tag::isdbs>().frequency;
198         case FrontendSettings::Tag::isdbs3:
199             return settings.get<FrontendSettings::Tag::isdbs3>().frequency;
200         case FrontendSettings::Tag::isdbt:
201             return settings.get<FrontendSettings::Tag::isdbt>().frequency;
202         default:
203             return 0;
204     }
205 }
206 
resetBlindScanStartingFrequency(FrontendConfig & config,int64_t resetingFreq)207 void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig& config,
208                                                        int64_t resetingFreq) {
209     switch (config.settings.getTag()) {
210         case FrontendSettings::Tag::analog:
211             config.settings.get<FrontendSettings::Tag::analog>().frequency = resetingFreq;
212             break;
213         case FrontendSettings::Tag::atsc:
214             config.settings.get<FrontendSettings::Tag::atsc>().frequency = resetingFreq;
215             break;
216         case FrontendSettings::Tag::atsc3:
217             config.settings.get<FrontendSettings::Tag::atsc3>().frequency = resetingFreq;
218             break;
219         case FrontendSettings::Tag::dvbc:
220             config.settings.get<FrontendSettings::Tag::dvbc>().frequency = resetingFreq;
221             break;
222         case FrontendSettings::Tag::dvbs:
223             config.settings.get<FrontendSettings::Tag::dvbs>().frequency = resetingFreq;
224             break;
225         case FrontendSettings::Tag::dvbt:
226             config.settings.get<FrontendSettings::Tag::dvbt>().frequency = resetingFreq;
227             break;
228         case FrontendSettings::Tag::isdbs:
229             config.settings.get<FrontendSettings::Tag::isdbs>().frequency = resetingFreq;
230             break;
231         case FrontendSettings::Tag::isdbs3:
232             config.settings.get<FrontendSettings::Tag::isdbs3>().frequency = resetingFreq;
233             break;
234         case FrontendSettings::Tag::isdbt:
235             config.settings.get<FrontendSettings::Tag::isdbt>().frequency = resetingFreq;
236             break;
237         default:
238             break;
239     }
240 }
241 
getFrontendIds()242 AssertionResult FrontendTests::getFrontendIds() {
243     ndk::ScopedAStatus status;
244     status = mService->getFrontendIds(&mFeIds);
245     return AssertionResult(status.isOk());
246 }
247 
getFrontendInfo(int32_t frontendId)248 AssertionResult FrontendTests::getFrontendInfo(int32_t frontendId) {
249     ndk::ScopedAStatus status;
250     status = mService->getFrontendInfo(frontendId, &mFrontendInfo);
251     return AssertionResult(status.isOk());
252 }
253 
openFrontendById(int32_t frontendId)254 AssertionResult FrontendTests::openFrontendById(int32_t frontendId) {
255     ndk::ScopedAStatus status;
256     status = mService->openFrontendById(frontendId, &mFrontend);
257     return AssertionResult(status.isOk());
258 }
259 
setFrontendCallback()260 AssertionResult FrontendTests::setFrontendCallback() {
261     EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
262     mFrontendCallback = ndk::SharedRefBase::make<FrontendCallback>();
263     auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
264     return AssertionResult(callbackStatus.isOk());
265 }
266 
scanFrontend(FrontendConfig config,FrontendScanType type)267 AssertionResult FrontendTests::scanFrontend(FrontendConfig config, FrontendScanType type) {
268     EXPECT_TRUE(mFrontendCallback)
269             << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
270 
271     EXPECT_TRUE(mFrontendInfo.type == config.type)
272             << "FrontendConfig does not match the frontend info of the given id.";
273 
274     mFrontendCallback->scanTest(mFrontend, config, type);
275     return AssertionResult(true);
276 }
277 
stopScanFrontend()278 AssertionResult FrontendTests::stopScanFrontend() {
279     EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
280     ndk::ScopedAStatus status;
281     status = mFrontend->stopScan();
282 
283     return AssertionResult(status.isOk());
284 }
285 
setLnb(int32_t lnbId)286 AssertionResult FrontendTests::setLnb(int32_t lnbId) {
287     if (!mFrontendCallback) {
288         ALOGW("[vts] open and set frontend callback first.");
289         return failure();
290     }
291     return AssertionResult(mFrontend->setLnb(lnbId).isOk());
292 }
293 
linkCiCam(int32_t ciCamId)294 AssertionResult FrontendTests::linkCiCam(int32_t ciCamId) {
295     ndk::ScopedAStatus status;
296     int32_t ltsId;
297     status = mFrontend->linkCiCam(ciCamId, &ltsId);
298     return AssertionResult(status.isOk());
299 }
300 
removeOutputPid(int32_t removePid)301 AssertionResult FrontendTests::removeOutputPid(int32_t removePid) {
302     ndk::ScopedAStatus status;
303     status = mFrontend->removeOutputPid(removePid);
304     return AssertionResult(status.isOk() || status.getServiceSpecificError() ==
305                                                     static_cast<int32_t>(Result::UNAVAILABLE));
306 }
307 
unlinkCiCam(int32_t ciCamId)308 AssertionResult FrontendTests::unlinkCiCam(int32_t ciCamId) {
309     ndk::ScopedAStatus status = mFrontend->unlinkCiCam(ciCamId);
310     return AssertionResult(status.isOk());
311 }
312 
verifyFrontendStatus(vector<FrontendStatusType> statusTypes,vector<FrontendStatus> expectStatuses)313 void FrontendTests::verifyFrontendStatus(vector<FrontendStatusType> statusTypes,
314                                          vector<FrontendStatus> expectStatuses) {
315     ASSERT_TRUE(mFrontend) << "Frontend is not opened yet.";
316     ndk::ScopedAStatus status;
317     vector<FrontendStatus> realStatuses;
318 
319     status = mFrontend->getStatus(statusTypes, &realStatuses);
320     ASSERT_TRUE(status.isOk() && realStatuses.size() == statusTypes.size());
321 
322     for (int i = 0; i < statusTypes.size(); i++) {
323         FrontendStatusType type = statusTypes[i];
324         switch (type) {
325             case FrontendStatusType::MODULATIONS: {
326                 ASSERT_TRUE(std::equal(
327                         realStatuses[i].get<FrontendStatus::Tag::modulations>().begin(),
328                         realStatuses[i].get<FrontendStatus::Tag::modulations>().end(),
329                         expectStatuses[i].get<FrontendStatus::Tag::modulations>().begin()));
330                 break;
331             }
332             case FrontendStatusType::BERS: {
333                 ASSERT_TRUE(std::equal(realStatuses[i].get<FrontendStatus::Tag::bers>().begin(),
334                                        realStatuses[i].get<FrontendStatus::Tag::bers>().end(),
335                                        expectStatuses[i].get<FrontendStatus::Tag::bers>().begin()));
336                 break;
337             }
338             case FrontendStatusType::CODERATES: {
339                 ASSERT_TRUE(std::equal(
340                         realStatuses[i].get<FrontendStatus::Tag::codeRates>().begin(),
341                         realStatuses[i].get<FrontendStatus::Tag::codeRates>().end(),
342                         expectStatuses[i].get<FrontendStatus::Tag::codeRates>().begin()));
343                 break;
344             }
345             case FrontendStatusType::GUARD_INTERVAL: {
346                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::interval>() ==
347                             expectStatuses[i].get<FrontendStatus::Tag::interval>());
348                 break;
349             }
350             case FrontendStatusType::TRANSMISSION_MODE: {
351                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::transmissionMode>() ==
352                             expectStatuses[i].get<FrontendStatus::Tag::transmissionMode>());
353                 break;
354             }
355             case FrontendStatusType::UEC: {
356                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::uec>() ==
357                             expectStatuses[i].get<FrontendStatus::Tag::uec>());
358                 break;
359             }
360             case FrontendStatusType::T2_SYSTEM_ID: {
361                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::systemId>() ==
362                             expectStatuses[i].get<FrontendStatus::Tag::systemId>());
363                 break;
364             }
365             case FrontendStatusType::INTERLEAVINGS: {
366                 ASSERT_TRUE(std::equal(
367                         realStatuses[i].get<FrontendStatus::Tag::interleaving>().begin(),
368                         realStatuses[i].get<FrontendStatus::Tag::interleaving>().end(),
369                         expectStatuses[i].get<FrontendStatus::Tag::interleaving>().begin()));
370                 break;
371             }
372             case FrontendStatusType::ISDBT_SEGMENTS: {
373                 ASSERT_TRUE(std::equal(
374                         realStatuses[i].get<FrontendStatus::Tag::isdbtSegment>().begin(),
375                         realStatuses[i].get<FrontendStatus::Tag::isdbtSegment>().end(),
376                         expectStatuses[i].get<FrontendStatus::Tag::isdbtSegment>().begin()));
377                 break;
378             }
379             case FrontendStatusType::TS_DATA_RATES: {
380                 ASSERT_TRUE(std::equal(
381                         realStatuses[i].get<FrontendStatus::Tag::tsDataRate>().begin(),
382                         realStatuses[i].get<FrontendStatus::Tag::tsDataRate>().end(),
383                         expectStatuses[i].get<FrontendStatus::Tag::tsDataRate>().begin()));
384                 break;
385             }
386             case FrontendStatusType::ROLL_OFF: {
387                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::rollOff>() ==
388                             expectStatuses[i].get<FrontendStatus::Tag::rollOff>());
389                 break;
390             }
391             case FrontendStatusType::IS_MISO: {
392                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::isMiso>() ==
393                             expectStatuses[i].get<FrontendStatus::Tag::isMiso>());
394                 break;
395             }
396             case FrontendStatusType::IS_LINEAR: {
397                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::isLinear>() ==
398                             expectStatuses[i].get<FrontendStatus::Tag::isLinear>());
399                 break;
400             }
401             case FrontendStatusType::IS_SHORT_FRAMES: {
402                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::isShortFrames>() ==
403                             expectStatuses[i].get<FrontendStatus::Tag::isShortFrames>());
404                 break;
405             }
406             case FrontendStatusType::ISDBT_MODE: {
407                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::isdbtMode>() ==
408                             expectStatuses[i].get<FrontendStatus::Tag::isdbtMode>());
409                 break;
410             }
411             case FrontendStatusType::ISDBT_PARTIAL_RECEPTION_FLAG: {
412                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::partialReceptionFlag>() ==
413                             expectStatuses[i].get<FrontendStatus::Tag::partialReceptionFlag>());
414                 break;
415             }
416             case FrontendStatusType::STREAM_ID_LIST: {
417                 ASSERT_TRUE(std::equal(
418                         realStatuses[i].get<FrontendStatus::Tag::streamIdList>().begin(),
419                         realStatuses[i].get<FrontendStatus::Tag::streamIdList>().end(),
420                         expectStatuses[i].get<FrontendStatus::Tag::streamIdList>().begin()));
421                 break;
422             }
423             case FrontendStatusType::DVBT_CELL_IDS: {
424                 ASSERT_TRUE(std::equal(
425                         realStatuses[i].get<FrontendStatus::Tag::dvbtCellIds>().begin(),
426                         realStatuses[i].get<FrontendStatus::Tag::dvbtCellIds>().end(),
427                         expectStatuses[i].get<FrontendStatus::Tag::dvbtCellIds>().begin()));
428                 break;
429             }
430             case FrontendStatusType::ATSC3_ALL_PLP_INFO: {
431                 ASSERT_TRUE(std::equal(
432                         realStatuses[i].get<FrontendStatus::Tag::allPlpInfo>().begin(),
433                         realStatuses[i].get<FrontendStatus::Tag::allPlpInfo>().end(),
434                         expectStatuses[i].get<FrontendStatus::Tag::allPlpInfo>().begin()));
435                 break;
436             }
437             case FrontendStatusType::IPTV_CONTENT_URL: {
438                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::iptvContentUrl>() ==
439                             expectStatuses[i].get<FrontendStatus::Tag::iptvContentUrl>());
440                 break;
441             }
442             case FrontendStatusType::IPTV_PACKETS_LOST: {
443                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::iptvPacketsLost>() ==
444                             expectStatuses[i].get<FrontendStatus::Tag::iptvPacketsLost>());
445                 break;
446             }
447             case FrontendStatusType::IPTV_PACKETS_RECEIVED: {
448                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::iptvPacketsReceived>() ==
449                             expectStatuses[i].get<FrontendStatus::Tag::iptvPacketsReceived>());
450                 break;
451             }
452             case FrontendStatusType::IPTV_WORST_JITTER_MS: {
453                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::iptvWorstJitterMs>() ==
454                             expectStatuses[i].get<FrontendStatus::Tag::iptvWorstJitterMs>());
455                 break;
456             }
457             case FrontendStatusType::IPTV_AVERAGE_JITTER_MS: {
458                 ASSERT_TRUE(realStatuses[i].get<FrontendStatus::Tag::iptvAverageJitterMs>() ==
459                             expectStatuses[i].get<FrontendStatus::Tag::iptvAverageJitterMs>());
460                 break;
461             }
462             default: {
463                 continue;
464             }
465         }
466     }
467     ASSERT_TRUE(status.isOk());
468 }
469 
tuneFrontend(FrontendConfig config,bool testWithDemux)470 AssertionResult FrontendTests::tuneFrontend(FrontendConfig config, bool testWithDemux) {
471     EXPECT_TRUE(mFrontendCallback)
472             << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
473 
474     EXPECT_TRUE(mFrontendInfo.type == config.type)
475             << "FrontendConfig does not match the frontend info of the given id.";
476 
477     mIsSoftwareFe = config.isSoftwareFe;
478     if (mIsSoftwareFe && testWithDemux) {
479         if (getDvrTests()->openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) != success()) {
480             ALOGW("[vts] Software frontend dvr configure openDvr failed.");
481             return failure();
482         }
483         if (getDvrTests()->configDvrPlayback(mDvrConfig.settings) != success()) {
484             ALOGW("[vts] Software frontend dvr configure Dvr playback failed.");
485             return failure();
486         }
487         if (getDvrTests()->getDvrPlaybackMQDescriptor() != success()) {
488             ALOGW("[vts] Software frontend dvr configure get MQDesc failed.");
489             return failure();
490         }
491         getDvrTests()->startPlaybackInputThread(
492                 mDvrConfig.playbackInputFile,
493                 mDvrConfig.settings.get<DvrSettings::Tag::playback>());
494         getDvrTests()->startDvrPlayback();
495     }
496     mFrontendCallback->tuneTestOnLock(mFrontend, config.settings);
497     return AssertionResult(true);
498 }
499 
stopTuneFrontend(bool testWithDemux)500 AssertionResult FrontendTests::stopTuneFrontend(bool testWithDemux) {
501     EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
502     ndk::ScopedAStatus status;
503     status = mFrontend->stopTune();
504     if (mIsSoftwareFe && testWithDemux) {
505         getDvrTests()->stopPlaybackThread();
506         getDvrTests()->stopDvrPlayback();
507         getDvrTests()->closeDvrPlayback();
508     }
509     return AssertionResult(status.isOk());
510 }
511 
closeFrontend()512 AssertionResult FrontendTests::closeFrontend() {
513     EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
514     ndk::ScopedAStatus status;
515     status = mFrontend->close();
516     mFrontend = nullptr;
517     mFrontendCallback = nullptr;
518     return AssertionResult(status.isOk());
519 }
520 
getFrontendIdByType(FrontendType feType,int32_t & feId)521 void FrontendTests::getFrontendIdByType(FrontendType feType, int32_t& feId) {
522     ASSERT_TRUE(getFrontendIds());
523     for (size_t i = 0; i < mFeIds.size(); i++) {
524         ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
525         if (mFrontendInfo.type != feType) {
526             continue;
527         }
528         feId = mFeIds[i];
529         return;
530     }
531     feId = INVALID_ID;
532 }
533 
verifyHardwareInfo()534 AssertionResult FrontendTests::verifyHardwareInfo() {
535     EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
536     std::string info;
537     ndk::ScopedAStatus status = mFrontend->getHardwareInfo(&info);
538     return AssertionResult(status.isOk() && !info.empty());
539 }
540 
tuneTest(FrontendConfig frontendConf)541 void FrontendTests::tuneTest(FrontendConfig frontendConf) {
542     int32_t feId;
543     getFrontendIdByType(frontendConf.type, feId);
544     ASSERT_TRUE(feId != INVALID_ID);
545     ASSERT_TRUE(openFrontendById(feId));
546     ASSERT_TRUE(setFrontendCallback());
547     if (frontendConf.canConnectToCiCam) {
548         ASSERT_TRUE(linkCiCam(frontendConf.ciCamId));
549         ASSERT_TRUE(removeOutputPid(frontendConf.removePid));
550         ASSERT_TRUE(unlinkCiCam(frontendConf.ciCamId));
551     }
552     ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
553     verifyFrontendStatus(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
554     ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
555     ASSERT_TRUE(closeFrontend());
556 }
557 
debugInfoTest(FrontendConfig frontendConf)558 void FrontendTests::debugInfoTest(FrontendConfig frontendConf) {
559     int32_t feId;
560     getFrontendIdByType(frontendConf.type, feId);
561     ASSERT_TRUE(feId != INVALID_ID);
562     ASSERT_TRUE(openFrontendById(feId));
563     ASSERT_TRUE(setFrontendCallback());
564     ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
565     ASSERT_TRUE(verifyHardwareInfo());
566     ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
567     ASSERT_TRUE(closeFrontend());
568 }
569 
maxNumberOfFrontendsTest()570 void FrontendTests::maxNumberOfFrontendsTest() {
571     ASSERT_TRUE(getFrontendIds());
572     for (size_t i = 0; i < mFeIds.size(); i++) {
573         ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
574         int32_t defaultMax = -1;
575         ndk::ScopedAStatus status;
576         // Check default value
577         status = mService->getMaxNumberOfFrontends(mFrontendInfo.type, &defaultMax);
578         ASSERT_TRUE(status.isOk());
579         ASSERT_TRUE(defaultMax > 0);
580         // Set to -1
581         status = mService->setMaxNumberOfFrontends(mFrontendInfo.type, -1);
582         ASSERT_TRUE(status.getServiceSpecificError() ==
583                     static_cast<int32_t>(Result::INVALID_ARGUMENT));
584         // Set to defaultMax + 1
585         status = mService->setMaxNumberOfFrontends(mFrontendInfo.type, defaultMax + 1);
586         ASSERT_TRUE(status.getServiceSpecificError() ==
587                     static_cast<int32_t>(Result::INVALID_ARGUMENT));
588         // Set to 0
589         status = mService->setMaxNumberOfFrontends(mFrontendInfo.type, 0);
590         ASSERT_TRUE(status.isOk());
591         // Check after set
592         int32_t currentMax = -1;
593         status = mService->getMaxNumberOfFrontends(mFrontendInfo.type, &currentMax);
594         ASSERT_TRUE(status.isOk());
595         ASSERT_TRUE(currentMax == 0);
596         // Reset to default
597         status = mService->setMaxNumberOfFrontends(mFrontendInfo.type, defaultMax);
598         ASSERT_TRUE(status.isOk());
599         status = mService->getMaxNumberOfFrontends(mFrontendInfo.type, &currentMax);
600         ASSERT_TRUE(status.isOk());
601         ASSERT_TRUE(defaultMax == currentMax);
602     }
603 }
604 
scanTest(FrontendConfig frontendConf,FrontendScanType scanType)605 void FrontendTests::scanTest(FrontendConfig frontendConf, FrontendScanType scanType) {
606     int32_t feId;
607     getFrontendIdByType(frontendConf.type, feId);
608     ASSERT_TRUE(feId != INVALID_ID);
609     ASSERT_TRUE(openFrontendById(feId));
610     ASSERT_TRUE(setFrontendCallback());
611     ASSERT_TRUE(scanFrontend(frontendConf, scanType));
612     ASSERT_TRUE(stopScanFrontend());
613     ASSERT_TRUE(closeFrontend());
614 }
615 
statusReadinessTest(FrontendConfig frontendConf)616 void FrontendTests::statusReadinessTest(FrontendConfig frontendConf) {
617     int32_t feId;
618     vector<FrontendStatusType> allTypes;
619     vector<FrontendStatusReadiness> readiness;
620     getFrontendIdByType(frontendConf.type, feId);
621     ASSERT_TRUE(feId != INVALID_ID);
622     ASSERT_TRUE(openFrontendById(feId));
623     ASSERT_TRUE(setFrontendCallback());
624     if (frontendConf.canConnectToCiCam) {
625         ASSERT_TRUE(linkCiCam(frontendConf.ciCamId));
626         ASSERT_TRUE(removeOutputPid(frontendConf.removePid));
627         ASSERT_TRUE(unlinkCiCam(frontendConf.ciCamId));
628     }
629     ASSERT_TRUE(getFrontendInfo(feId));
630     ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
631 
632     // TODO: find a better way to push all frontend status types
633     for (int32_t i = 0; i <= static_cast<int32_t>(FrontendStatusType::ATSC3_ALL_PLP_INFO); i++) {
634         allTypes.push_back(static_cast<FrontendStatusType>(i));
635     }
636 
637     ndk::ScopedAStatus status = mFrontend->getFrontendStatusReadiness(allTypes, &readiness);
638     ASSERT_TRUE(status.isOk());
639     ASSERT_TRUE(readiness.size() == allTypes.size());
640     for (int32_t i = 0; i < readiness.size(); i++) {
641         int32_t j = 0;
642         while (j < mFrontendInfo.statusCaps.size()) {
643             if (allTypes[i] == mFrontendInfo.statusCaps[j]) {
644                 ASSERT_TRUE(readiness[i] == FrontendStatusReadiness::UNAVAILABLE ||
645                             readiness[i] == FrontendStatusReadiness::UNSTABLE ||
646                             readiness[i] == FrontendStatusReadiness::STABLE);
647                 break;
648             }
649             j++;
650         }
651 
652         if (j >= mFrontendInfo.statusCaps.size()) {
653             ASSERT_TRUE(readiness[i] == FrontendStatusReadiness::UNSUPPORTED);
654         }
655     }
656 
657     ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
658     ASSERT_TRUE(closeFrontend());
659 }
660