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