1 /*
2 * Copyright (C) 2019 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 #define LOG_TAG "Tuner_hidl_hal_test"
18
19 #include <VtsHalHidlTargetTestBase.h>
20 #include <VtsHalHidlTargetTestEnvBase.h>
21 #include <android-base/logging.h>
22 #include <android/hardware/tv/tuner/1.0/IDemux.h>
23 #include <android/hardware/tv/tuner/1.0/IDescrambler.h>
24 #include <android/hardware/tv/tuner/1.0/IDvr.h>
25 #include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
26 #include <android/hardware/tv/tuner/1.0/IFilter.h>
27 #include <android/hardware/tv/tuner/1.0/IFilterCallback.h>
28 #include <android/hardware/tv/tuner/1.0/IFrontend.h>
29 #include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
30 #include <android/hardware/tv/tuner/1.0/ITuner.h>
31 #include <android/hardware/tv/tuner/1.0/types.h>
32 #include <binder/MemoryDealer.h>
33 #include <fmq/MessageQueue.h>
34 #include <gtest/gtest.h>
35 #include <hidl/GtestPrinter.h>
36 #include <hidl/HidlSupport.h>
37 #include <hidl/HidlTransportSupport.h>
38 #include <hidl/ServiceManagement.h>
39 #include <hidl/Status.h>
40 #include <hidlmemory/FrameworkUtils.h>
41 #include <utils/Condition.h>
42 #include <utils/Mutex.h>
43 #include <fstream>
44 #include <iostream>
45 #include <map>
46
47 #define WAIT_TIMEOUT 3000000000
48 #define WAIT_TIMEOUT_data_ready 3000000000 * 4
49
50 using android::Condition;
51 using android::IMemory;
52 using android::IMemoryHeap;
53 using android::MemoryDealer;
54 using android::Mutex;
55 using android::sp;
56 using android::hardware::EventFlag;
57 using android::hardware::fromHeap;
58 using android::hardware::hidl_string;
59 using android::hardware::hidl_vec;
60 using android::hardware::HidlMemory;
61 using android::hardware::kSynchronizedReadWrite;
62 using android::hardware::MessageQueue;
63 using android::hardware::MQDescriptorSync;
64 using android::hardware::Return;
65 using android::hardware::Void;
66 using android::hardware::tv::tuner::V1_0::DataFormat;
67 using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
68 using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
69 using android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
70 using android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent;
71 using android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings;
72 using android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent;
73 using android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
74 using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
75 using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
76 using android::hardware::tv::tuner::V1_0::DemuxFilterType;
77 using android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
78 using android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
79 using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
80 using android::hardware::tv::tuner::V1_0::DvrSettings;
81 using android::hardware::tv::tuner::V1_0::DvrType;
82 using android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
83 using android::hardware::tv::tuner::V1_0::FrontendAtscSettings;
84 using android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
85 using android::hardware::tv::tuner::V1_0::FrontendEventType;
86 using android::hardware::tv::tuner::V1_0::FrontendId;
87 using android::hardware::tv::tuner::V1_0::FrontendInnerFec;
88 using android::hardware::tv::tuner::V1_0::FrontendScanMessage;
89 using android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
90 using android::hardware::tv::tuner::V1_0::FrontendSettings;
91 using android::hardware::tv::tuner::V1_0::IDemux;
92 using android::hardware::tv::tuner::V1_0::IDescrambler;
93 using android::hardware::tv::tuner::V1_0::IDvr;
94 using android::hardware::tv::tuner::V1_0::IDvrCallback;
95 using android::hardware::tv::tuner::V1_0::IFilter;
96 using android::hardware::tv::tuner::V1_0::IFilterCallback;
97 using android::hardware::tv::tuner::V1_0::IFrontend;
98 using android::hardware::tv::tuner::V1_0::IFrontendCallback;
99 using android::hardware::tv::tuner::V1_0::ITuner;
100 using android::hardware::tv::tuner::V1_0::PlaybackSettings;
101 using android::hardware::tv::tuner::V1_0::PlaybackStatus;
102 using android::hardware::tv::tuner::V1_0::RecordSettings;
103 using android::hardware::tv::tuner::V1_0::RecordStatus;
104 using android::hardware::tv::tuner::V1_0::Result;
105
106 namespace {
107
108 using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
109 using MQDesc = MQDescriptorSync<uint8_t>;
110
111 const std::vector<uint8_t> goldenDataOutputBuffer{
112 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
113 0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
114 0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
115 0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
116 0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
117 0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
118 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
119 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
120 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
121 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
122 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x2d, 0x20,
123 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x62, 0x61, 0x63, 0x3d,
124 0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
125 0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x65, 0x3d,
126 0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68, 0x65,
127 0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
128 0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e,
129 0x30, 0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20,
130 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72,
131 0x6f, 0x6d, 0x61, 0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69,
132 0x73, 0x3d, 0x31, 0x20, 0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71,
133 0x6d, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31,
134 0x2c, 0x31, 0x31, 0x20, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d,
135 0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66,
136 0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d,
137 0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x68,
138 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x5f,
139 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e, 0x72, 0x3d, 0x30, 0x20,
140 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69, 0x6e, 0x74, 0x65,
141 0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72, 0x61, 0x79,
142 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
143 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
144 0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68,
145 0x74, 0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30,
146 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20,
147 0x73, 0x63, 0x65, 0x6e, 0x65,
148 };
149
150 // const uint16_t FMQ_SIZE_4K = 0x1000;
151 const uint32_t FMQ_SIZE_1M = 0x100000;
152 const uint32_t FMQ_SIZE_16M = 0x1000000;
153
154 struct FilterConf {
155 DemuxFilterType type;
156 DemuxFilterSettings setting;
157 };
158
159 enum FilterEventType : uint8_t {
160 UNDEFINED,
161 SECTION,
162 MEDIA,
163 PES,
164 RECORD,
165 MMTPRECORD,
166 DOWNLOAD,
167 TEMI,
168 };
169
170 struct PlaybackConf {
171 string inputDataFile;
172 PlaybackSettings setting;
173 };
174
175 class FrontendCallback : public IFrontendCallback {
176 public:
onEvent(FrontendEventType frontendEventType)177 virtual Return<void> onEvent(FrontendEventType frontendEventType) override {
178 android::Mutex::Autolock autoLock(mMsgLock);
179 mEventReceived = true;
180 mEventType = frontendEventType;
181 mMsgCondition.signal();
182 return Void();
183 }
184
onScanMessage(FrontendScanMessageType,const FrontendScanMessage &)185 virtual Return<void> onScanMessage(FrontendScanMessageType /* type */,
186 const FrontendScanMessage& /* message */) override {
187 android::Mutex::Autolock autoLock(mMsgLock);
188 mScanMessageReceived = true;
189 mMsgCondition.signal();
190 return Void();
191 };
192
193 void testOnEvent(sp<IFrontend>& frontend, FrontendSettings settings);
194 void testOnDiseqcMessage(sp<IFrontend>& frontend, FrontendSettings settings);
195
196 private:
197 bool mEventReceived = false;
198 bool mDiseqcMessageReceived = false;
199 bool mScanMessageReceived = false;
200 FrontendEventType mEventType;
201 hidl_vec<uint8_t> mEventMessage;
202 android::Mutex mMsgLock;
203 android::Condition mMsgCondition;
204 };
205
testOnEvent(sp<IFrontend> & frontend,FrontendSettings settings)206 void FrontendCallback::testOnEvent(sp<IFrontend>& frontend, FrontendSettings settings) {
207 Result result = frontend->tune(settings);
208
209 EXPECT_TRUE(result == Result::SUCCESS);
210
211 android::Mutex::Autolock autoLock(mMsgLock);
212 while (!mEventReceived) {
213 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
214 EXPECT_TRUE(false) << "event not received within timeout";
215 return;
216 }
217 }
218 }
219
testOnDiseqcMessage(sp<IFrontend> & frontend,FrontendSettings settings)220 void FrontendCallback::testOnDiseqcMessage(sp<IFrontend>& frontend, FrontendSettings settings) {
221 Result result = frontend->tune(settings);
222
223 EXPECT_TRUE(result == Result::SUCCESS);
224
225 android::Mutex::Autolock autoLock(mMsgLock);
226 while (!mDiseqcMessageReceived) {
227 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
228 EXPECT_TRUE(false) << "diseqc message not received within timeout";
229 return;
230 }
231 }
232 }
233
234 class FilterCallback : public IFilterCallback {
235 public:
onFilterEvent(const DemuxFilterEvent & filterEvent)236 virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent) override {
237 android::Mutex::Autolock autoLock(mMsgLock);
238 // Temprarily we treat the first coming back filter data on the matching pid a success
239 // once all of the MQ are cleared, means we got all the expected output
240 mFilterIdToEvent = filterEvent;
241 readFilterEventData();
242 mPidFilterOutputCount++;
243 // mFilterIdToMQ.erase(filterEvent.filterId);
244
245 // startFilterEventThread(filterEvent);
246 mMsgCondition.signal();
247 return Void();
248 }
249
onFilterStatus(const DemuxFilterStatus)250 virtual Return<void> onFilterStatus(const DemuxFilterStatus /*status*/) override {
251 return Void();
252 }
253
setFilterId(uint32_t filterId)254 void setFilterId(uint32_t filterId) { mFilterId = filterId; }
setFilterEventType(FilterEventType type)255 void setFilterEventType(FilterEventType type) { mFilterEventType = type; }
256
257 void testFilterDataOutput();
258
259 void startFilterEventThread(DemuxFilterEvent event);
260 static void* __threadLoopFilter(void* threadArgs);
261 void filterThreadLoop(DemuxFilterEvent& event);
262
263 void updateFilterMQ(MQDesc& filterMQDescriptor);
264 void updateGoldenOutputMap(string goldenOutputFile);
265 bool readFilterEventData();
266
267 private:
268 struct FilterThreadArgs {
269 FilterCallback* user;
270 DemuxFilterEvent event;
271 };
272 uint16_t mDataLength = 0;
273 std::vector<uint8_t> mDataOutputBuffer;
274
275 string mFilterIdToGoldenOutput;
276
277 uint32_t mFilterId;
278 FilterEventType mFilterEventType;
279 std::unique_ptr<FilterMQ> mFilterIdToMQ;
280 EventFlag* mFilterIdToMQEventFlag;
281 DemuxFilterEvent mFilterIdToEvent;
282
283 android::Mutex mMsgLock;
284 android::Mutex mFilterOutputLock;
285 android::Condition mMsgCondition;
286 android::Condition mFilterOutputCondition;
287
288 pthread_t mFilterThread;
289
290 int mPidFilterOutputCount = 0;
291 };
292
startFilterEventThread(DemuxFilterEvent event)293 void FilterCallback::startFilterEventThread(DemuxFilterEvent event) {
294 struct FilterThreadArgs* threadArgs =
295 (struct FilterThreadArgs*)malloc(sizeof(struct FilterThreadArgs));
296 threadArgs->user = this;
297 threadArgs->event = event;
298
299 pthread_create(&mFilterThread, NULL, __threadLoopFilter, (void*)threadArgs);
300 pthread_setname_np(mFilterThread, "test_playback_input_loop");
301 }
302
testFilterDataOutput()303 void FilterCallback::testFilterDataOutput() {
304 android::Mutex::Autolock autoLock(mMsgLock);
305 while (mPidFilterOutputCount < 1) {
306 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
307 EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
308 return;
309 }
310 }
311 mPidFilterOutputCount = 0;
312 ALOGW("[vts] pass and stop");
313 }
314
updateFilterMQ(MQDesc & filterMQDescriptor)315 void FilterCallback::updateFilterMQ(MQDesc& filterMQDescriptor) {
316 mFilterIdToMQ = std::make_unique<FilterMQ>(filterMQDescriptor, true /* resetPointers */);
317 EXPECT_TRUE(mFilterIdToMQ);
318 EXPECT_TRUE(EventFlag::createEventFlag(mFilterIdToMQ->getEventFlagWord(),
319 &mFilterIdToMQEventFlag) == android::OK);
320 }
321
updateGoldenOutputMap(string goldenOutputFile)322 void FilterCallback::updateGoldenOutputMap(string goldenOutputFile) {
323 mFilterIdToGoldenOutput = goldenOutputFile;
324 }
325
__threadLoopFilter(void * threadArgs)326 void* FilterCallback::__threadLoopFilter(void* threadArgs) {
327 FilterCallback* const self =
328 static_cast<FilterCallback*>(((struct FilterThreadArgs*)threadArgs)->user);
329 self->filterThreadLoop(((struct FilterThreadArgs*)threadArgs)->event);
330 return 0;
331 }
332
filterThreadLoop(DemuxFilterEvent &)333 void FilterCallback::filterThreadLoop(DemuxFilterEvent& /* event */) {
334 android::Mutex::Autolock autoLock(mFilterOutputLock);
335 // Read from mFilterIdToMQ[event.filterId] per event and filter type
336
337 // Assemble to filterOutput[filterId]
338
339 // check if filterOutput[filterId] matches goldenOutput[filterId]
340
341 // If match, remove filterId entry from MQ map
342
343 // end thread
344 }
345
readFilterEventData()346 bool FilterCallback::readFilterEventData() {
347 bool result = false;
348 DemuxFilterEvent filterEvent = mFilterIdToEvent;
349 ALOGW("[vts] reading from filter FMQ %d", mFilterId);
350 // todo separate filter handlers
351 for (int i = 0; i < filterEvent.events.size(); i++) {
352 switch (mFilterEventType) {
353 case FilterEventType::SECTION:
354 mDataLength = filterEvent.events[i].section().dataLength;
355 break;
356 case FilterEventType::PES:
357 mDataLength = filterEvent.events[i].pes().dataLength;
358 break;
359 case FilterEventType::MEDIA:
360 break;
361 case FilterEventType::RECORD:
362 break;
363 case FilterEventType::MMTPRECORD:
364 break;
365 case FilterEventType::DOWNLOAD:
366 break;
367 default:
368 break;
369 }
370 // EXPECT_TRUE(mDataLength == goldenDataOutputBuffer.size()) << "buffer size does not
371 // match";
372
373 mDataOutputBuffer.resize(mDataLength);
374 result = mFilterIdToMQ->read(mDataOutputBuffer.data(), mDataLength);
375 EXPECT_TRUE(result) << "can't read from Filter MQ";
376
377 /*for (int i = 0; i < mDataLength; i++) {
378 EXPECT_TRUE(goldenDataOutputBuffer[i] == mDataOutputBuffer[i]) << "data does not match";
379 }*/
380 }
381 mFilterIdToMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
382 return result;
383 }
384
385 class DvrCallback : public IDvrCallback {
386 public:
onRecordStatus(DemuxFilterStatus status)387 virtual Return<void> onRecordStatus(DemuxFilterStatus status) override {
388 ALOGW("[vts] record status %hhu", status);
389 switch (status) {
390 case DemuxFilterStatus::DATA_READY:
391 break;
392 case DemuxFilterStatus::LOW_WATER:
393 break;
394 case DemuxFilterStatus::HIGH_WATER:
395 case DemuxFilterStatus::OVERFLOW:
396 ALOGW("[vts] record overflow. Flushing");
397 break;
398 }
399 return Void();
400 }
401
onPlaybackStatus(PlaybackStatus status)402 virtual Return<void> onPlaybackStatus(PlaybackStatus status) override {
403 // android::Mutex::Autolock autoLock(mMsgLock);
404 ALOGW("[vts] playback status %d", status);
405 switch (status) {
406 case PlaybackStatus::SPACE_EMPTY:
407 case PlaybackStatus::SPACE_ALMOST_EMPTY:
408 ALOGW("[vts] keep playback inputing %d", status);
409 mKeepWritingPlaybackFMQ = true;
410 break;
411 case PlaybackStatus::SPACE_ALMOST_FULL:
412 case PlaybackStatus::SPACE_FULL:
413 ALOGW("[vts] stop playback inputing %d", status);
414 mKeepWritingPlaybackFMQ = false;
415 break;
416 }
417 return Void();
418 }
419
420 void testFilterDataOutput();
421 void stopPlaybackThread();
422 void testRecordOutput();
423 void stopRecordThread();
424
425 void startPlaybackInputThread(PlaybackConf playbackConf, MQDesc& playbackMQDescriptor);
426 void startRecordOutputThread(RecordSettings recordSetting, MQDesc& recordMQDescriptor);
427 static void* __threadLoopPlayback(void* threadArgs);
428 static void* __threadLoopRecord(void* threadArgs);
429 void playbackThreadLoop(PlaybackConf* playbackConf, bool* keepWritingPlaybackFMQ);
430 void recordThreadLoop(RecordSettings* recordSetting, bool* keepWritingPlaybackFMQ);
431
432 bool readRecordFMQ();
433
434 private:
435 struct PlaybackThreadArgs {
436 DvrCallback* user;
437 PlaybackConf* playbackConf;
438 bool* keepWritingPlaybackFMQ;
439 };
440 struct RecordThreadArgs {
441 DvrCallback* user;
442 RecordSettings* recordSetting;
443 bool* keepReadingRecordFMQ;
444 };
445 uint16_t mDataLength = 0;
446 std::vector<uint8_t> mDataOutputBuffer;
447
448 std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterIdToMQ;
449 std::unique_ptr<FilterMQ> mPlaybackMQ;
450 std::unique_ptr<FilterMQ> mRecordMQ;
451 std::map<uint32_t, EventFlag*> mFilterIdToMQEventFlag;
452 std::map<uint32_t, DemuxFilterEvent> mFilterIdToEvent;
453
454 android::Mutex mMsgLock;
455 android::Mutex mPlaybackThreadLock;
456 android::Mutex mRecordThreadLock;
457 android::Condition mMsgCondition;
458
459 bool mKeepWritingPlaybackFMQ = true;
460 bool mKeepReadingRecordFMQ = true;
461 bool mPlaybackThreadRunning;
462 bool mRecordThreadRunning;
463 pthread_t mPlaybackThread;
464 pthread_t mRecordThread;
465
466 int mPidFilterOutputCount = 0;
467 };
468
startPlaybackInputThread(PlaybackConf playbackConf,MQDesc & playbackMQDescriptor)469 void DvrCallback::startPlaybackInputThread(PlaybackConf playbackConf,
470 MQDesc& playbackMQDescriptor) {
471 mPlaybackMQ = std::make_unique<FilterMQ>(playbackMQDescriptor, true /* resetPointers */);
472 EXPECT_TRUE(mPlaybackMQ);
473 struct PlaybackThreadArgs* threadArgs =
474 (struct PlaybackThreadArgs*)malloc(sizeof(struct PlaybackThreadArgs));
475 threadArgs->user = this;
476 threadArgs->playbackConf = &playbackConf;
477 threadArgs->keepWritingPlaybackFMQ = &mKeepWritingPlaybackFMQ;
478
479 pthread_create(&mPlaybackThread, NULL, __threadLoopPlayback, (void*)threadArgs);
480 pthread_setname_np(mPlaybackThread, "test_playback_input_loop");
481 }
482
stopPlaybackThread()483 void DvrCallback::stopPlaybackThread() {
484 mPlaybackThreadRunning = false;
485 mKeepWritingPlaybackFMQ = false;
486
487 android::Mutex::Autolock autoLock(mPlaybackThreadLock);
488 }
489
__threadLoopPlayback(void * threadArgs)490 void* DvrCallback::__threadLoopPlayback(void* threadArgs) {
491 DvrCallback* const self =
492 static_cast<DvrCallback*>(((struct PlaybackThreadArgs*)threadArgs)->user);
493 self->playbackThreadLoop(((struct PlaybackThreadArgs*)threadArgs)->playbackConf,
494 ((struct PlaybackThreadArgs*)threadArgs)->keepWritingPlaybackFMQ);
495 return 0;
496 }
497
playbackThreadLoop(PlaybackConf * playbackConf,bool * keepWritingPlaybackFMQ)498 void DvrCallback::playbackThreadLoop(PlaybackConf* playbackConf, bool* keepWritingPlaybackFMQ) {
499 android::Mutex::Autolock autoLock(mPlaybackThreadLock);
500 mPlaybackThreadRunning = true;
501
502 // Create the EventFlag that is used to signal the HAL impl that data have been
503 // written into the Playback FMQ
504 EventFlag* playbackMQEventFlag;
505 EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) ==
506 android::OK);
507
508 // open the stream and get its length
509 std::ifstream inputData(playbackConf->inputDataFile, std::ifstream::binary);
510 int writeSize = playbackConf->setting.packetSize * 6;
511 char* buffer = new char[writeSize];
512 ALOGW("[vts] playback thread loop start %s", playbackConf->inputDataFile.c_str());
513 if (!inputData.is_open()) {
514 mPlaybackThreadRunning = false;
515 ALOGW("[vts] Error %s", strerror(errno));
516 }
517
518 while (mPlaybackThreadRunning) {
519 // move the stream pointer for packet size * 6 every read until the end
520 while (*keepWritingPlaybackFMQ) {
521 inputData.read(buffer, writeSize);
522 if (!inputData) {
523 int leftSize = inputData.gcount();
524 if (leftSize == 0) {
525 mPlaybackThreadRunning = false;
526 break;
527 }
528 inputData.clear();
529 inputData.read(buffer, leftSize);
530 // Write the left over of the input data and quit the thread
531 if (leftSize > 0) {
532 EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], leftSize));
533 playbackMQEventFlag->wake(
534 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
535 }
536 mPlaybackThreadRunning = false;
537 break;
538 }
539 // Write input FMQ and notify the Tuner Implementation
540 EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], writeSize));
541 playbackMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
542 inputData.seekg(writeSize, inputData.cur);
543 sleep(1);
544 }
545 }
546
547 ALOGW("[vts] Playback thread end.");
548
549 delete[] buffer;
550 inputData.close();
551 }
552
testRecordOutput()553 void DvrCallback::testRecordOutput() {
554 android::Mutex::Autolock autoLock(mMsgLock);
555 while (mDataOutputBuffer.empty()) {
556 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
557 EXPECT_TRUE(false) << "record output matching pid does not output within timeout";
558 return;
559 }
560 }
561 stopRecordThread();
562 ALOGW("[vts] record pass and stop");
563 }
564
startRecordOutputThread(RecordSettings recordSetting,MQDesc & recordMQDescriptor)565 void DvrCallback::startRecordOutputThread(RecordSettings recordSetting,
566 MQDesc& recordMQDescriptor) {
567 mRecordMQ = std::make_unique<FilterMQ>(recordMQDescriptor, true /* resetPointers */);
568 EXPECT_TRUE(mRecordMQ);
569 struct RecordThreadArgs* threadArgs =
570 (struct RecordThreadArgs*)malloc(sizeof(struct RecordThreadArgs));
571 threadArgs->user = this;
572 threadArgs->recordSetting = &recordSetting;
573 threadArgs->keepReadingRecordFMQ = &mKeepReadingRecordFMQ;
574
575 pthread_create(&mRecordThread, NULL, __threadLoopRecord, (void*)threadArgs);
576 pthread_setname_np(mRecordThread, "test_record_input_loop");
577 }
578
__threadLoopRecord(void * threadArgs)579 void* DvrCallback::__threadLoopRecord(void* threadArgs) {
580 DvrCallback* const self =
581 static_cast<DvrCallback*>(((struct RecordThreadArgs*)threadArgs)->user);
582 self->recordThreadLoop(((struct RecordThreadArgs*)threadArgs)->recordSetting,
583 ((struct RecordThreadArgs*)threadArgs)->keepReadingRecordFMQ);
584 return 0;
585 }
586
recordThreadLoop(RecordSettings *,bool * keepReadingRecordFMQ)587 void DvrCallback::recordThreadLoop(RecordSettings* /*recordSetting*/, bool* keepReadingRecordFMQ) {
588 ALOGD("[vts] DvrCallback record threadLoop start.");
589 android::Mutex::Autolock autoLock(mRecordThreadLock);
590 mRecordThreadRunning = true;
591
592 // Create the EventFlag that is used to signal the HAL impl that data have been
593 // read from the Record FMQ
594 EventFlag* recordMQEventFlag;
595 EXPECT_TRUE(EventFlag::createEventFlag(mRecordMQ->getEventFlagWord(), &recordMQEventFlag) ==
596 android::OK);
597
598 while (mRecordThreadRunning) {
599 while (*keepReadingRecordFMQ) {
600 uint32_t efState = 0;
601 android::status_t status = recordMQEventFlag->wait(
602 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
603 true /* retry on spurious wake */);
604 if (status != android::OK) {
605 ALOGD("[vts] wait for data ready on the record FMQ");
606 continue;
607 }
608 // Our current implementation filter the data and write it into the filter FMQ
609 // immediately after the DATA_READY from the VTS/framework
610 if (!readRecordFMQ()) {
611 ALOGD("[vts] record data failed to be filtered. Ending thread");
612 mRecordThreadRunning = false;
613 break;
614 }
615 }
616 }
617
618 mRecordThreadRunning = false;
619 ALOGD("[vts] record thread ended.");
620 }
621
readRecordFMQ()622 bool DvrCallback::readRecordFMQ() {
623 android::Mutex::Autolock autoLock(mMsgLock);
624 bool result = false;
625 mDataOutputBuffer.clear();
626 mDataOutputBuffer.resize(mRecordMQ->availableToRead());
627 result = mRecordMQ->read(mDataOutputBuffer.data(), mRecordMQ->availableToRead());
628 EXPECT_TRUE(result) << "can't read from Record MQ";
629 mMsgCondition.signal();
630 return result;
631 }
632
stopRecordThread()633 void DvrCallback::stopRecordThread() {
634 mKeepReadingRecordFMQ = false;
635 mRecordThreadRunning = false;
636 android::Mutex::Autolock autoLock(mRecordThreadLock);
637 }
638
639 class TunerHidlTest : public testing::TestWithParam<std::string> {
640 public:
SetUp()641 virtual void SetUp() override {
642 mService = ITuner::getService(GetParam());
643 ASSERT_NE(mService, nullptr);
644 }
645
646 sp<ITuner> mService;
647
648 protected:
description(const std::string & description)649 static void description(const std::string& description) {
650 RecordProperty("description", description);
651 }
652
653 sp<IFrontend> mFrontend;
654 sp<FrontendCallback> mFrontendCallback;
655 sp<IDescrambler> mDescrambler;
656 sp<IDemux> mDemux;
657 sp<IDvr> mDvr;
658 sp<IFilter> mFilter;
659 std::map<uint32_t, sp<IFilter>> mFilters;
660 std::map<uint32_t, sp<FilterCallback>> mFilterCallbacks;
661 sp<FilterCallback> mFilterCallback;
662 sp<DvrCallback> mDvrCallback;
663 MQDesc mFilterMQDescriptor;
664 MQDesc mPlaybackMQDescriptor;
665 MQDesc mRecordMQDescriptor;
666 vector<uint32_t> mUsedFilterIds;
667
668 uint32_t mDemuxId;
669 uint32_t mFilterId;
670
671 pthread_t mPlaybackshread;
672 bool mPlaybackThreadRunning;
673
674 ::testing::AssertionResult createFrontend(int32_t frontendId);
675 ::testing::AssertionResult tuneFrontend(int32_t frontendId);
676 ::testing::AssertionResult stopTuneFrontend(int32_t frontendId);
677 ::testing::AssertionResult closeFrontend(int32_t frontendId);
678 ::testing::AssertionResult createDemux();
679 ::testing::AssertionResult createDemuxWithFrontend(int32_t frontendId,
680 FrontendSettings settings);
681 ::testing::AssertionResult getPlaybackMQDescriptor();
682 ::testing::AssertionResult addPlaybackToDemux(PlaybackSettings setting);
683 ::testing::AssertionResult getRecordMQDescriptor();
684 ::testing::AssertionResult addRecordToDemux(RecordSettings setting);
685 ::testing::AssertionResult addFilterToDemux(DemuxFilterType type, DemuxFilterSettings setting);
686 ::testing::AssertionResult getFilterMQDescriptor();
687 ::testing::AssertionResult closeDemux();
688 ::testing::AssertionResult createDescrambler();
689 ::testing::AssertionResult closeDescrambler();
690
691 ::testing::AssertionResult playbackDataFlowTest(vector<FilterConf> filterConf,
692 PlaybackConf playbackConf,
693 vector<string> goldenOutputFiles);
694 ::testing::AssertionResult recordDataFlowTest(vector<FilterConf> filterConf,
695 RecordSettings recordSetting,
696 vector<string> goldenOutputFiles);
697 ::testing::AssertionResult broadcastDataFlowTest(vector<FilterConf> filterConf,
698 vector<string> goldenOutputFiles);
699 };
700
createFrontend(int32_t frontendId)701 ::testing::AssertionResult TunerHidlTest::createFrontend(int32_t frontendId) {
702 Result status;
703
704 mService->openFrontendById(frontendId, [&](Result result, const sp<IFrontend>& frontend) {
705 mFrontend = frontend;
706 status = result;
707 });
708 if (status != Result::SUCCESS) {
709 return ::testing::AssertionFailure();
710 }
711
712 mFrontendCallback = new FrontendCallback();
713 auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
714
715 return ::testing::AssertionResult(callbackStatus.isOk());
716 }
717
tuneFrontend(int32_t frontendId)718 ::testing::AssertionResult TunerHidlTest::tuneFrontend(int32_t frontendId) {
719 if (createFrontend(frontendId) == ::testing::AssertionFailure()) {
720 return ::testing::AssertionFailure();
721 }
722
723 // Frontend Settings for testing
724 FrontendSettings frontendSettings;
725 FrontendAtscSettings frontendAtscSettings{
726 .frequency = 0,
727 .modulation = FrontendAtscModulation::UNDEFINED,
728 };
729 frontendSettings.atsc(frontendAtscSettings);
730 mFrontendCallback->testOnEvent(mFrontend, frontendSettings);
731
732 FrontendDvbtSettings frontendDvbtSettings{
733 .frequency = 0,
734 };
735 frontendSettings.dvbt(frontendDvbtSettings);
736 mFrontendCallback->testOnEvent(mFrontend, frontendSettings);
737
738 return ::testing::AssertionResult(true);
739 }
740
stopTuneFrontend(int32_t frontendId)741 ::testing::AssertionResult TunerHidlTest::stopTuneFrontend(int32_t frontendId) {
742 Result status;
743 if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) {
744 return ::testing::AssertionFailure();
745 }
746
747 status = mFrontend->stopTune();
748 return ::testing::AssertionResult(status == Result::SUCCESS);
749 }
750
closeFrontend(int32_t frontendId)751 ::testing::AssertionResult TunerHidlTest::closeFrontend(int32_t frontendId) {
752 Result status;
753 if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) {
754 return ::testing::AssertionFailure();
755 }
756
757 status = mFrontend->close();
758 mFrontend = nullptr;
759 return ::testing::AssertionResult(status == Result::SUCCESS);
760 }
761
createDemux()762 ::testing::AssertionResult TunerHidlTest::createDemux() {
763 Result status;
764
765 mService->openDemux([&](Result result, uint32_t demuxId, const sp<IDemux>& demux) {
766 mDemux = demux;
767 mDemuxId = demuxId;
768 status = result;
769 });
770 return ::testing::AssertionResult(status == Result::SUCCESS);
771 }
772
createDemuxWithFrontend(int32_t frontendId,FrontendSettings settings)773 ::testing::AssertionResult TunerHidlTest::createDemuxWithFrontend(int32_t frontendId,
774 FrontendSettings settings) {
775 Result status;
776
777 if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
778 return ::testing::AssertionFailure();
779 }
780
781 if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) {
782 return ::testing::AssertionFailure();
783 }
784
785 mFrontendCallback->testOnEvent(mFrontend, settings);
786
787 status = mDemux->setFrontendDataSource(frontendId);
788
789 return ::testing::AssertionResult(status == Result::SUCCESS);
790 }
791
closeDemux()792 ::testing::AssertionResult TunerHidlTest::closeDemux() {
793 Result status;
794 if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
795 return ::testing::AssertionFailure();
796 }
797
798 status = mDemux->close();
799 mDemux = nullptr;
800 return ::testing::AssertionResult(status == Result::SUCCESS);
801 }
802
createDescrambler()803 ::testing::AssertionResult TunerHidlTest::createDescrambler() {
804 Result status;
805
806 mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) {
807 mDescrambler = descrambler;
808 status = result;
809 });
810 if (status != Result::SUCCESS) {
811 return ::testing::AssertionFailure();
812 }
813
814 if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
815 return ::testing::AssertionFailure();
816 }
817
818 status = mDescrambler->setDemuxSource(mDemuxId);
819 if (status != Result::SUCCESS) {
820 return ::testing::AssertionFailure();
821 }
822
823 // Test if demux source can be set more than once.
824 status = mDescrambler->setDemuxSource(mDemuxId);
825 return ::testing::AssertionResult(status == Result::INVALID_STATE);
826 }
827
closeDescrambler()828 ::testing::AssertionResult TunerHidlTest::closeDescrambler() {
829 Result status;
830 if (!mDescrambler && createDescrambler() == ::testing::AssertionFailure()) {
831 return ::testing::AssertionFailure();
832 }
833
834 status = mDescrambler->close();
835 mDescrambler = nullptr;
836 return ::testing::AssertionResult(status == Result::SUCCESS);
837 }
838
addPlaybackToDemux(PlaybackSettings setting)839 ::testing::AssertionResult TunerHidlTest::addPlaybackToDemux(PlaybackSettings setting) {
840 Result status;
841
842 if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
843 return ::testing::AssertionFailure();
844 }
845
846 // Create dvr callback
847 mDvrCallback = new DvrCallback();
848
849 // Add playback input to the local demux
850 mDemux->openDvr(DvrType::PLAYBACK, FMQ_SIZE_1M, mDvrCallback,
851 [&](Result result, const sp<IDvr>& dvr) {
852 mDvr = dvr;
853 status = result;
854 });
855
856 if (status != Result::SUCCESS) {
857 return ::testing::AssertionFailure();
858 }
859
860 DvrSettings dvrSetting;
861 dvrSetting.playback(setting);
862 status = mDvr->configure(dvrSetting);
863
864 return ::testing::AssertionResult(status == Result::SUCCESS);
865 }
866
getPlaybackMQDescriptor()867 ::testing::AssertionResult TunerHidlTest::getPlaybackMQDescriptor() {
868 Result status;
869
870 if ((!mDemux && createDemux() == ::testing::AssertionFailure()) || !mDvr) {
871 return ::testing::AssertionFailure();
872 }
873
874 mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
875 mPlaybackMQDescriptor = dvrMQDesc;
876 status = result;
877 });
878
879 return ::testing::AssertionResult(status == Result::SUCCESS);
880 }
881
addRecordToDemux(RecordSettings setting)882 ::testing::AssertionResult TunerHidlTest::addRecordToDemux(RecordSettings setting) {
883 Result status;
884
885 if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
886 return ::testing::AssertionFailure();
887 }
888
889 // Create dvr callback
890 mDvrCallback = new DvrCallback();
891
892 // Add playback input to the local demux
893 mDemux->openDvr(DvrType::RECORD, FMQ_SIZE_1M, mDvrCallback,
894 [&](Result result, const sp<IDvr>& dvr) {
895 mDvr = dvr;
896 status = result;
897 });
898
899 if (status != Result::SUCCESS) {
900 return ::testing::AssertionFailure();
901 }
902
903 DvrSettings dvrSetting;
904 dvrSetting.record(setting);
905 status = mDvr->configure(dvrSetting);
906
907 return ::testing::AssertionResult(status == Result::SUCCESS);
908 }
909
getRecordMQDescriptor()910 ::testing::AssertionResult TunerHidlTest::getRecordMQDescriptor() {
911 Result status;
912
913 if ((!mDemux && createDemux() == ::testing::AssertionFailure()) || !mDvr) {
914 return ::testing::AssertionFailure();
915 }
916
917 mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
918 mRecordMQDescriptor = dvrMQDesc;
919 status = result;
920 });
921
922 return ::testing::AssertionResult(status == Result::SUCCESS);
923 }
924
addFilterToDemux(DemuxFilterType type,DemuxFilterSettings setting)925 ::testing::AssertionResult TunerHidlTest::addFilterToDemux(DemuxFilterType type,
926 DemuxFilterSettings setting) {
927 Result status;
928
929 if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
930 return ::testing::AssertionFailure();
931 }
932
933 // Create demux callback
934 mFilterCallback = new FilterCallback();
935
936 // Add filter to the local demux
937 mDemux->openFilter(type, FMQ_SIZE_16M, mFilterCallback,
938 [&](Result result, const sp<IFilter>& filter) {
939 mFilter = filter;
940 status = result;
941 });
942
943 if (status != Result::SUCCESS) {
944 return ::testing::AssertionFailure();
945 }
946
947 mFilter->getId([&](Result result, uint32_t filterId) {
948 mFilterId = filterId;
949 status = result;
950 });
951
952 if (status != Result::SUCCESS) {
953 return ::testing::AssertionFailure();
954 }
955
956 mFilterCallback->setFilterId(mFilterId);
957
958 FilterEventType eventType = FilterEventType::UNDEFINED;
959 switch (type.mainType) {
960 case DemuxFilterMainType::TS:
961 switch (type.subType.tsFilterType()) {
962 case DemuxTsFilterType::UNDEFINED:
963 break;
964 case DemuxTsFilterType::SECTION:
965 eventType = FilterEventType::SECTION;
966 break;
967 case DemuxTsFilterType::PES:
968 eventType = FilterEventType::PES;
969 break;
970 case DemuxTsFilterType::TS:
971 break;
972 case DemuxTsFilterType::AUDIO:
973 case DemuxTsFilterType::VIDEO:
974 eventType = FilterEventType::MEDIA;
975 break;
976 case DemuxTsFilterType::PCR:
977 break;
978 case DemuxTsFilterType::RECORD:
979 eventType = FilterEventType::RECORD;
980 break;
981 case DemuxTsFilterType::TEMI:
982 eventType = FilterEventType::TEMI;
983 break;
984 }
985 break;
986 case DemuxFilterMainType::MMTP:
987 /*mmtpSettings*/
988 break;
989 case DemuxFilterMainType::IP:
990 /*ipSettings*/
991 break;
992 case DemuxFilterMainType::TLV:
993 /*tlvSettings*/
994 break;
995 case DemuxFilterMainType::ALP:
996 /*alpSettings*/
997 break;
998 default:
999 break;
1000 }
1001 mFilterCallback->setFilterEventType(eventType);
1002
1003 // Configure the filter
1004 status = mFilter->configure(setting);
1005
1006 return ::testing::AssertionResult(status == Result::SUCCESS);
1007 }
1008
getFilterMQDescriptor()1009 ::testing::AssertionResult TunerHidlTest::getFilterMQDescriptor() {
1010 Result status;
1011
1012 if (!mDemux || !mFilter) {
1013 return ::testing::AssertionFailure();
1014 }
1015
1016 mFilter->getQueueDesc([&](Result result, const MQDesc& filterMQDesc) {
1017 mFilterMQDescriptor = filterMQDesc;
1018 status = result;
1019 });
1020
1021 return ::testing::AssertionResult(status == Result::SUCCESS);
1022 }
1023
playbackDataFlowTest(vector<FilterConf> filterConf,PlaybackConf playbackConf,vector<string>)1024 ::testing::AssertionResult TunerHidlTest::playbackDataFlowTest(
1025 vector<FilterConf> filterConf, PlaybackConf playbackConf,
1026 vector<string> /*goldenOutputFiles*/) {
1027 Result status;
1028 int filterIdsSize;
1029 // Filter Configuration Module
1030 for (int i = 0; i < filterConf.size(); i++) {
1031 if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) ==
1032 ::testing::AssertionFailure() ||
1033 // TODO use a map to save the FMQs/EvenFlags and pass to callback
1034 getFilterMQDescriptor() == ::testing::AssertionFailure()) {
1035 return ::testing::AssertionFailure();
1036 }
1037 filterIdsSize = mUsedFilterIds.size();
1038 mUsedFilterIds.resize(filterIdsSize + 1);
1039 mUsedFilterIds[filterIdsSize] = mFilterId;
1040 mFilters[mFilterId] = mFilter;
1041 mFilterCallbacks[mFilterId] = mFilterCallback;
1042 mFilterCallback->updateFilterMQ(mFilterMQDescriptor);
1043 // mDemuxCallback->updateGoldenOutputMap(goldenOutputFiles[i]);
1044 status = mFilter->start();
1045 if (status != Result::SUCCESS) {
1046 return ::testing::AssertionFailure();
1047 }
1048 }
1049
1050 // Playback Input Module
1051 PlaybackSettings playbackSetting = playbackConf.setting;
1052 if (addPlaybackToDemux(playbackSetting) == ::testing::AssertionFailure() ||
1053 getPlaybackMQDescriptor() == ::testing::AssertionFailure()) {
1054 return ::testing::AssertionFailure();
1055 }
1056 for (int i = 0; i <= filterIdsSize; i++) {
1057 if (mDvr->attachFilter(mFilters[mUsedFilterIds[i]]) != Result::SUCCESS) {
1058 return ::testing::AssertionFailure();
1059 }
1060 }
1061 mDvrCallback->startPlaybackInputThread(playbackConf, mPlaybackMQDescriptor);
1062 status = mDvr->start();
1063 if (status != Result::SUCCESS) {
1064 return ::testing::AssertionFailure();
1065 }
1066
1067 // Data Verify Module
1068 std::map<uint32_t, sp<FilterCallback>>::iterator it;
1069 for (it = mFilterCallbacks.begin(); it != mFilterCallbacks.end(); it++) {
1070 it->second->testFilterDataOutput();
1071 }
1072 mDvrCallback->stopPlaybackThread();
1073
1074 // Clean Up Module
1075 for (int i = 0; i <= filterIdsSize; i++) {
1076 if (mFilters[mUsedFilterIds[i]]->stop() != Result::SUCCESS) {
1077 return ::testing::AssertionFailure();
1078 }
1079 }
1080 if (mDvr->stop() != Result::SUCCESS) {
1081 return ::testing::AssertionFailure();
1082 }
1083 mUsedFilterIds.clear();
1084 mFilterCallbacks.clear();
1085 mFilters.clear();
1086 return closeDemux();
1087 }
1088
broadcastDataFlowTest(vector<FilterConf> filterConf,vector<string>)1089 ::testing::AssertionResult TunerHidlTest::broadcastDataFlowTest(
1090 vector<FilterConf> filterConf, vector<string> /*goldenOutputFiles*/) {
1091 Result status;
1092 hidl_vec<FrontendId> feIds;
1093
1094 mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
1095 status = result;
1096 feIds = frontendIds;
1097 });
1098
1099 if (feIds.size() == 0) {
1100 ALOGW("[ WARN ] Frontend isn't available");
1101 return ::testing::AssertionFailure();
1102 }
1103
1104 FrontendDvbtSettings dvbt{
1105 .frequency = 1000,
1106 };
1107 FrontendSettings settings;
1108 settings.dvbt(dvbt);
1109
1110 if (createDemuxWithFrontend(feIds[0], settings) != ::testing::AssertionSuccess()) {
1111 return ::testing::AssertionFailure();
1112 }
1113
1114 int filterIdsSize;
1115 // Filter Configuration Module
1116 for (int i = 0; i < filterConf.size(); i++) {
1117 if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) ==
1118 ::testing::AssertionFailure() ||
1119 // TODO use a map to save the FMQs/EvenFlags and pass to callback
1120 getFilterMQDescriptor() == ::testing::AssertionFailure()) {
1121 return ::testing::AssertionFailure();
1122 }
1123 filterIdsSize = mUsedFilterIds.size();
1124 mUsedFilterIds.resize(filterIdsSize + 1);
1125 mUsedFilterIds[filterIdsSize] = mFilterId;
1126 mFilters[mFilterId] = mFilter;
1127 mFilterCallbacks[mFilterId] = mFilterCallback;
1128 mFilterCallback->updateFilterMQ(mFilterMQDescriptor);
1129 status = mFilter->start();
1130 if (status != Result::SUCCESS) {
1131 return ::testing::AssertionFailure();
1132 }
1133 }
1134
1135 // Data Verify Module
1136 std::map<uint32_t, sp<FilterCallback>>::iterator it;
1137 for (it = mFilterCallbacks.begin(); it != mFilterCallbacks.end(); it++) {
1138 it->second->testFilterDataOutput();
1139 }
1140
1141 // Clean Up Module
1142 for (int i = 0; i <= filterIdsSize; i++) {
1143 if (mFilters[mUsedFilterIds[i]]->stop() != Result::SUCCESS) {
1144 return ::testing::AssertionFailure();
1145 }
1146 }
1147 if (mFrontend->stopTune() != Result::SUCCESS) {
1148 return ::testing::AssertionFailure();
1149 }
1150 mUsedFilterIds.clear();
1151 mFilterCallbacks.clear();
1152 mFilters.clear();
1153 return closeDemux();
1154 }
1155
recordDataFlowTest(vector<FilterConf> filterConf,RecordSettings recordSetting,vector<string>)1156 ::testing::AssertionResult TunerHidlTest::recordDataFlowTest(vector<FilterConf> filterConf,
1157 RecordSettings recordSetting,
1158 vector<string> /*goldenOutputFiles*/) {
1159 Result status;
1160 hidl_vec<FrontendId> feIds;
1161
1162 mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
1163 status = result;
1164 feIds = frontendIds;
1165 });
1166
1167 if (feIds.size() == 0) {
1168 ALOGW("[ WARN ] Frontend isn't available");
1169 return ::testing::AssertionFailure();
1170 }
1171
1172 FrontendDvbtSettings dvbt{
1173 .frequency = 1000,
1174 };
1175 FrontendSettings settings;
1176 settings.dvbt(dvbt);
1177
1178 int filterIdsSize;
1179 // Filter Configuration Module
1180 for (int i = 0; i < filterConf.size(); i++) {
1181 if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) ==
1182 ::testing::AssertionFailure() ||
1183 // TODO use a map to save the FMQs/EvenFlags and pass to callback
1184 getFilterMQDescriptor() == ::testing::AssertionFailure()) {
1185 return ::testing::AssertionFailure();
1186 }
1187 filterIdsSize = mUsedFilterIds.size();
1188 mUsedFilterIds.resize(filterIdsSize + 1);
1189 mUsedFilterIds[filterIdsSize] = mFilterId;
1190 mFilters[mFilterId] = mFilter;
1191 }
1192
1193 // Record Config Module
1194 if (addRecordToDemux(recordSetting) == ::testing::AssertionFailure() ||
1195 getRecordMQDescriptor() == ::testing::AssertionFailure()) {
1196 return ::testing::AssertionFailure();
1197 }
1198 for (int i = 0; i <= filterIdsSize; i++) {
1199 if (mDvr->attachFilter(mFilters[mUsedFilterIds[i]]) != Result::SUCCESS) {
1200 return ::testing::AssertionFailure();
1201 }
1202 }
1203
1204 mDvrCallback->startRecordOutputThread(recordSetting, mRecordMQDescriptor);
1205 status = mDvr->start();
1206 if (status != Result::SUCCESS) {
1207 return ::testing::AssertionFailure();
1208 }
1209
1210 if (createDemuxWithFrontend(feIds[0], settings) != ::testing::AssertionSuccess()) {
1211 return ::testing::AssertionFailure();
1212 }
1213
1214 // Data Verify Module
1215 mDvrCallback->testRecordOutput();
1216
1217 // Clean Up Module
1218 for (int i = 0; i <= filterIdsSize; i++) {
1219 if (mFilters[mUsedFilterIds[i]]->stop() != Result::SUCCESS) {
1220 return ::testing::AssertionFailure();
1221 }
1222 }
1223 if (mFrontend->stopTune() != Result::SUCCESS) {
1224 return ::testing::AssertionFailure();
1225 }
1226 mUsedFilterIds.clear();
1227 mFilterCallbacks.clear();
1228 mFilters.clear();
1229 return closeDemux();
1230 }
1231
1232 /*
1233 * API STATUS TESTS
1234 */
TEST_P(TunerHidlTest,CreateFrontend)1235 TEST_P(TunerHidlTest, CreateFrontend) {
1236 Result status;
1237 hidl_vec<FrontendId> feIds;
1238
1239 description("Create Frontends");
1240 mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
1241 status = result;
1242 feIds = frontendIds;
1243 });
1244
1245 if (feIds.size() == 0) {
1246 ALOGW("[ WARN ] Frontend isn't available");
1247 return;
1248 }
1249
1250 for (size_t i = 0; i < feIds.size(); i++) {
1251 ASSERT_TRUE(createFrontend(feIds[i]));
1252 }
1253 }
1254
TEST_P(TunerHidlTest,TuneFrontend)1255 TEST_P(TunerHidlTest, TuneFrontend) {
1256 Result status;
1257 hidl_vec<FrontendId> feIds;
1258
1259 description("Tune Frontends and check callback onEvent");
1260 mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
1261 status = result;
1262 feIds = frontendIds;
1263 });
1264
1265 if (feIds.size() == 0) {
1266 ALOGW("[ WARN ] Frontend isn't available");
1267 return;
1268 }
1269
1270 for (size_t i = 0; i < feIds.size(); i++) {
1271 ASSERT_TRUE(tuneFrontend(feIds[i]));
1272 }
1273 }
1274
TEST_P(TunerHidlTest,StopTuneFrontend)1275 TEST_P(TunerHidlTest, StopTuneFrontend) {
1276 Result status;
1277 hidl_vec<FrontendId> feIds;
1278
1279 description("stopTune Frontends");
1280 mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
1281 status = result;
1282 feIds = frontendIds;
1283 });
1284
1285 if (feIds.size() == 0) {
1286 ALOGW("[ WARN ] Frontend isn't available");
1287 return;
1288 }
1289
1290 for (size_t i = 0; i < feIds.size(); i++) {
1291 ASSERT_TRUE(stopTuneFrontend(feIds[i]));
1292 }
1293 }
1294
TEST_P(TunerHidlTest,CloseFrontend)1295 TEST_P(TunerHidlTest, CloseFrontend) {
1296 Result status;
1297 hidl_vec<FrontendId> feIds;
1298
1299 description("Close Frontends");
1300 mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
1301 status = result;
1302 feIds = frontendIds;
1303 });
1304
1305 if (feIds.size() == 0) {
1306 ALOGW("[ WARN ] Frontend isn't available");
1307 return;
1308 }
1309
1310 for (size_t i = 0; i < feIds.size(); i++) {
1311 ASSERT_TRUE(closeFrontend(feIds[i]));
1312 }
1313 }
1314
TEST_P(TunerHidlTest,CreateDemuxWithFrontend)1315 TEST_P(TunerHidlTest, CreateDemuxWithFrontend) {
1316 Result status;
1317 hidl_vec<FrontendId> feIds;
1318
1319 description("Create Demux with Frontend");
1320 mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
1321 status = result;
1322 feIds = frontendIds;
1323 });
1324
1325 if (feIds.size() == 0) {
1326 ALOGW("[ WARN ] Frontend isn't available");
1327 return;
1328 }
1329
1330 FrontendDvbtSettings dvbt{
1331 .frequency = 1000,
1332 };
1333 FrontendSettings settings;
1334 settings.dvbt(dvbt);
1335
1336 for (size_t i = 0; i < feIds.size(); i++) {
1337 ASSERT_TRUE(createDemuxWithFrontend(feIds[i], settings));
1338 mFrontend->stopTune();
1339 }
1340 }
1341
TEST_P(TunerHidlTest,CreateDemux)1342 TEST_P(TunerHidlTest, CreateDemux) {
1343 description("Create Demux");
1344 ASSERT_TRUE(createDemux());
1345 }
1346
TEST_P(TunerHidlTest,CloseDemux)1347 TEST_P(TunerHidlTest, CloseDemux) {
1348 description("Close Demux");
1349 ASSERT_TRUE(closeDemux());
1350 }
1351
TEST_P(TunerHidlTest,CreateDescrambler)1352 TEST_P(TunerHidlTest, CreateDescrambler) {
1353 description("Create Descrambler");
1354 ASSERT_TRUE(createDescrambler());
1355 }
1356
TEST_P(TunerHidlTest,CloseDescrambler)1357 TEST_P(TunerHidlTest, CloseDescrambler) {
1358 description("Close Descrambler");
1359 ASSERT_TRUE(closeDescrambler());
1360 }
1361
1362 /*
1363 * DATA FLOW TESTS
1364 *
1365 * TODO: re-enable the tests after finalizing the testing stream.
1366 */
1367 /*TEST_P(TunerHidlTest, PlaybackDataFlowWithSectionFilterTest) {
1368 description("Feed ts data from playback and configure pes filter to get output");
1369
1370 // todo modulize the filter conf parser
1371 vector<FilterConf> filterConf;
1372 filterConf.resize(1);
1373
1374 DemuxFilterSettings filterSetting;
1375 DemuxTsFilterSettings tsFilterSetting{
1376 .tpid = 18,
1377 };
1378 DemuxFilterSectionSettings sectionFilterSetting;
1379 tsFilterSetting.filterSettings.section(sectionFilterSetting);
1380 filterSetting.ts(tsFilterSetting);
1381
1382 DemuxFilterType type{
1383 .mainType = DemuxFilterMainType::TS,
1384 };
1385 type.subType.tsFilterType(DemuxTsFilterType::SECTION);
1386 FilterConf sectionFilterConf{
1387 .type = type,
1388 .setting = filterSetting,
1389 };
1390 filterConf[0] = sectionFilterConf;
1391
1392 PlaybackSettings playbackSetting{
1393 .statusMask = 0xf,
1394 .lowThreshold = 0x1000,
1395 .highThreshold = 0x07fff,
1396 .dataFormat = DataFormat::TS,
1397 .packetSize = 188,
1398 };
1399
1400 PlaybackConf playbackConf{
1401 .inputDataFile = "/vendor/etc/test1.ts",
1402 .setting = playbackSetting,
1403 };
1404
1405 vector<string> goldenOutputFiles;
1406
1407 ASSERT_TRUE(playbackDataFlowTest(filterConf, playbackConf, goldenOutputFiles));
1408 }
1409
1410 TEST_P(TunerHidlTest, BroadcastDataFlowWithPesFilterTest) {
1411 description("Feed ts data from frontend and test with PES filter");
1412
1413 // todo modulize the filter conf parser
1414 vector<FilterConf> filterConf;
1415 filterConf.resize(1);
1416
1417 DemuxFilterSettings filterSetting;
1418 DemuxTsFilterSettings tsFilterSetting{
1419 .tpid = 119,
1420 };
1421 DemuxFilterPesDataSettings pesFilterSetting;
1422 tsFilterSetting.filterSettings.pesData(pesFilterSetting);
1423 filterSetting.ts(tsFilterSetting);
1424
1425 DemuxFilterType type{
1426 .mainType = DemuxFilterMainType::TS,
1427 };
1428 type.subType.tsFilterType(DemuxTsFilterType::PES);
1429 FilterConf pesFilterConf{
1430 .type = type,
1431 .setting = filterSetting,
1432 };
1433 filterConf[0] = pesFilterConf;
1434
1435 vector<string> goldenOutputFiles;
1436
1437 ASSERT_TRUE(broadcastDataFlowTest(filterConf, goldenOutputFiles));
1438 }
1439
1440 TEST_P(TunerHidlTest, RecordDataFlowWithTsRecordFilterTest) {
1441 description("Feed ts data from frontend to recording and test with ts record filter");
1442
1443 // todo modulize the filter conf parser
1444 vector<FilterConf> filterConf;
1445 filterConf.resize(1);
1446
1447 DemuxFilterSettings filterSetting;
1448 DemuxTsFilterSettings tsFilterSetting{
1449 .tpid = 119,
1450 };
1451 DemuxFilterRecordSettings recordFilterSetting;
1452 tsFilterSetting.filterSettings.record(recordFilterSetting);
1453 filterSetting.ts(tsFilterSetting);
1454
1455 DemuxFilterType type{
1456 .mainType = DemuxFilterMainType::TS,
1457 };
1458 type.subType.tsFilterType(DemuxTsFilterType::RECORD);
1459 FilterConf recordFilterConf{
1460 .type = type,
1461 .setting = filterSetting,
1462 };
1463 filterConf[0] = recordFilterConf;
1464
1465 RecordSettings recordSetting{
1466 .statusMask = 0xf,
1467 .lowThreshold = 0x1000,
1468 .highThreshold = 0x07fff,
1469 .dataFormat = DataFormat::TS,
1470 .packetSize = 188,
1471 };
1472
1473 vector<string> goldenOutputFiles;
1474
1475 ASSERT_TRUE(recordDataFlowTest(filterConf, recordSetting, goldenOutputFiles));
1476 }*/
1477
1478 } // namespace
1479
1480 INSTANTIATE_TEST_SUITE_P(
1481 PerInstance, TunerHidlTest,
1482 testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
1483 android::hardware::PrintInstanceNameToString);
1484