1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "FilterTests.h"
18 
startFilterEventThread(DemuxFilterEvent event)19 void FilterCallback::startFilterEventThread(DemuxFilterEvent event) {
20     struct FilterThreadArgs* threadArgs =
21             (struct FilterThreadArgs*)malloc(sizeof(struct FilterThreadArgs));
22     threadArgs->user = this;
23     threadArgs->event = event;
24 
25     pthread_create(&mFilterThread, NULL, __threadLoopFilter, (void*)threadArgs);
26     pthread_setname_np(mFilterThread, "test_playback_input_loop");
27 }
28 
testFilterDataOutput()29 void FilterCallback::testFilterDataOutput() {
30     android::Mutex::Autolock autoLock(mMsgLock);
31     while (mPidFilterOutputCount < 1) {
32         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
33             EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
34             return;
35         }
36     }
37     mPidFilterOutputCount = 0;
38     ALOGW("[vts] pass and stop");
39 }
40 
updateFilterMQ(MQDesc & filterMQDescriptor)41 void FilterCallback::updateFilterMQ(MQDesc& filterMQDescriptor) {
42     mFilterMQ = std::make_unique<FilterMQ>(filterMQDescriptor, true /* resetPointers */);
43     EXPECT_TRUE(mFilterMQ);
44     EXPECT_TRUE(EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterMQEventFlag) ==
45                 android::OK);
46 }
47 
updateGoldenOutputMap(string goldenOutputFile)48 void FilterCallback::updateGoldenOutputMap(string goldenOutputFile) {
49     mFilterIdToGoldenOutput = goldenOutputFile;
50 }
51 
__threadLoopFilter(void * threadArgs)52 void* FilterCallback::__threadLoopFilter(void* threadArgs) {
53     FilterCallback* const self =
54             static_cast<FilterCallback*>(((struct FilterThreadArgs*)threadArgs)->user);
55     self->filterThreadLoop(((struct FilterThreadArgs*)threadArgs)->event);
56     return 0;
57 }
58 
filterThreadLoop(DemuxFilterEvent &)59 void FilterCallback::filterThreadLoop(DemuxFilterEvent& /* event */) {
60     android::Mutex::Autolock autoLock(mFilterOutputLock);
61     // Read from mFilterMQ[event.filterId] per event and filter type
62 
63     // Assemble to filterOutput[filterId]
64 
65     // check if filterOutput[filterId] matches goldenOutput[filterId]
66 
67     // If match, remove filterId entry from MQ map
68 
69     // end thread
70 }
71 
readFilterEventData()72 bool FilterCallback::readFilterEventData() {
73     bool result = false;
74     DemuxFilterEvent filterEvent = mFilterEvent;
75     ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
76     // todo separate filter handlers
77     for (int i = 0; i < filterEvent.events.size(); i++) {
78         switch (mFilterEventType) {
79             case FilterEventType::SECTION:
80                 mDataLength = filterEvent.events[i].section().dataLength;
81                 break;
82             case FilterEventType::PES:
83                 mDataLength = filterEvent.events[i].pes().dataLength;
84                 break;
85             case FilterEventType::MEDIA:
86                 return dumpAvData(filterEvent.events[i].media());
87             case FilterEventType::RECORD:
88                 break;
89             case FilterEventType::MMTPRECORD:
90                 break;
91             case FilterEventType::DOWNLOAD:
92                 break;
93             default:
94                 break;
95         }
96         // EXPECT_TRUE(mDataLength == goldenDataOutputBuffer.size()) << "buffer size does not
97         // match";
98 
99         mDataOutputBuffer.resize(mDataLength);
100         result = mFilterMQ->read(mDataOutputBuffer.data(), mDataLength);
101         EXPECT_TRUE(result) << "can't read from Filter MQ";
102 
103         /*for (int i = 0; i < mDataLength; i++) {
104             EXPECT_TRUE(goldenDataOutputBuffer[i] == mDataOutputBuffer[i]) << "data does not match";
105         }*/
106     }
107     mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
108     return result;
109 }
110 
dumpAvData(DemuxFilterMediaEvent event)111 bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
112     uint32_t length = event.dataLength;
113     uint64_t dataId = event.avDataId;
114     // read data from buffer pointed by a handle
115     hidl_handle handle = event.avMemory;
116 
117     int av_fd = handle.getNativeHandle()->data[0];
118     uint8_t* buffer = static_cast<uint8_t*>(
119             mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0 /*offset*/));
120     if (buffer == MAP_FAILED) {
121         ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
122         return false;
123     }
124     uint8_t output[length + 1];
125     memcpy(output, buffer, length);
126     // print buffer and check with golden output.
127     EXPECT_TRUE(mFilter->releaseAvHandle(handle, dataId) == Result::SUCCESS);
128     return true;
129 }
130 
openFilterInDemux(DemuxFilterType type,uint32_t bufferSize)131 AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, uint32_t bufferSize) {
132     Result status;
133     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
134 
135     // Create demux callback
136     mFilterCallback = new FilterCallback();
137 
138     // Add filter to the local demux
139     mDemux->openFilter(type, bufferSize, mFilterCallback,
140                        [&](Result result, const sp<IFilter>& filter) {
141                            mFilter = filter;
142                            status = result;
143                        });
144 
145     if (status == Result::SUCCESS) {
146         mFilterCallback->setFilterEventType(getFilterEventType(type));
147     }
148 
149     return AssertionResult(status == Result::SUCCESS);
150 }
151 
openTimeFilterInDemux()152 AssertionResult FilterTests::openTimeFilterInDemux() {
153     if (!mDemux) {
154         ALOGW("[vts] Test with openDemux first.");
155         return failure();
156     }
157 
158     // Add time filter to the local demux
159     Result status;
160     mDemux->openTimeFilter([&](Result result, const sp<ITimeFilter>& filter) {
161         mTimeFilter = filter;
162         status = result;
163     });
164 
165     return AssertionResult(status == Result::SUCCESS);
166 }
167 
setTimeStamp(uint64_t timeStamp)168 AssertionResult FilterTests::setTimeStamp(uint64_t timeStamp) {
169     if (!mTimeFilter) {
170         ALOGW("[vts] Test with openTimeFilterInDemux first.");
171         return failure();
172     }
173 
174     mBeginTimeStamp = timeStamp;
175     return AssertionResult(mTimeFilter->setTimeStamp(timeStamp) == Result::SUCCESS);
176 }
177 
getTimeStamp()178 AssertionResult FilterTests::getTimeStamp() {
179     if (!mTimeFilter) {
180         ALOGW("[vts] Test with openTimeFilterInDemux first.");
181         return failure();
182     }
183 
184     Result status;
185     mTimeFilter->getTimeStamp([&](Result result, uint64_t /*timeStamp*/) { status = result; });
186 
187     return AssertionResult(status == Result::SUCCESS);
188 }
189 
getNewlyOpenedFilterId(uint32_t & filterId)190 AssertionResult FilterTests::getNewlyOpenedFilterId(uint32_t& filterId) {
191     Result status;
192     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
193     EXPECT_TRUE(mFilter) << "Test with openFilterInDemux first.";
194     EXPECT_TRUE(mFilterCallback) << "Test with openFilterInDemux first.";
195 
196     mFilter->getId([&](Result result, uint32_t filterId) {
197         mFilterId = filterId;
198         status = result;
199     });
200 
201     if (status == Result::SUCCESS) {
202         mFilterCallback->setFilterId(mFilterId);
203         mFilterCallback->setFilterInterface(mFilter);
204         mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
205         mFilters[mFilterId] = mFilter;
206         mFilterCallbacks[mFilterId] = mFilterCallback;
207         filterId = mFilterId;
208     }
209 
210     return AssertionResult(status == Result::SUCCESS);
211 }
212 
configFilter(DemuxFilterSettings setting,uint32_t filterId)213 AssertionResult FilterTests::configFilter(DemuxFilterSettings setting, uint32_t filterId) {
214     Result status;
215     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
216     status = mFilters[filterId]->configure(setting);
217 
218     return AssertionResult(status == Result::SUCCESS);
219 }
220 
getFilterMQDescriptor(uint32_t filterId)221 AssertionResult FilterTests::getFilterMQDescriptor(uint32_t filterId) {
222     Result status;
223     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
224     EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
225 
226     mFilter->getQueueDesc([&](Result result, const MQDesc& filterMQDesc) {
227         mFilterMQDescriptor = filterMQDesc;
228         status = result;
229     });
230 
231     if (status == Result::SUCCESS) {
232         mFilterCallbacks[filterId]->updateFilterMQ(mFilterMQDescriptor);
233     }
234 
235     return AssertionResult(status == Result::SUCCESS);
236 }
237 
setFilterDataSource(uint32_t sourceFilterId,uint32_t sinkFilterId)238 AssertionResult FilterTests::setFilterDataSource(uint32_t sourceFilterId, uint32_t sinkFilterId) {
239     if (!mFilters[sourceFilterId] || !mFilters[sinkFilterId]) {
240         ALOGE("[vts] setFilterDataSource filter not opened.");
241         return failure();
242     }
243 
244     auto status = mFilters[sinkFilterId]->setDataSource(mFilters[sourceFilterId]);
245     return AssertionResult(status == Result::SUCCESS);
246 }
247 
setFilterDataSourceToDemux(uint32_t filterId)248 AssertionResult FilterTests::setFilterDataSourceToDemux(uint32_t filterId) {
249     if (!mFilters[filterId]) {
250         ALOGE("[vts] setFilterDataSourceToDemux filter not opened.");
251         return failure();
252     }
253 
254     auto status = mFilters[filterId]->setDataSource(NULL);
255     return AssertionResult(status == Result::SUCCESS);
256 }
257 
startFilter(uint32_t filterId)258 AssertionResult FilterTests::startFilter(uint32_t filterId) {
259     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
260     Result status = mFilters[filterId]->start();
261     return AssertionResult(status == Result::SUCCESS);
262 }
263 
stopFilter(uint32_t filterId)264 AssertionResult FilterTests::stopFilter(uint32_t filterId) {
265     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
266     Result status = mFilters[filterId]->stop();
267     return AssertionResult(status == Result::SUCCESS);
268 }
269 
clearTimeStamp()270 AssertionResult FilterTests::clearTimeStamp() {
271     if (!mTimeFilter) {
272         ALOGW("[vts] Test with openTimeFilterInDemux first.");
273         return failure();
274     }
275 
276     return AssertionResult(mTimeFilter->clearTimeStamp() == Result::SUCCESS);
277 }
278 
closeFilter(uint32_t filterId)279 AssertionResult FilterTests::closeFilter(uint32_t filterId) {
280     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
281     Result status = mFilters[filterId]->close();
282     if (status == Result::SUCCESS) {
283         for (int i = 0; i < mUsedFilterIds.size(); i++) {
284             if (mUsedFilterIds[i] == filterId) {
285                 mUsedFilterIds.erase(mUsedFilterIds.begin() + i);
286                 break;
287             }
288         }
289         mFilterCallbacks.erase(filterId);
290         mFilters.erase(filterId);
291     }
292     return AssertionResult(status == Result::SUCCESS);
293 }
294 
closeTimeFilter()295 AssertionResult FilterTests::closeTimeFilter() {
296     if (!mTimeFilter) {
297         ALOGW("[vts] Test with openTimeFilterInDemux first.");
298         return failure();
299     }
300 
301     return AssertionResult(mTimeFilter->close() == Result::SUCCESS);
302 }
303