• 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 <binder/MemoryDealer.h>
18 
19 #include "../../../config/TunerTestingConfigAidlReaderV1_0.h"
20 
21 #include <aidl/android/hardware/tv/tuner/DataFormat.h>
22 #include <aidl/android/hardware/tv/tuner/DemuxAlpFilterType.h>
23 #include <aidl/android/hardware/tv/tuner/DemuxFilterMainType.h>
24 #include <aidl/android/hardware/tv/tuner/DemuxFilterMonitorEventType.h>
25 #include <aidl/android/hardware/tv/tuner/DemuxFilterSettings.h>
26 #include <aidl/android/hardware/tv/tuner/DemuxFilterType.h>
27 #include <aidl/android/hardware/tv/tuner/DemuxIpAddress.h>
28 #include <aidl/android/hardware/tv/tuner/DemuxIpFilterSettings.h>
29 #include <aidl/android/hardware/tv/tuner/DemuxIpFilterType.h>
30 #include <aidl/android/hardware/tv/tuner/DemuxMmtpFilterType.h>
31 #include <aidl/android/hardware/tv/tuner/DemuxRecordScIndexType.h>
32 #include <aidl/android/hardware/tv/tuner/DemuxTsFilterType.h>
33 #include <aidl/android/hardware/tv/tuner/DvrSettings.h>
34 #include <aidl/android/hardware/tv/tuner/DvrType.h>
35 #include <aidl/android/hardware/tv/tuner/FrontendDvbtBandwidth.h>
36 #include <aidl/android/hardware/tv/tuner/FrontendDvbtCoderate.h>
37 #include <aidl/android/hardware/tv/tuner/FrontendDvbtConstellation.h>
38 #include <aidl/android/hardware/tv/tuner/FrontendDvbtGuardInterval.h>
39 #include <aidl/android/hardware/tv/tuner/FrontendDvbtHierarchy.h>
40 #include <aidl/android/hardware/tv/tuner/FrontendDvbtSettings.h>
41 #include <aidl/android/hardware/tv/tuner/FrontendDvbtStandard.h>
42 #include <aidl/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.h>
43 #include <aidl/android/hardware/tv/tuner/FrontendSettings.h>
44 #include <aidl/android/hardware/tv/tuner/FrontendType.h>
45 #include <aidl/android/hardware/tv/tuner/PlaybackSettings.h>
46 #include <aidl/android/hardware/tv/tuner/RecordSettings.h>
47 
48 using namespace std;
49 using namespace aidl::android::hardware::tv::tuner;
50 using namespace android::media::tuner::testing::configuration::V1_0;
51 
52 const int32_t FMQ_SIZE_4M = 0x400000;
53 const int32_t FMQ_SIZE_16M = 0x1000000;
54 
55 #define FILTER_MAIN_TYPE_BIT_COUNT 5
56 #define STATUS_CHECK_INTERVAL_MS 100L
57 
58 // Hardware configs
59 static map<string, FrontendConfig> frontendMap;
60 static map<string, FilterConfig> filterMap;
61 static map<string, DvrConfig> dvrMap;
62 static map<string, LnbConfig> lnbMap;
63 static map<string, TimeFilterConfig> timeFilterMap;
64 static map<string, vector<uint8_t>> diseqcMsgMap;
65 static map<string, DescramblerConfig> descramblerMap;
66 
67 // Hardware and test cases connections
68 static LiveBroadcastHardwareConnections live;
69 static ScanHardwareConnections scan;
70 static DvrPlaybackHardwareConnections playback;
71 static DvrRecordHardwareConnections record;
72 static DescramblingHardwareConnections descrambling;
73 static LnbLiveHardwareConnections lnbLive;
74 static LnbRecordHardwareConnections lnbRecord;
75 static TimeFilterHardwareConnections timeFilter;
76 static LnbDescramblingHardwareConnections lnbDescrambling;
77 
78 /*
79  * This function takes in a 2d vector of device Id's
80  * The n vectors correlate to the ids for n different devices (eg frontends, filters)
81  * The resultant 2d vector is every combination of id's with 1 id from each vector
82  */
generateIdCombinations(vector<vector<string>> & ids)83 inline vector<vector<string>> generateIdCombinations(vector<vector<string>>& ids) {
84     vector<vector<string>> combinations;
85 
86     // The index of each vector in ids that will be used in the next combination
87     // EG {0, 2} means combo {ids[0][0] ids[1][2]} will be next
88     const int size = static_cast<int>(ids.size());
89     vector<int> indexes_used_in_combination(size, 0);
90 
91     // The vector number from ids whose elements we will cycle through to make combinations.
92     // First, start at the right most vector
93     int cycled_vector = size - 1;
94 
95     while (cycled_vector >= 0) {
96         // Make a combination (one at a time)
97         vector<string> combo;
98         for (size_t i = 0; i < indexes_used_in_combination.size(); ++i) {
99             const int combo_index = indexes_used_in_combination[i];
100             combo.push_back(ids[i][combo_index]);
101         }
102         combinations.push_back(combo);
103 
104         // Find the right most vector that still has space [elements left] to cycle through and
105         // create a combination
106         while (cycled_vector >= 0 &&
107                indexes_used_in_combination[cycled_vector] == ids[cycled_vector].size() - 1) {
108             cycled_vector--;
109         }
110 
111         // Use this check to avoid segmentation faults
112         if (cycled_vector >= 0) {
113             // Once found, we have a vector we can cycle through, so increase to its next element
114             indexes_used_in_combination[cycled_vector]++;
115 
116             // Reset the other vectors to the right to their first element so we can cycle through
117             // them again with the new element from cycled vector
118             for (size_t i = cycled_vector + 1; i < indexes_used_in_combination.size(); ++i) {
119                 indexes_used_in_combination[i] = 0;
120             }
121 
122             // all the vectors to the right were reset, so we can cycle through them again
123             // Start at the furthest right vector
124             cycled_vector = size - 1;
125         }
126     }
127 
128     return combinations;
129 }
130 
131 /*
132  * index 0 - playback dvr
133  * index 1 - audio filters
134  * index 2 - optional section filters
135  */
generatePlaybackCombinations()136 static inline vector<DvrPlaybackHardwareConnections> generatePlaybackCombinations() {
137     vector<DvrPlaybackHardwareConnections> combinations;
138     vector<string> sectionFilterIds_optional = sectionFilterIds;
139     sectionFilterIds_optional.push_back(emptyHardwareId);
140     vector<vector<string>> deviceIds{playbackDvrIds, audioFilterIds, sectionFilterIds_optional};
141 
142     const int dvrIndex = 0;
143     const int audioFilterIndex = 1;
144     const int sectionFilterIndex = 2;
145 
146     auto idCombinations = generateIdCombinations(deviceIds);
147     for (auto& combo : idCombinations) {
148         DvrPlaybackHardwareConnections mPlayback;
149         mPlayback.dvrId = combo[dvrIndex];
150         mPlayback.audioFilterId = combo[audioFilterIndex];
151         mPlayback.sectionFilterId = combo[sectionFilterIndex];
152         const int videoFilterIndex =
153                 find(audioFilterIds.begin(), audioFilterIds.end(), mPlayback.audioFilterId) -
154                 audioFilterIds.begin();
155         mPlayback.videoFilterId = videoFilterIds[videoFilterIndex];
156         combinations.push_back(mPlayback);
157     }
158 
159     return combinations;
160 }
161 
generatePlaybackConfigs()162 static inline vector<DvrPlaybackHardwareConnections> generatePlaybackConfigs() {
163     vector<DvrPlaybackHardwareConnections> playback_configs;
164     if (configuredPlayback) {
165         ALOGD("Using DVR playback configuration provided.");
166         playback_configs = {playback};
167     } else {
168         ALOGD("Dvr playback not provided. Generating possible combinations. Consider adding it to "
169               "the configuration file.");
170         playback_configs = generatePlaybackCombinations();
171     }
172 
173     return playback_configs;
174 }
175 
176 /*
177  * index 0 - frontends
178  * index 1 - audio filters
179  * index 2 - lnbs
180  */
generateLnbLiveCombinations()181 static inline vector<LnbLiveHardwareConnections> generateLnbLiveCombinations() {
182     vector<LnbLiveHardwareConnections> combinations;
183     vector<vector<string>> deviceIds{frontendIds, audioFilterIds, lnbIds};
184 
185     const int frontendIndex = 0;
186     const int audioFilterIndex = 1;
187     const int lnbIndex = 2;
188 
189     // TODO: Find a better way to vary diseqcMsgs, if at all
190     auto idCombinations = generateIdCombinations(deviceIds);
191     for (auto& combo : idCombinations) {
192         const string feId = combo[frontendIndex];
193         auto type = frontendMap[feId].type;
194         if (type == FrontendType::DVBS || type == FrontendType::ISDBS ||
195             type == FrontendType::ISDBS3) {
196             LnbLiveHardwareConnections mLnbLive;
197             mLnbLive.frontendId = feId;
198             mLnbLive.audioFilterId = combo[audioFilterIndex];
199             const int videoFilterIndex =
200                     find(audioFilterIds.begin(), audioFilterIds.end(), mLnbLive.audioFilterId) -
201                     audioFilterIds.begin();
202             mLnbLive.videoFilterId = videoFilterIds[videoFilterIndex];
203             mLnbLive.lnbId = combo[lnbIndex];
204             mLnbLive.diseqcMsgs = diseqcMsgs;
205             combinations.push_back(mLnbLive);
206         }
207     }
208 
209     return combinations;
210 }
211 
generateLnbLiveConfigurations()212 static inline vector<LnbLiveHardwareConnections> generateLnbLiveConfigurations() {
213     vector<LnbLiveHardwareConnections> lnbLive_configs;
214     if (configuredLnbLive) {
215         ALOGD("Using LnbLive configuration provided.");
216         lnbLive_configs = {lnbLive};
217     } else {
218         ALOGD("LnbLive not provided. Generating possible combinations. Consider adding it to the "
219               "configuration file.");
220         lnbLive_configs = generateLnbLiveCombinations();
221     }
222 
223     return lnbLive_configs;
224 }
225 
generateScanCombinations()226 static inline vector<ScanHardwareConnections> generateScanCombinations() {
227     vector<ScanHardwareConnections> combinations;
228 
229     for (auto& id : frontendIds) {
230         ScanHardwareConnections mScan;
231         mScan.frontendId = id;
232         combinations.push_back(mScan);
233     }
234 
235     return combinations;
236 }
237 
generateScanConfigurations()238 static inline vector<ScanHardwareConnections> generateScanConfigurations() {
239     vector<ScanHardwareConnections> scan_configs;
240     if (configuredScan) {
241         ALOGD("Using scan configuration provided.");
242         scan_configs = {scan};
243     } else {
244         ALOGD("Scan not provided. Generating possible combinations. Consider adding it to "
245               "the configuration file.");
246         scan_configs = generateScanCombinations();
247     }
248 
249     return scan_configs;
250 }
251 
252 /*
253  * index 0 - frontends
254  * index 1 - record filter
255  * index 2 - Record Dvr
256  * index 3 - Lnb
257  */
generateLnbRecordCombinations()258 static inline vector<LnbRecordHardwareConnections> generateLnbRecordCombinations() {
259     vector<LnbRecordHardwareConnections> combinations;
260     vector<vector<string>> deviceIds{frontendIds, recordFilterIds, recordDvrIds, lnbIds};
261 
262     const int frontendIndex = 0;
263     const int recordFilterIndex = 1;
264     const int dvrIndex = 2;
265     const int lnbIndex = 3;
266 
267     auto idCombinations = generateIdCombinations(deviceIds);
268     // TODO : Find a better way to vary diseqcMsgs, if at all
269     for (auto& combo : idCombinations) {
270         const string feId = combo[frontendIndex];
271         auto type = frontendMap[feId].type;
272         if (type == FrontendType::DVBS || type == FrontendType::ISDBS ||
273             type == FrontendType::ISDBS3) {
274             LnbRecordHardwareConnections mLnbRecord;
275             mLnbRecord.frontendId = feId;
276             mLnbRecord.recordFilterId = combo[recordFilterIndex];
277             mLnbRecord.dvrRecordId = combo[dvrIndex];
278             mLnbRecord.lnbId = combo[lnbIndex];
279             mLnbRecord.diseqcMsgs = diseqcMsgs;
280             combinations.push_back(mLnbRecord);
281         }
282     }
283 
284     return combinations;
285 }
286 
generateLnbRecordConfigurations()287 static inline vector<LnbRecordHardwareConnections> generateLnbRecordConfigurations() {
288     vector<LnbRecordHardwareConnections> lnbRecord_configs;
289     if (configuredLnbRecord) {
290         ALOGD("Using LnbRecord configuration provided.");
291         lnbRecord_configs = {lnbRecord};
292     } else {
293         ALOGD("LnbRecord not provided. Generating possible combinations. Consider adding it to "
294               "the configuration file.");
295         lnbRecord_configs = generateLnbRecordCombinations();
296     }
297 
298     return lnbRecord_configs;
299 }
300 
301 /*
302  * index 0 - decramblers
303  * index 1 - frontends
304  * index 2 - audio filters
305  * index 3 - Dvr SW Fe Connections
306  * index 4 - DVR Source Connections
307  */
generateDescramblingCombinations()308 static inline vector<DescramblingHardwareConnections> generateDescramblingCombinations() {
309     vector<DescramblingHardwareConnections> combinations;
310     vector<string> mfrontendIds = frontendIds;
311     vector<string> mDvrFeConnectionIds = playbackDvrIds;
312     vector<string> mDvrSourceConnectionIds = playbackDvrIds;
313 
314     // Add the empty hardware id to each vector to include combinations where these 3 fields might
315     // be optional
316     mfrontendIds.push_back(emptyHardwareId);
317     mDvrFeConnectionIds.push_back(emptyHardwareId);
318     mDvrSourceConnectionIds.push_back(emptyHardwareId);
319 
320     const int descramblerIndex = 0;
321     const int frontendIndex = 1;
322     const int audioFilterIndex = 2;
323     const int dvrFeIdIndex = 3;
324     const int dvrSourceIdIndex = 4;
325 
326     vector<vector<string>> deviceIds{descramblerIds, mfrontendIds, audioFilterIds,
327                                      mDvrFeConnectionIds, mDvrSourceConnectionIds};
328     auto idCombinations = generateIdCombinations(deviceIds);
329     for (auto& combo : idCombinations) {
330         DescramblingHardwareConnections mDescrambling;
331         const string feId = combo[frontendIndex];
332         const string dvrSwFeId = combo[dvrFeIdIndex];
333         const string dvrSourceId = combo[dvrSourceIdIndex];
334         mDescrambling.hasFrontendConnection = feId.compare(emptyHardwareId) == 0 ? false : true;
335         if (!mDescrambling.hasFrontendConnection) {
336             if (dvrSourceId.compare(emptyHardwareId) == 0) {
337                 // If combination does not have a frontend or dvr source connection, do not include
338                 // it
339                 continue;
340             }
341         } else {
342             if (frontendMap[feId].isSoftwareFe && dvrSwFeId.compare(emptyHardwareId) == 0) {
343                 // If combination has a software frontend and no dvr->software frontend connection,
344                 // do not include it
345                 continue;
346             }
347         }
348         if (dvrSwFeId.compare(dvrSourceId) == 0) {
349             // If dvr->software frontend connection is the same as dvr source input to tuner, do not
350             // include it.
351             continue;
352         }
353         mDescrambling.frontendId = feId;
354         mDescrambling.audioFilterId = combo[audioFilterIndex];
355         const int videoFilterIndex =
356                 find(audioFilterIds.begin(), audioFilterIds.end(), mDescrambling.audioFilterId) -
357                 audioFilterIds.begin();
358         mDescrambling.videoFilterId = videoFilterIds[videoFilterIndex];
359         mDescrambling.dvrSoftwareFeId = dvrSwFeId;
360         mDescrambling.dvrSourceId = dvrSourceId;
361         mDescrambling.descramblerId = combo[descramblerIndex];
362         combinations.push_back(mDescrambling);
363     }
364 
365     return combinations;
366 }
367 
generateDescramblingConfigurations()368 static inline vector<DescramblingHardwareConnections> generateDescramblingConfigurations() {
369     vector<DescramblingHardwareConnections> descrambling_configs;
370     if (configuredDescrambling) {
371         ALOGD("Using Descrambling configuration provided.");
372         descrambling_configs = {descrambling};
373     } else {
374         ALOGD("Descrambling not provided. Generating possible combinations. Consider adding it to "
375               "the "
376               "configuration file.");
377         descrambling_configs = generateDescramblingCombinations();
378     }
379 
380     return descrambling_configs;
381 }
382 
generateTimeFilterCombinations()383 static inline vector<TimeFilterHardwareConnections> generateTimeFilterCombinations() {
384     vector<TimeFilterHardwareConnections> combinations;
385 
386     for (auto& id : timeFilterIds) {
387         TimeFilterHardwareConnections mTimeFilter;
388         mTimeFilter.timeFilterId = id;
389         combinations.push_back(mTimeFilter);
390     }
391 
392     return combinations;
393 }
394 
generateTimeFilterConfigurations()395 static inline vector<TimeFilterHardwareConnections> generateTimeFilterConfigurations() {
396     vector<TimeFilterHardwareConnections> timeFilter_configs;
397     if (configuredTimeFilter) {
398         ALOGD("Using TimeFilter configuration provided.");
399         timeFilter_configs = {timeFilter};
400     } else {
401         ALOGD("TimeFilter not provided. Generating possible combinations. Consider adding it to "
402               "the "
403               "configuration file.");
404         timeFilter_configs = generateTimeFilterCombinations();
405     }
406 
407     return timeFilter_configs;
408 }
409 
410 /*
411  * index 0 - frontends
412  * index 1 - record dvrs
413  * index 2 - record filters
414  */
generateRecordCombinations()415 static inline vector<DvrRecordHardwareConnections> generateRecordCombinations() {
416     vector<DvrRecordHardwareConnections> combinations;
417 
418     const int frontendIdIndex = 0;
419     const int recordDvrIndex = 1;
420     const int recordFilterIndex = 2;
421 
422     vector<vector<string>> deviceIds{frontendIds, recordDvrIds, recordFilterIds};
423 
424     auto idCombinations = generateIdCombinations(deviceIds);
425     for (auto& combo : idCombinations) {
426         DvrRecordHardwareConnections mRecord;
427         const string feId = combo[frontendIdIndex];
428         mRecord.hasFrontendConnection = true;
429         if (frontendMap[feId].isSoftwareFe) {
430             // If we have a software frontend, do not include configuration for testing.
431             continue;
432         }
433         mRecord.frontendId = feId;
434         mRecord.support = true;
435         mRecord.dvrSourceId = emptyHardwareId;
436         mRecord.dvrSoftwareFeId = emptyHardwareId;
437         mRecord.recordFilterId = combo[recordFilterIndex];
438         mRecord.dvrRecordId = combo[recordDvrIndex];
439         combinations.push_back(mRecord);
440     }
441 
442     return combinations;
443 }
444 
generateRecordConfigurations()445 static inline vector<DvrRecordHardwareConnections> generateRecordConfigurations() {
446     vector<DvrRecordHardwareConnections> record_configs;
447     if (configuredRecord) {
448         ALOGD("Using Record configuration provided.");
449         record_configs = {record};
450     } else {
451         ALOGD("Record not provided. Generating possible combinations. Consider adding it to "
452               "the "
453               "configuration file.");
454         record_configs = generateRecordCombinations();
455     }
456 
457     return record_configs;
458 }
459 
460 /*
461  * index 0 - frontends
462  * index 1 - audio filters
463  * index 2 - playback dvrs
464  * index 3 - section Filters
465  */
generateLiveCombinations()466 static inline vector<LiveBroadcastHardwareConnections> generateLiveCombinations() {
467     vector<LiveBroadcastHardwareConnections> combinations;
468     vector<string> mSectionFilterIds = sectionFilterIds;
469     vector<string> mDvrSwConnectionIds = playbackDvrIds;
470 
471     // Adding the empty hardware id to cover cases where fields are optional
472     mSectionFilterIds.push_back(emptyHardwareId);
473     mDvrSwConnectionIds.push_back(emptyHardwareId);
474 
475     const int frontendIdIndex = 0;
476     const int audioFilterIdIndex = 1;
477     const int dvrSwConnectionIdIndex = 2;
478     const int sectionFilterIdIndex = 3;
479 
480     vector<vector<string>> deviceIds{frontendIds, audioFilterIds, mDvrSwConnectionIds,
481                                      mSectionFilterIds};
482 
483     auto idCombinations = generateIdCombinations(deviceIds);
484     for (auto& combo : idCombinations) {
485         LiveBroadcastHardwareConnections mLive;
486         const string feId = combo[frontendIdIndex];
487         const string dvrSwConnectionId = combo[dvrSwConnectionIdIndex];
488         mLive.hasFrontendConnection = true;
489 
490         if (frontendMap[feId].isSoftwareFe && dvrSwConnectionId.compare(emptyHardwareId) == 0) {
491             // If the frontend is a software frontend and there is no dvr playback connected, do not
492             // include configuration
493             continue;
494         }
495         mLive.frontendId = feId;
496         mLive.dvrSoftwareFeId = dvrSwConnectionId;
497         mLive.audioFilterId = combo[audioFilterIdIndex];
498         const int videoFilterIdIndex =
499                 find(audioFilterIds.begin(), audioFilterIds.end(), mLive.audioFilterId) -
500                 audioFilterIds.begin();
501         mLive.videoFilterId = videoFilterIds[videoFilterIdIndex];
502         mLive.sectionFilterId = combo[sectionFilterIdIndex];
503 
504         if (pcrFilterIds.empty()) {
505             // If pcr Filters have not been provided, set it to empty hardware id
506             mLive.pcrFilterId = emptyHardwareId;
507         } else {
508             // If pcr Filters have been provided, use the first index if there is only 1, or choose
509             // the filter that corresponds to the correct audio and video filter pair
510             const int pcrFilterIdIndex = pcrFilterIds.size() == 1 ? 0 : videoFilterIdIndex;
511             mLive.pcrFilterId = pcrFilterIds[pcrFilterIdIndex];
512         }
513 
514         combinations.push_back(mLive);
515     }
516 
517     return combinations;
518 }
519 
generateLiveConfigurations()520 static inline vector<LiveBroadcastHardwareConnections> generateLiveConfigurations() {
521     vector<LiveBroadcastHardwareConnections> live_configs;
522     if (configuredLive) {
523         ALOGD("Using Live configuration provided.");
524         live_configs = {live};
525     } else {
526         ALOGD("Live not provided. Generating possible combinations. Consider adding it to "
527               "the "
528               "configuration file.");
529         live_configs = generateLiveCombinations();
530     }
531 
532     return live_configs;
533 }
534 
generateLnbDescramblingCombinations()535 static inline vector<LnbDescramblingHardwareConnections> generateLnbDescramblingCombinations() {
536     vector<LnbDescramblingHardwareConnections> combinations;
537     vector<vector<string>> deviceIds{frontendIds, audioFilterIds, lnbIds, descramblerIds};
538 
539     const int frontendIdIndex = 0;
540     const int audioFilterIdIndex = 1;
541     const int lnbIdIndex = 2;
542     const int descramblerIdIndex = 3;
543 
544     auto idCombinations = generateIdCombinations(deviceIds);
545     // TODO : Find a better way to vary diseqcMsgs, if at all
546     for (auto& combo : idCombinations) {
547         const string feId = combo[frontendIdIndex];
548         auto type = frontendMap[feId].type;
549         if (type == FrontendType::DVBS || type == FrontendType::ISDBS ||
550             type == FrontendType::ISDBS3) {
551             LnbDescramblingHardwareConnections mLnbDescrambling;
552             mLnbDescrambling.support = true;
553             mLnbDescrambling.frontendId = feId;
554             mLnbDescrambling.audioFilterId = combo[audioFilterIdIndex];
555             const int videoFilterIdIndex = find(audioFilterIds.begin(), audioFilterIds.end(),
556                                                 mLnbDescrambling.audioFilterId) -
557                                            audioFilterIds.begin();
558             mLnbDescrambling.videoFilterId = videoFilterIds[videoFilterIdIndex];
559             mLnbDescrambling.lnbId = combo[lnbIdIndex];
560             mLnbDescrambling.descramblerId = combo[descramblerIdIndex];
561             mLnbDescrambling.diseqcMsgs = diseqcMsgs;
562             combinations.push_back(mLnbDescrambling);
563         }
564     }
565 
566     return combinations;
567 }
568 
generateLnbDescramblingConfigurations()569 static inline vector<LnbDescramblingHardwareConnections> generateLnbDescramblingConfigurations() {
570     vector<LnbDescramblingHardwareConnections> lnbDescrambling_configs;
571     if (configuredLnbDescrambling) {
572         ALOGD("Using LnbDescrambling configuration provided");
573         lnbDescrambling_configs = {lnbDescrambling};
574     } else {
575         ALOGD("LnbDescrambling not provided. Generating possible combinations. Consider adding it "
576               "to the configuration file.");
577         lnbDescrambling_configs = generateLnbDescramblingCombinations();
578     }
579 
580     return lnbDescrambling_configs;
581 }
582 
583 /** Config all the frontends that would be used in the tests */
initFrontendConfig()584 inline void initFrontendConfig() {
585     // The test will use the internal default fe when default fe is connected to any data flow
586     // without overriding in the xml config.
587     string defaultFeId = "FE_DEFAULT";
588     FrontendDvbtSettings dvbtSettings{
589             .frequency = 578000000,
590             .transmissionMode = FrontendDvbtTransmissionMode::AUTO,
591             .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
592             .isHighPriority = true,
593     };
594     frontendMap[defaultFeId].type = FrontendType::DVBT;
595     frontendMap[defaultFeId].settings.set<FrontendSettings::Tag::dvbt>(dvbtSettings);
596 
597     vector<FrontendStatusType> types;
598     types.push_back(FrontendStatusType::UEC);
599     types.push_back(FrontendStatusType::IS_MISO);
600 
601     vector<FrontendStatus> statuses;
602     FrontendStatus status;
603     status.set<FrontendStatus::Tag::uec>(4);
604     statuses.push_back(status);
605     status.set<FrontendStatus::Tag::isMiso>(true);
606     statuses.push_back(status);
607 
608     frontendMap[defaultFeId].tuneStatusTypes = types;
609     frontendMap[defaultFeId].expectTuneStatuses = statuses;
610     frontendMap[defaultFeId].isSoftwareFe = true;
611     frontendMap[defaultFeId].canConnectToCiCam = true;
612     frontendMap[defaultFeId].ciCamId = 0;
613     frontendMap[defaultFeId].supportBlindScan = true;
614     FrontendDvbtSettings dvbt;
615     dvbt.transmissionMode = FrontendDvbtTransmissionMode::MODE_8K_E;
616     frontendMap[defaultFeId].settings.set<FrontendSettings::Tag::dvbt>(dvbt);
617     // Read customized config
618     TunerTestingConfigAidlReader1_0::readFrontendConfig1_0(frontendMap);
619 };
620 
initFilterConfig()621 inline void initFilterConfig() {
622     // The test will use the internal default filter when default filter is connected to any
623     // data flow without overriding in the xml config.
624     string defaultAudioFilterId = "FILTER_AUDIO_DEFAULT";
625     string defaultVideoFilterId = "FILTER_VIDEO_DEFAULT";
626 
627     filterMap[defaultVideoFilterId].type.mainType = DemuxFilterMainType::TS;
628     filterMap[defaultVideoFilterId].type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
629             DemuxTsFilterType::VIDEO);
630     filterMap[defaultVideoFilterId].bufferSize = FMQ_SIZE_16M;
631     filterMap[defaultVideoFilterId].settings =
632             DemuxFilterSettings::make<DemuxFilterSettings::Tag::ts>();
633     filterMap[defaultVideoFilterId].settings.get<DemuxFilterSettings::Tag::ts>().tpid = 256;
634     DemuxFilterAvSettings video;
635     video.isPassthrough = false;
636     filterMap[defaultVideoFilterId]
637             .settings.get<DemuxFilterSettings::Tag::ts>()
638             .filterSettings.set<DemuxTsFilterSettingsFilterSettings::Tag::av>(video);
639     filterMap[defaultVideoFilterId].monitorEventTypes =
640             static_cast<int32_t>(DemuxFilterMonitorEventType::SCRAMBLING_STATUS) |
641             static_cast<int32_t>(DemuxFilterMonitorEventType::IP_CID_CHANGE);
642     filterMap[defaultVideoFilterId].streamType.set<AvStreamType::Tag::video>(
643             VideoStreamType::MPEG1);
644 
645     filterMap[defaultAudioFilterId].type.mainType = DemuxFilterMainType::TS;
646     filterMap[defaultAudioFilterId].type.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
647             DemuxTsFilterType::AUDIO);
648     filterMap[defaultAudioFilterId].bufferSize = FMQ_SIZE_16M;
649     filterMap[defaultAudioFilterId].settings =
650             DemuxFilterSettings::make<DemuxFilterSettings::Tag::ts>();
651     filterMap[defaultAudioFilterId].settings.get<DemuxFilterSettings::Tag::ts>().tpid = 256;
652     DemuxFilterAvSettings audio;
653     audio.isPassthrough = false;
654     filterMap[defaultAudioFilterId]
655             .settings.get<DemuxFilterSettings::Tag::ts>()
656             .filterSettings.set<DemuxTsFilterSettingsFilterSettings::Tag::av>(audio);
657     filterMap[defaultAudioFilterId].monitorEventTypes =
658             static_cast<int32_t>(DemuxFilterMonitorEventType::SCRAMBLING_STATUS) |
659             static_cast<int32_t>(DemuxFilterMonitorEventType::IP_CID_CHANGE);
660     filterMap[defaultAudioFilterId].streamType.set<AvStreamType::Tag::audio>(AudioStreamType::MP3);
661     // Read customized config
662     TunerTestingConfigAidlReader1_0::readFilterConfig1_0(filterMap);
663 };
664 
665 /** Config all the dvrs that would be used in the tests */
initDvrConfig()666 inline void initDvrConfig() {
667     // Read customized config
668     TunerTestingConfigAidlReader1_0::readDvrConfig1_0(dvrMap);
669 };
670 
initTimeFilterConfig()671 inline void initTimeFilterConfig() {
672     // Read customized config
673     TunerTestingConfigAidlReader1_0::readTimeFilterConfig1_0(timeFilterMap);
674 };
675 
initDescramblerConfig()676 inline void initDescramblerConfig() {
677     // Read customized config
678     TunerTestingConfigAidlReader1_0::readDescramblerConfig1_0(descramblerMap);
679 }
680 
initLnbConfig()681 inline void initLnbConfig() {
682     // Read customized config
683     TunerTestingConfigAidlReader1_0::readLnbConfig1_0(lnbMap);
684 };
685 
initDiseqcMsgsConfig()686 inline void initDiseqcMsgsConfig() {
687     // Read customized config
688     TunerTestingConfigAidlReader1_0::readDiseqcMessages(diseqcMsgMap);
689 };
690 
determineScan()691 inline void determineScan() {
692     if (!frontendMap.empty()) {
693         scan.hasFrontendConnection = true;
694         ALOGD("Can support scan");
695     }
696 }
697 
determineTimeFilter()698 inline void determineTimeFilter() {
699     if (!timeFilterMap.empty()) {
700         timeFilter.support = true;
701         ALOGD("Can support time filter");
702     }
703 }
704 
determineDvrPlayback()705 inline void determineDvrPlayback() {
706     if (!playbackDvrIds.empty() && !audioFilterIds.empty() && !videoFilterIds.empty()) {
707         playback.support = true;
708         ALOGD("Can support dvr playback");
709     }
710 }
711 
determineLnbLive()712 inline void determineLnbLive() {
713     if (!audioFilterIds.empty() && !videoFilterIds.empty() && !frontendMap.empty() &&
714         !lnbMap.empty()) {
715         lnbLive.support = true;
716         ALOGD("Can support lnb live");
717     }
718 }
719 
determineLnbRecord()720 inline void determineLnbRecord() {
721     if (!frontendMap.empty() && !recordFilterIds.empty() && !recordDvrIds.empty() &&
722         !lnbMap.empty()) {
723         lnbRecord.support = true;
724         ALOGD("Can support lnb record");
725     }
726 }
727 
determineLive()728 inline void determineLive() {
729     if (videoFilterIds.empty() || audioFilterIds.empty() || frontendMap.empty()) {
730         return;
731     }
732     if (!hasHwFe) {
733         if (hasSwFe) {
734             if (dvrMap.empty()) {
735                 ALOGD("Cannot configure Live. Only software frontends and no dvr connections.");
736                 return;
737             }
738             // Live is available if there is SW FE and some DVR is attached.
739         } else {
740             // We will arrive here because frontendMap won't be empty since
741             // there will be at least a default frontend declared. But the
742             // default frontend doesn't count as "hasSwFe".
743             ALOGD("Cannot configure Live. No frontend declared at all.");
744             return;
745         }
746     }
747     ALOGD("Can support live");
748     live.hasFrontendConnection = true;
749 }
750 
determineDescrambling()751 inline void determineDescrambling() {
752     if (descramblerMap.empty() || audioFilterIds.empty() || videoFilterIds.empty()) {
753         return;
754     }
755     if (frontendMap.empty() && playbackDvrIds.empty()) {
756         ALOGD("Cannot configure descrambling. No frontends or playback dvr's");
757         return;
758     }
759     if (hasSwFe && !hasHwFe && playbackDvrIds.empty()) {
760         ALOGD("cannot configure descrambling. Only SW frontends and no playback dvr's");
761         return;
762     }
763     ALOGD("Can support descrambling");
764     descrambling.support = true;
765 }
766 
determineDvrRecord()767 inline void determineDvrRecord() {
768     if (recordDvrIds.empty() || recordFilterIds.empty()) {
769         return;
770     }
771     if (frontendMap.empty() && playbackDvrIds.empty()) {
772         ALOGD("Cannot support dvr record. No frontends and no playback dvr's");
773         return;
774     }
775     if (hasSwFe && !hasHwFe && playbackDvrIds.empty()) {
776         ALOGD("Cannot support dvr record. Only SW frontends and no playback dvr's");
777         return;
778     }
779     ALOGD("Can support dvr record.");
780     record.support = true;
781 }
782 
determineLnbDescrambling()783 inline void determineLnbDescrambling() {
784     if (frontendIds.empty() || audioFilterIds.empty() || videoFilterIds.empty() || lnbIds.empty() ||
785         descramblerIds.empty()) {
786         return;
787     }
788     ALOGD("Can support LnbDescrambling.");
789     lnbDescrambling.support = true;
790 }
791 
792 /** Read the vendor configurations of which hardware to use for each test cases/data flows */
connectHardwaresToTestCases()793 inline void connectHardwaresToTestCases() {
794     TunerTestingConfigAidlReader1_0::connectLiveBroadcast(live);
795     TunerTestingConfigAidlReader1_0::connectScan(scan);
796     TunerTestingConfigAidlReader1_0::connectDvrRecord(record);
797     TunerTestingConfigAidlReader1_0::connectTimeFilter(timeFilter);
798     TunerTestingConfigAidlReader1_0::connectDescrambling(descrambling);
799     TunerTestingConfigAidlReader1_0::connectLnbLive(lnbLive);
800     TunerTestingConfigAidlReader1_0::connectLnbRecord(lnbRecord);
801     TunerTestingConfigAidlReader1_0::connectDvrPlayback(playback);
802     TunerTestingConfigAidlReader1_0::connectLnbDescrambling(lnbDescrambling);
803 };
804 
determineDataFlows()805 inline void determineDataFlows() {
806     determineScan();
807     determineTimeFilter();
808     determineDvrPlayback();
809     determineLnbLive();
810     determineLnbRecord();
811     determineLive();
812     determineDescrambling();
813     determineDvrRecord();
814     determineLnbDescrambling();
815 }
816 
validateConnections()817 inline bool validateConnections() {
818     if (record.support && !record.hasFrontendConnection &&
819         record.dvrSourceId.compare(emptyHardwareId) == 0) {
820         ALOGW("[vts config] Record must support either a DVR source or a Frontend source.");
821         return false;
822     }
823     bool feIsValid = live.hasFrontendConnection
824                              ? frontendMap.find(live.frontendId) != frontendMap.end()
825                              : true;
826     feIsValid &= scan.hasFrontendConnection ? frontendMap.find(scan.frontendId) != frontendMap.end()
827                                             : true;
828     feIsValid &= record.support && record.hasFrontendConnection
829                          ? frontendMap.find(record.frontendId) != frontendMap.end()
830                          : true;
831     feIsValid &= descrambling.support && descrambling.hasFrontendConnection
832                          ? frontendMap.find(descrambling.frontendId) != frontendMap.end()
833                          : true;
834 
835     feIsValid &= lnbLive.support ? frontendMap.find(lnbLive.frontendId) != frontendMap.end() : true;
836 
837     feIsValid &=
838             lnbRecord.support ? frontendMap.find(lnbRecord.frontendId) != frontendMap.end() : true;
839 
840     feIsValid &= lnbDescrambling.support
841                          ? frontendMap.find(lnbDescrambling.frontendId) != frontendMap.end()
842                          : true;
843 
844     if (!feIsValid) {
845         ALOGW("[vts config] dynamic config fe connection is invalid.");
846         return false;
847     }
848 
849     bool dvrIsValid = frontendMap[live.frontendId].isSoftwareFe
850                               ? dvrMap.find(live.dvrSoftwareFeId) != dvrMap.end()
851                               : true;
852 
853     if (record.support) {
854         if (record.hasFrontendConnection) {
855             if (frontendMap[record.frontendId].isSoftwareFe) {
856                 dvrIsValid &= dvrMap.find(record.dvrSoftwareFeId) != dvrMap.end();
857             }
858         } else {
859             dvrIsValid &= dvrMap.find(record.dvrSourceId) != dvrMap.end();
860         }
861         dvrIsValid &= dvrMap.find(record.dvrRecordId) != dvrMap.end();
862     }
863 
864     if (descrambling.support) {
865         if (descrambling.hasFrontendConnection) {
866             if (frontendMap[descrambling.frontendId].isSoftwareFe) {
867                 dvrIsValid &= dvrMap.find(descrambling.dvrSoftwareFeId) != dvrMap.end();
868             }
869         } else {
870             dvrIsValid &= dvrMap.find(descrambling.dvrSourceId) != dvrMap.end();
871         }
872     }
873 
874     dvrIsValid &= lnbRecord.support ? dvrMap.find(lnbRecord.dvrRecordId) != dvrMap.end() : true;
875 
876     dvrIsValid &= playback.support ? dvrMap.find(playback.dvrId) != dvrMap.end() : true;
877 
878     if (!dvrIsValid) {
879         ALOGW("[vts config] dynamic config dvr connection is invalid.");
880         return false;
881     }
882 
883     bool filterIsValid = (live.hasFrontendConnection)
884                              ? filterMap.find(live.audioFilterId) != filterMap.end() &&
885                                filterMap.find(live.videoFilterId) != filterMap.end()
886                              : true;
887     filterIsValid &=
888             record.support ? filterMap.find(record.recordFilterId) != filterMap.end() : true;
889 
890     filterIsValid &= descrambling.support
891                              ? filterMap.find(descrambling.videoFilterId) != filterMap.end() &&
892                                        filterMap.find(descrambling.audioFilterId) != filterMap.end()
893                              : true;
894 
895     for (auto& filterId : descrambling.extraFilters) {
896         filterIsValid &= filterMap.find(filterId) != filterMap.end();
897     }
898 
899     filterIsValid &= lnbLive.support
900                              ? filterMap.find(lnbLive.audioFilterId) != filterMap.end() &&
901                                        filterMap.find(lnbLive.videoFilterId) != filterMap.end()
902                              : true;
903 
904     filterIsValid &=
905             lnbRecord.support ? filterMap.find(lnbRecord.recordFilterId) != filterMap.end() : true;
906 
907     for (auto& filterId : lnbRecord.extraFilters) {
908         filterIsValid &= filterMap.find(filterId) != filterMap.end();
909     }
910 
911     for (auto& filterId : lnbLive.extraFilters) {
912         filterIsValid &= filterMap.find(filterId) != filterMap.end();
913     }
914 
915     filterIsValid &= playback.support
916                              ? filterMap.find(playback.audioFilterId) != filterMap.end() &&
917                                        filterMap.find(playback.videoFilterId) != filterMap.end()
918                              : true;
919     filterIsValid &= playback.sectionFilterId.compare(emptyHardwareId) == 0
920                              ? true
921                              : filterMap.find(playback.sectionFilterId) != filterMap.end();
922 
923     for (auto& filterId : playback.extraFilters) {
924         filterIsValid &=
925                 playback.hasExtraFilters ? filterMap.find(filterId) != filterMap.end() : true;
926     }
927 
928     filterIsValid &=
929             lnbDescrambling.support
930                     ? filterMap.find(lnbDescrambling.audioFilterId) != filterMap.end() &&
931                               filterMap.find(lnbDescrambling.videoFilterId) != filterMap.end()
932                     : true;
933 
934     if (!filterIsValid) {
935         ALOGW("[vts config] dynamic config filter connection is invalid.");
936         return false;
937     }
938 
939     if (audioFilterIds.size() != videoFilterIds.size()) {
940         ALOGW("[vts config] the number of audio and video filters should be equal");
941         return false;
942     }
943 
944     if (!pcrFilterIds.empty() && pcrFilterIds.size() != 1 &&
945         pcrFilterIds.size() != audioFilterIds.size()) {
946         ALOGW("[vts config] When more than 1 pcr filter is configured, the number of pcr filters "
947               "must equal the number of audio and video filters.");
948         return false;
949     }
950 
951     bool timeFilterIsValid =
952             timeFilter.support ? timeFilterMap.find(timeFilter.timeFilterId) != timeFilterMap.end()
953                                : true;
954 
955     if (!timeFilterIsValid) {
956         ALOGW("[vts config] dynamic config time filter connection is invalid.");
957     }
958 
959     bool descramblerIsValid =
960             descrambling.support
961                     ? descramblerMap.find(descrambling.descramblerId) != descramblerMap.end()
962                     : true;
963 
964     descramblerIsValid &=
965             lnbDescrambling.support
966                     ? descramblerMap.find(lnbDescrambling.descramblerId) != descramblerMap.end()
967                     : true;
968 
969     if (!descramblerIsValid) {
970         ALOGW("[vts config] dynamic config descrambler connection is invalid.");
971         return false;
972     }
973 
974     bool lnbIsValid = lnbLive.support ? lnbMap.find(lnbLive.lnbId) != lnbMap.end() : true;
975 
976     lnbIsValid &= lnbRecord.support ? lnbMap.find(lnbRecord.lnbId) != lnbMap.end() : true;
977 
978     lnbIsValid &=
979             lnbDescrambling.support ? lnbMap.find(lnbDescrambling.lnbId) != lnbMap.end() : true;
980 
981     if (!lnbIsValid) {
982         ALOGW("[vts config] dynamic config lnb connection is invalid.");
983         return false;
984     }
985 
986     bool diseqcMsgsIsValid = true;
987 
988     for (auto& msg : lnbRecord.diseqcMsgs) {
989         diseqcMsgsIsValid &= diseqcMsgMap.find(msg) != diseqcMsgMap.end();
990     }
991 
992     for (auto& msg : lnbLive.diseqcMsgs) {
993         diseqcMsgsIsValid &= diseqcMsgMap.find(msg) != diseqcMsgMap.end();
994     }
995 
996     for (auto& msg : lnbDescrambling.diseqcMsgs) {
997         diseqcMsgsIsValid &= diseqcMsgMap.find(msg) != diseqcMsgMap.end();
998     }
999 
1000     if (!diseqcMsgsIsValid) {
1001         ALOGW("[vts config] dynamic config diseqcMsg is invalid.");
1002         return false;
1003     }
1004 
1005     return true;
1006 }
1007