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