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 (auto event : filterEvent.events) {
78         switch (event.getDiscriminator()) {
79             case DemuxFilterEvent::Event::hidl_discriminator::section:
80                 mDataLength = event.section().dataLength;
81                 break;
82             case DemuxFilterEvent::Event::hidl_discriminator::pes:
83                 mDataLength = event.pes().dataLength;
84                 break;
85             case DemuxFilterEvent::Event::hidl_discriminator::media:
86                 return dumpAvData(event.media());
87             case DemuxFilterEvent::Event::hidl_discriminator::tsRecord:
88                 return readRecordData(event.tsRecord());
89             default:
90                 continue;
91         }
92         // EXPECT_TRUE(mDataLength == goldenDataOutputBuffer.size()) << "buffer size does not
93         // match";
94         if (mFilterMQ != NULL) {
95             mDataOutputBuffer.resize(mDataLength);
96             result = mFilterMQ->read(mDataOutputBuffer.data(), mDataLength);
97             EXPECT_TRUE(result) << "can't read from Filter MQ";
98         }
99 
100         /*for (int i = 0; i < mDataLength; i++) {
101             EXPECT_TRUE(goldenDataOutputBuffer[i] == mDataOutputBuffer[i]) << "data does not match";
102         }*/
103     }
104     if (mFilterMQ != NULL) {
105         mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
106     }
107     return result;
108 }
109 
dumpAvData(DemuxFilterMediaEvent event)110 bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
111     uint32_t length = event.dataLength;
112     uint64_t dataId = event.avDataId;
113     // read data from buffer pointed by a handle
114     hidl_handle handle = event.avMemory;
115 
116     int av_fd = handle.getNativeHandle()->data[0];
117     uint8_t* buffer = static_cast<uint8_t*>(
118             mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0 /*offset*/));
119     if (buffer == MAP_FAILED) {
120         ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
121         return false;
122     }
123     uint8_t output[length + 1];
124     memcpy(output, buffer, length);
125     // print buffer and check with golden output.
126     EXPECT_TRUE(mFilter->releaseAvHandle(handle, dataId) == Result::SUCCESS);
127     return true;
128 }
129 
readRecordData(DemuxFilterTsRecordEvent event)130 bool FilterCallback::readRecordData(DemuxFilterTsRecordEvent event) {
131     ALOGD("[vts] got DemuxFilterTsRecordEvent with pid=%d.", event.pid.tPid());
132     return true;
133 }
134 
openFilterInDemux(DemuxFilterType type,uint32_t bufferSize)135 AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, uint32_t bufferSize) {
136     Result status;
137     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
138 
139     // Create demux callback
140     mFilterCallback = new FilterCallback();
141 
142     // Add filter to the local demux
143     mDemux->openFilter(type, bufferSize, mFilterCallback,
144                        [&](Result result, const sp<IFilter>& filter) {
145                            mFilter = filter;
146                            status = result;
147                        });
148     return AssertionResult(status == Result::SUCCESS);
149 }
150 
openTimeFilterInDemux()151 AssertionResult FilterTests::openTimeFilterInDemux() {
152     if (!mDemux) {
153         ALOGW("[vts] Test with openDemux first.");
154         return failure();
155     }
156 
157     // Add time filter to the local demux
158     Result status;
159     mDemux->openTimeFilter([&](Result result, const sp<ITimeFilter>& filter) {
160         mTimeFilter = filter;
161         status = result;
162     });
163 
164     return AssertionResult(status == Result::SUCCESS);
165 }
166 
setTimeStamp(uint64_t timeStamp)167 AssertionResult FilterTests::setTimeStamp(uint64_t timeStamp) {
168     if (!mTimeFilter) {
169         ALOGW("[vts] Test with openTimeFilterInDemux first.");
170         return failure();
171     }
172 
173     mBeginTimeStamp = timeStamp;
174     return AssertionResult(mTimeFilter->setTimeStamp(timeStamp) == Result::SUCCESS);
175 }
176 
getTimeStamp()177 AssertionResult FilterTests::getTimeStamp() {
178     if (!mTimeFilter) {
179         ALOGW("[vts] Test with openTimeFilterInDemux first.");
180         return failure();
181     }
182 
183     Result status;
184     mTimeFilter->getTimeStamp([&](Result result, uint64_t /*timeStamp*/) { status = result; });
185 
186     return AssertionResult(status == Result::SUCCESS);
187 }
188 
getNewlyOpenedFilterId(uint32_t & filterId)189 AssertionResult FilterTests::getNewlyOpenedFilterId(uint32_t& filterId) {
190     Result status;
191     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
192     EXPECT_TRUE(mFilter) << "Test with openFilterInDemux first.";
193     EXPECT_TRUE(mFilterCallback) << "Test with openFilterInDemux first.";
194 
195     mFilter->getId([&](Result result, uint32_t filterId) {
196         mFilterId = filterId;
197         status = result;
198     });
199 
200     if (status == Result::SUCCESS) {
201         mFilterCallback->setFilterId(mFilterId);
202         mFilterCallback->setFilterInterface(mFilter);
203         mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
204         mFilters[mFilterId] = mFilter;
205         mFilterCallbacks[mFilterId] = mFilterCallback;
206         filterId = mFilterId;
207     }
208 
209     return AssertionResult(status == Result::SUCCESS);
210 }
211 
configFilter(DemuxFilterSettings setting,uint32_t filterId)212 AssertionResult FilterTests::configFilter(DemuxFilterSettings setting, uint32_t filterId) {
213     Result status;
214     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
215     status = mFilters[filterId]->configure(setting);
216 
217     return AssertionResult(status == Result::SUCCESS);
218 }
219 
getFilterMQDescriptor(uint32_t filterId,bool getMqDesc)220 AssertionResult FilterTests::getFilterMQDescriptor(uint32_t filterId, bool getMqDesc) {
221     if (!getMqDesc) {
222         ALOGE("[vts] Filter does not need FMQ.");
223         return success();
224     }
225     Result status;
226     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
227     EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
228 
229     mFilter->getQueueDesc([&](Result result, const MQDesc& filterMQDesc) {
230         mFilterMQDescriptor = filterMQDesc;
231         status = result;
232     });
233 
234     if (status == Result::SUCCESS) {
235         mFilterCallbacks[filterId]->updateFilterMQ(mFilterMQDescriptor);
236     }
237 
238     return AssertionResult(status == Result::SUCCESS);
239 }
240 
setFilterDataSource(uint32_t sourceFilterId,uint32_t sinkFilterId)241 AssertionResult FilterTests::setFilterDataSource(uint32_t sourceFilterId, uint32_t sinkFilterId) {
242     if (!mFilters[sourceFilterId] || !mFilters[sinkFilterId]) {
243         ALOGE("[vts] setFilterDataSource filter not opened.");
244         return failure();
245     }
246 
247     auto status = mFilters[sinkFilterId]->setDataSource(mFilters[sourceFilterId]);
248     return AssertionResult(status == Result::SUCCESS);
249 }
250 
setFilterDataSourceToDemux(uint32_t filterId)251 AssertionResult FilterTests::setFilterDataSourceToDemux(uint32_t filterId) {
252     if (!mFilters[filterId]) {
253         ALOGE("[vts] setFilterDataSourceToDemux filter not opened.");
254         return failure();
255     }
256 
257     auto status = mFilters[filterId]->setDataSource(NULL);
258     return AssertionResult(status == Result::SUCCESS);
259 }
260 
startFilter(uint32_t filterId)261 AssertionResult FilterTests::startFilter(uint32_t filterId) {
262     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
263     Result status = mFilters[filterId]->start();
264     return AssertionResult(status == Result::SUCCESS);
265 }
266 
stopFilter(uint32_t filterId)267 AssertionResult FilterTests::stopFilter(uint32_t filterId) {
268     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
269     Result status = mFilters[filterId]->stop();
270     return AssertionResult(status == Result::SUCCESS);
271 }
272 
clearTimeStamp()273 AssertionResult FilterTests::clearTimeStamp() {
274     if (!mTimeFilter) {
275         ALOGW("[vts] Test with openTimeFilterInDemux first.");
276         return failure();
277     }
278 
279     return AssertionResult(mTimeFilter->clearTimeStamp() == Result::SUCCESS);
280 }
281 
closeFilter(uint32_t filterId)282 AssertionResult FilterTests::closeFilter(uint32_t filterId) {
283     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
284     Result status = mFilters[filterId]->close();
285     for (int i = 0; i < mUsedFilterIds.size(); i++) {
286         if (mUsedFilterIds[i] == filterId) {
287             mUsedFilterIds.erase(mUsedFilterIds.begin() + i);
288             break;
289         }
290     }
291     mFilterCallbacks.erase(filterId);
292     mFilters.erase(filterId);
293     return AssertionResult(status == Result::SUCCESS);
294 }
295 
closeTimeFilter()296 AssertionResult FilterTests::closeTimeFilter() {
297     if (!mTimeFilter) {
298         ALOGW("[vts] Test with openTimeFilterInDemux first.");
299         return failure();
300     }
301 
302     return AssertionResult(mTimeFilter->close() == Result::SUCCESS);
303 }
304