1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <android/hardware/tv/tuner/1.0/types.h>
18 #include <binder/MemoryDealer.h>
19 #include <hidl/HidlSupport.h>
20 #include <hidl/HidlTransportSupport.h>
21 #include <hidl/Status.h>
22 #include <hidlmemory/FrameworkUtils.h>
23 
24 #include "../../../config/TunerTestingConfigReaderV1_0.h"
25 
26 using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
27 using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
28 using android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth;
29 using android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
30 using android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
31 using android::hardware::tv::tuner::V1_0::FrontendSettings;
32 using android::hardware::tv::tuner::V1_0::FrontendStatus;
33 using android::hardware::tv::tuner::V1_0::FrontendStatusType;
34 using android::hardware::tv::tuner::V1_0::FrontendType;
35 
36 using namespace std;
37 using namespace android::media::tuner::testing::configuration::V1_0;
38 
39 const uint32_t FMQ_SIZE_4M = 0x400000;
40 const uint32_t FMQ_SIZE_16M = 0x1000000;
41 
42 const string configFilePath = "/vendor/etc/tuner_vts_config_1_0.xml";
43 
44 #define FILTER_MAIN_TYPE_BIT_COUNT 5
45 
46 // Hardware configs
47 static map<string, FrontendConfig> frontendMap;
48 static map<string, FilterConfig> filterMap;
49 static map<string, DvrConfig> dvrMap;
50 static map<string, LnbConfig> lnbMap;
51 static map<string, TimeFilterConfig> timeFilterMap;
52 static map<string, vector<uint8_t>> diseqcMsgMap;
53 static map<string, DescramblerConfig> descramblerMap;
54 
55 // Hardware and test cases connections
56 static LiveBroadcastHardwareConnections live;
57 static ScanHardwareConnections scan;
58 static DvrPlaybackHardwareConnections playback;
59 static DvrRecordHardwareConnections record;
60 static DescramblingHardwareConnections descrambling;
61 static LnbLiveHardwareConnections lnbLive;
62 static LnbRecordHardwareConnections lnbRecord;
63 static TimeFilterHardwareConnections timeFilter;
64 
65 /** Config all the frontends that would be used in the tests */
initFrontendConfig()66 inline void initFrontendConfig() {
67     // The test will use the internal default fe when default fe is connected to any data flow
68     // without overriding in the xml config.
69     string defaultFeId = "FE_DEFAULT";
70     FrontendDvbtSettings dvbtSettings{
71             .frequency = 578000000,
72             .transmissionMode = FrontendDvbtTransmissionMode::AUTO,
73             .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
74             .isHighPriority = true,
75     };
76     frontendMap[defaultFeId].type = FrontendType::DVBT;
77     frontendMap[defaultFeId].settings.dvbt(dvbtSettings);
78 
79     vector<FrontendStatusType> types;
80     types.push_back(FrontendStatusType::DEMOD_LOCK);
81     FrontendStatus status;
82     status.isDemodLocked(true);
83     vector<FrontendStatus> statuses;
84     statuses.push_back(status);
85     frontendMap[defaultFeId].tuneStatusTypes = types;
86     frontendMap[defaultFeId].expectTuneStatuses = statuses;
87     frontendMap[defaultFeId].isSoftwareFe = true;
88 
89     // Read customized config
90     TunerTestingConfigReader1_0::readFrontendConfig1_0(frontendMap);
91 };
92 
initFilterConfig()93 inline void initFilterConfig() {
94     // The test will use the internal default filter when default filter is connected to any
95     // data flow without overriding in the xml config.
96     string defaultAudioFilterId = "FILTER_AUDIO_DEFAULT";
97     string defaultVideoFilterId = "FILTER_VIDEO_DEFAULT";
98 
99     filterMap[defaultVideoFilterId].type.mainType = DemuxFilterMainType::TS;
100     filterMap[defaultVideoFilterId].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
101     filterMap[defaultVideoFilterId].bufferSize = FMQ_SIZE_16M;
102     filterMap[defaultVideoFilterId].settings.ts().tpid = 256;
103     filterMap[defaultVideoFilterId].settings.ts().filterSettings.av({.isPassthrough = false});
104 
105     filterMap[defaultAudioFilterId].type.mainType = DemuxFilterMainType::TS;
106     filterMap[defaultAudioFilterId].type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
107     filterMap[defaultAudioFilterId].bufferSize = FMQ_SIZE_16M;
108     filterMap[defaultAudioFilterId].settings.ts().tpid = 256;
109     filterMap[defaultAudioFilterId].settings.ts().filterSettings.av({.isPassthrough = false});
110 
111     // Read customized config
112     TunerTestingConfigReader1_0::readFilterConfig1_0(filterMap);
113 };
114 
115 /** Config all the dvrs that would be used in the tests */
initDvrConfig()116 inline void initDvrConfig() {
117     // Read customized config
118     TunerTestingConfigReader1_0::readDvrConfig1_0(dvrMap);
119 };
120 
121 /** Config all the lnbs that would be used in the tests */
initLnbConfig()122 inline void initLnbConfig() {
123     // Read customized config
124     TunerTestingConfigReader1_0::readLnbConfig1_0(lnbMap);
125     TunerTestingConfigReader1_0::readDiseqcMessages(diseqcMsgMap);
126 };
127 
128 /** Config all the time filters that would be used in the tests */
initTimeFilterConfig()129 inline void initTimeFilterConfig() {
130     // Read customized config
131     TunerTestingConfigReader1_0::readTimeFilterConfig1_0(timeFilterMap);
132 };
133 
134 /** Config all the descramblers that would be used in the tests */
initDescramblerConfig()135 inline void initDescramblerConfig() {
136     // Read customized config
137     TunerTestingConfigReader1_0::readDescramblerConfig1_0(descramblerMap);
138 };
139 
140 /** Read the vendor configurations of which hardware to use for each test cases/data flows */
connectHardwaresToTestCases()141 inline void connectHardwaresToTestCases() {
142     TunerTestingConfigReader1_0::connectLiveBroadcast(live);
143     TunerTestingConfigReader1_0::connectScan(scan);
144     TunerTestingConfigReader1_0::connectDvrPlayback(playback);
145     TunerTestingConfigReader1_0::connectDvrRecord(record);
146     TunerTestingConfigReader1_0::connectDescrambling(descrambling);
147     TunerTestingConfigReader1_0::connectLnbLive(lnbLive);
148     TunerTestingConfigReader1_0::connectLnbRecord(lnbRecord);
149     TunerTestingConfigReader1_0::connectTimeFilter(timeFilter);
150 };
151 
validateConnections()152 inline bool validateConnections() {
153     if ((!live.hasFrontendConnection || !scan.hasFrontendConnection) && !playback.support) {
154         ALOGW("[vts config] VTS must support either a DVR source or a Frontend source.");
155         return false;
156     }
157 
158     if (record.support && !record.hasFrontendConnection &&
159         record.dvrSourceId.compare(emptyHardwareId) == 0) {
160         ALOGW("[vts config] Record must support either a DVR source or a Frontend source.");
161         return false;
162     }
163 
164     if (descrambling.support && !descrambling.hasFrontendConnection &&
165         descrambling.dvrSourceId.compare(emptyHardwareId) == 0) {
166         ALOGW("[vts config] Descrambling must support either a DVR source or a Frontend source.");
167         return false;
168     }
169 
170     bool feIsValid = live.hasFrontendConnection
171                              ? frontendMap.find(live.frontendId) != frontendMap.end()
172                              : true;
173     feIsValid &= scan.hasFrontendConnection ? frontendMap.find(scan.frontendId) != frontendMap.end()
174                                             : true;
175     feIsValid &= record.support && record.hasFrontendConnection
176                          ? frontendMap.find(record.frontendId) != frontendMap.end()
177                          : true;
178     feIsValid &= (descrambling.support && descrambling.hasFrontendConnection)
179                          ? frontendMap.find(descrambling.frontendId) != frontendMap.end()
180                          : true;
181     feIsValid &= lnbLive.support ? frontendMap.find(lnbLive.frontendId) != frontendMap.end() : true;
182     feIsValid &=
183             lnbRecord.support ? frontendMap.find(lnbRecord.frontendId) != frontendMap.end() : true;
184 
185     if (!feIsValid) {
186         ALOGW("[vts config] dynamic config fe connection is invalid.");
187         return false;
188     }
189 
190     bool dvrIsValid = (live.hasFrontendConnection && frontendMap[live.frontendId].isSoftwareFe)
191                               ? dvrMap.find(live.dvrSoftwareFeId) != dvrMap.end()
192                               : true;
193     dvrIsValid &= playback.support ? dvrMap.find(playback.dvrId) != dvrMap.end() : true;
194     if (record.support) {
195         if (record.hasFrontendConnection) {
196             if (frontendMap[record.frontendId].isSoftwareFe) {
197                 dvrIsValid &= dvrMap.find(record.dvrSoftwareFeId) != dvrMap.end();
198             }
199         } else {
200             dvrIsValid &= dvrMap.find(record.dvrSourceId) != dvrMap.end();
201         }
202         dvrIsValid &= dvrMap.find(record.dvrRecordId) != dvrMap.end();
203     }
204     if (descrambling.support) {
205         if (descrambling.hasFrontendConnection) {
206             if (frontendMap[descrambling.frontendId].isSoftwareFe) {
207                 dvrIsValid &= dvrMap.find(descrambling.dvrSoftwareFeId) != dvrMap.end();
208             }
209         } else {
210             dvrIsValid &= dvrMap.find(descrambling.dvrSourceId) != dvrMap.end();
211         }
212     }
213 
214     if (!dvrIsValid) {
215         ALOGW("[vts config] dynamic config dvr connection is invalid.");
216         return false;
217     }
218 
219     bool filterIsValid = (live.hasFrontendConnection)
220                              ? filterMap.find(live.audioFilterId) != filterMap.end() &&
221                                filterMap.find(live.videoFilterId) != filterMap.end()
222                              : true;
223     filterIsValid &= playback.support
224                              ? (filterMap.find(playback.audioFilterId) != filterMap.end() &&
225                                 filterMap.find(playback.videoFilterId) != filterMap.end())
226                              : true;
227     filterIsValid &=
228             record.support ? filterMap.find(record.recordFilterId) != filterMap.end() : true;
229     filterIsValid &= descrambling.support
230                              ? (filterMap.find(descrambling.audioFilterId) != filterMap.end() &&
231                                 filterMap.find(descrambling.videoFilterId) != filterMap.end())
232                              : true;
233     filterIsValid &= lnbLive.support ? (filterMap.find(lnbLive.audioFilterId) != filterMap.end() &&
234                                         filterMap.find(lnbLive.videoFilterId) != filterMap.end())
235                                      : true;
236     filterIsValid &=
237             lnbRecord.support ? filterMap.find(lnbRecord.recordFilterId) != filterMap.end() : true;
238 
239     if (!filterIsValid) {
240         ALOGW("[vts config] dynamic config filter connection is invalid.");
241         return false;
242     }
243 
244     bool lnbIsValid = lnbLive.support ? lnbMap.find(lnbLive.lnbId) != lnbMap.end() : true;
245     lnbIsValid &= lnbRecord.support ? lnbMap.find(lnbRecord.lnbId) != lnbMap.end() : true;
246 
247     if (!lnbIsValid) {
248         ALOGW("[vts config] dynamic config lnb connection is invalid.");
249         return false;
250     }
251 
252     bool descramblerIsValid =
253             descrambling.support
254                     ? descramblerMap.find(descrambling.descramblerId) != descramblerMap.end()
255                     : true;
256 
257     if (!descramblerIsValid) {
258         ALOGW("[vts config] dynamic config descrambler connection is invalid.");
259         return false;
260     }
261 
262     bool diseqcMsgIsValid = true;
263     if (lnbLive.support) {
264         for (auto msgName : lnbLive.diseqcMsgs) {
265             diseqcMsgIsValid &= diseqcMsgMap.find(msgName) != diseqcMsgMap.end();
266         }
267     }
268     if (lnbRecord.support) {
269         for (auto msgName : lnbRecord.diseqcMsgs) {
270             diseqcMsgIsValid &= diseqcMsgMap.find(msgName) != diseqcMsgMap.end();
271         }
272     }
273 
274     if (!diseqcMsgIsValid) {
275         ALOGW("[vts config] dynamic config diseqcMsg sender is invalid.");
276         return false;
277     }
278 
279     return true;
280 }
281