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