• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 
19 #include <inttypes.h>
20 #include <algorithm>
21 
22 #include <aidl/android/hardware/tv/tuner/DemuxFilterMonitorEventType.h>
23 #include <aidlcommonsupport/NativeHandle.h>
24 
25 using ::aidl::android::hardware::common::NativeHandle;
26 
onFilterEvent(const vector<DemuxFilterEvent> & events)27 ::ndk::ScopedAStatus FilterCallback::onFilterEvent(const vector<DemuxFilterEvent>& events) {
28     android::Mutex::Autolock autoLock(mMsgLock);
29     // Temprarily we treat the first coming back filter data on the matching pid a success
30     // once all of the MQ are cleared, means we got all the expected output
31     readFilterEventsData(events);
32     mPidFilterOutputCount++;
33     mMsgCondition.signal();
34 
35     for (auto it = mFilterCallbackVerifiers.begin(); it != mFilterCallbackVerifiers.end();) {
36         auto& [verifier, promise] = *it;
37         if (verifier(events)) {
38             promise.set_value();
39             it = mFilterCallbackVerifiers.erase(it);
40         } else {
41             ++it;
42         }
43     };
44 
45     return ::ndk::ScopedAStatus::ok();
46 }
47 
verifyFilterCallback(FilterCallbackVerifier && verifier)48 std::future<void> FilterCallback::verifyFilterCallback(FilterCallbackVerifier&& verifier) {
49     std::promise<void> promise;
50     auto future = promise.get_future();
51     mFilterCallbackVerifiers.emplace_back(std::move(verifier), std::move(promise));
52     return future;
53 }
54 
testFilterDataOutput()55 void FilterCallback::testFilterDataOutput() {
56     android::Mutex::Autolock autoLock(mMsgLock);
57     while (mPidFilterOutputCount < 1) {
58         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
59             EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
60             return;
61         }
62     }
63     mPidFilterOutputCount = 0;
64     ALOGW("[vts] pass and stop");
65 }
66 
testFilterScramblingEvent()67 void FilterCallback::testFilterScramblingEvent() {
68     android::Mutex::Autolock autoLock(mMsgLock);
69     while (mScramblingStatusEvent < 1) {
70         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
71             EXPECT_TRUE(false) << "scrambling event does not output within timeout";
72             return;
73         }
74     }
75     mScramblingStatusEvent = 0;
76     ALOGW("[vts] pass and stop");
77 }
78 
testFilterIpCidEvent()79 void FilterCallback::testFilterIpCidEvent() {
80     android::Mutex::Autolock autoLock(mMsgLock);
81     while (mIpCidEvent < 1) {
82         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
83             EXPECT_TRUE(false) << "ip cid change event does not output within timeout";
84             return;
85         }
86     }
87     mIpCidEvent = 0;
88     ALOGW("[vts] pass and stop");
89 }
90 
testStartIdAfterReconfigure()91 void FilterCallback::testStartIdAfterReconfigure() {
92     android::Mutex::Autolock autoLock(mMsgLock);
93     while (!mStartIdReceived) {
94         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
95             EXPECT_TRUE(false) << "does not receive start id within timeout";
96             return;
97         }
98     }
99     mStartIdReceived = false;
100     ALOGW("[vts] pass and stop");
101 }
102 
readFilterEventsData(const vector<DemuxFilterEvent> & events)103 void FilterCallback::readFilterEventsData(const vector<DemuxFilterEvent>& events) {
104     ALOGW("[vts] reading filter event");
105     // todo separate filter handlers
106     for (int i = 0; i < events.size(); i++) {
107         switch (events[i].getTag()) {
108             case DemuxFilterEvent::Tag::media:
109                 ALOGD("[vts] Media filter event, avMemHandle numFds=%zu.",
110                       events[i].get<DemuxFilterEvent::Tag::media>().avMemory.fds.size());
111                 dumpAvData(events[i].get<DemuxFilterEvent::Tag::media>());
112                 break;
113             case DemuxFilterEvent::Tag::tsRecord:
114                 ALOGD("[vts] TS record filter event, pts=%" PRIu64 ", firstMbInSlice=%d",
115                       events[i].get<DemuxFilterEvent::Tag::tsRecord>().pts,
116                       events[i].get<DemuxFilterEvent::Tag::tsRecord>().firstMbInSlice);
117                 break;
118             case DemuxFilterEvent::Tag::mmtpRecord:
119                 ALOGD("[vts] MMTP record filter event, pts=%" PRIu64
120                       ", firstMbInSlice=%d, mpuSequenceNumber=%d, tsIndexMask=%d",
121                       events[i].get<DemuxFilterEvent::Tag::mmtpRecord>().pts,
122                       events[i].get<DemuxFilterEvent::Tag::mmtpRecord>().firstMbInSlice,
123                       events[i].get<DemuxFilterEvent::Tag::mmtpRecord>().mpuSequenceNumber,
124                       events[i].get<DemuxFilterEvent::Tag::mmtpRecord>().tsIndexMask);
125                 break;
126             case DemuxFilterEvent::Tag::monitorEvent:
127                 switch (events[i].get<DemuxFilterEvent::Tag::monitorEvent>().getTag()) {
128                     case DemuxFilterMonitorEvent::Tag::scramblingStatus:
129                         mScramblingStatusEvent++;
130                         break;
131                     case DemuxFilterMonitorEvent::Tag::cid:
132                         mIpCidEvent++;
133                         break;
134                     default:
135                         break;
136                 }
137                 break;
138             case DemuxFilterEvent::Tag::startId:
139                 ALOGD("[vts] Restart filter event, startId=%d",
140                       events[i].get<DemuxFilterEvent::Tag::startId>());
141                 mStartIdReceived = true;
142                 break;
143             default:
144                 break;
145         }
146     }
147 }
148 
dumpAvData(const DemuxFilterMediaEvent & event)149 bool FilterCallback::dumpAvData(const DemuxFilterMediaEvent& event) {
150     int64_t length = event.dataLength;
151     int64_t offset = event.offset;
152     int av_fd;
153     // read data from buffer pointed by a handle
154     if (event.avMemory.fds.size() == 0) {
155         if (mAvSharedHandle == nullptr) {
156             return false;
157         }
158         av_fd = mAvSharedHandle->data[0];
159     } else {
160         av_fd = event.avMemory.fds[0].get();
161     }
162     uint8_t* buffer = static_cast<uint8_t*>(
163             mmap(NULL, length + offset, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0));
164     if (buffer == MAP_FAILED) {
165         ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
166         return false;
167     }
168     uint8_t output[length + 1];
169     memcpy(output, buffer + offset, length);
170     // print buffer and check with golden output.
171     return true;
172 }
173 
openFilterInDemux(DemuxFilterType type,int32_t bufferSize)174 AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, int32_t bufferSize) {
175     ndk::ScopedAStatus status;
176     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
177 
178     // Create demux callback
179     mFilterCallback = ndk::SharedRefBase::make<FilterCallback>();
180 
181     // Add filter to the local demux
182     status = mDemux->openFilter(type, bufferSize, mFilterCallback, &mFilter);
183 
184     return AssertionResult(status.isOk());
185 }
186 
getNewlyOpenedFilterId_64bit(int64_t & filterId)187 AssertionResult FilterTests::getNewlyOpenedFilterId_64bit(int64_t& filterId) {
188     ndk::ScopedAStatus status;
189     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
190     EXPECT_TRUE(mFilter) << "Test with openFilterInDemux first.";
191     EXPECT_TRUE(mFilterCallback) << "Test with openFilterInDemux first.";
192 
193     status = mFilter->getId64Bit(&mFilterId);
194     if (status.isOk()) {
195         mFilterCallback->setFilterId(mFilterId);
196         mFilterCallback->setFilterInterface(mFilter);
197         mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
198         mFilters[mFilterId] = mFilter;
199         mFilterCallbacks[mFilterId] = mFilterCallback;
200         filterId = mFilterId;
201 
202         // Check getId() too.
203         int32_t filterId32Bit;
204         status = mFilter->getId(&filterId32Bit);
205     }
206 
207     return AssertionResult(status.isOk());
208 }
209 
getSharedAvMemoryHandle(int64_t filterId)210 AssertionResult FilterTests::getSharedAvMemoryHandle(int64_t filterId) {
211     EXPECT_TRUE(mFilters[filterId]) << "Open media filter first.";
212     NativeHandle avMemory;
213     int64_t avMemSize;
214     ndk::ScopedAStatus status = mFilters[filterId]->getAvSharedHandle(&avMemory, &avMemSize);
215     if (status.isOk()) {
216         mAvSharedHandle = android::dupFromAidl(avMemory);
217         mFilterCallbacks[mFilterId]->setSharedHandle(mAvSharedHandle);
218         mFilterCallbacks[mFilterId]->setMemSize(avMemSize);
219     }
220     return AssertionResult(status.isOk());
221 }
222 
releaseShareAvHandle(int64_t filterId)223 AssertionResult FilterTests::releaseShareAvHandle(int64_t filterId) {
224     ndk::ScopedAStatus status;
225     EXPECT_TRUE(mFilters[filterId]) << "Open media filter first.";
226     EXPECT_TRUE(mAvSharedHandle) << "No shared av handle to release.";
227     status = mFilters[filterId]->releaseAvHandle(::android::makeToAidl(mAvSharedHandle),
228                                                  0 /*dataId*/);
229     native_handle_close(mAvSharedHandle);
230     native_handle_delete(mAvSharedHandle);
231     mAvSharedHandle = nullptr;
232 
233     return AssertionResult(status.isOk());
234 }
235 
configFilter(DemuxFilterSettings setting,int64_t filterId)236 AssertionResult FilterTests::configFilter(DemuxFilterSettings setting, int64_t filterId) {
237     ndk::ScopedAStatus status;
238     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
239     status = mFilters[filterId]->configure(setting);
240 
241     return AssertionResult(status.isOk());
242 }
243 
configAvFilterStreamType(AvStreamType type,int64_t filterId)244 AssertionResult FilterTests::configAvFilterStreamType(AvStreamType type, int64_t filterId) {
245     ndk::ScopedAStatus status;
246     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
247 
248     status = mFilters[filterId]->configureAvStreamType(type);
249     return AssertionResult(status.isOk());
250 }
251 
configIpFilterCid(int32_t ipCid,int64_t filterId)252 AssertionResult FilterTests::configIpFilterCid(int32_t ipCid, int64_t filterId) {
253     ndk::ScopedAStatus status;
254     EXPECT_TRUE(mFilters[filterId]) << "Open Ip filter first.";
255 
256     status = mFilters[filterId]->configureIpCid(ipCid);
257     return AssertionResult(status.isOk());
258 }
259 
getFilterMQDescriptor(int64_t filterId,bool getMqDesc)260 AssertionResult FilterTests::getFilterMQDescriptor(int64_t filterId, bool getMqDesc) {
261     if (!getMqDesc) {
262         ALOGE("[vts] Filter does not need FMQ.");
263         return success();
264     }
265     ndk::ScopedAStatus status;
266     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
267     EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
268 
269     status = mFilters[filterId]->getQueueDesc(&mFilterMQDescriptor);
270     return AssertionResult(status.isOk());
271 }
272 
startFilter(int64_t filterId)273 AssertionResult FilterTests::startFilter(int64_t filterId) {
274     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
275 
276     ndk::ScopedAStatus status = mFilters[filterId]->start();
277     return AssertionResult(status.isOk());
278 }
279 
stopFilter(int64_t filterId)280 AssertionResult FilterTests::stopFilter(int64_t filterId) {
281     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
282 
283     ndk::ScopedAStatus status = mFilters[filterId]->stop();
284     return AssertionResult(status.isOk());
285 }
286 
closeFilter(int64_t filterId)287 AssertionResult FilterTests::closeFilter(int64_t filterId) {
288     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
289     ndk::ScopedAStatus status = mFilters[filterId]->close();
290     if (status.isOk()) {
291         for (int i = 0; i < mUsedFilterIds.size(); i++) {
292             if (mUsedFilterIds[i] == filterId) {
293                 mUsedFilterIds.erase(mUsedFilterIds.begin() + i);
294                 break;
295             }
296         }
297         mFilterCallbacks.erase(filterId);
298         mFilters.erase(filterId);
299     }
300     return AssertionResult(status.isOk());
301 }
302 
configureMonitorEvent(int64_t filterId,int32_t monitorEventTypes)303 AssertionResult FilterTests::configureMonitorEvent(int64_t filterId, int32_t monitorEventTypes) {
304     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
305     ndk::ScopedAStatus status;
306 
307     status = mFilters[filterId]->configureMonitorEvent(monitorEventTypes);
308     if (monitorEventTypes & static_cast<int32_t>(DemuxFilterMonitorEventType::SCRAMBLING_STATUS)) {
309         mFilterCallbacks[filterId]->testFilterScramblingEvent();
310     }
311     if (monitorEventTypes & static_cast<int32_t>(DemuxFilterMonitorEventType::IP_CID_CHANGE)) {
312         mFilterCallbacks[filterId]->testFilterIpCidEvent();
313     }
314     return AssertionResult(status.isOk());
315 }
316 
startIdTest(int64_t filterId)317 AssertionResult FilterTests::startIdTest(int64_t filterId) {
318     EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
319     mFilterCallbacks[filterId]->testStartIdAfterReconfigure();
320     return AssertionResult(true);
321 }
322 
openTimeFilterInDemux()323 AssertionResult FilterTests::openTimeFilterInDemux() {
324     if (!mDemux) {
325         ALOGW("[vts] Test with openDemux first.");
326         return failure();
327     }
328 
329     // Add time filter to the local demux
330     auto status = mDemux->openTimeFilter(&mTimeFilter);
331     return AssertionResult(status.isOk());
332 }
333 
setTimeStamp(int64_t timeStamp)334 AssertionResult FilterTests::setTimeStamp(int64_t timeStamp) {
335     if (!mTimeFilter) {
336         ALOGW("[vts] Test with openTimeFilterInDemux first.");
337         return failure();
338     }
339 
340     mBeginTimeStamp = timeStamp;
341     return AssertionResult(mTimeFilter->setTimeStamp(timeStamp).isOk());
342 }
343 
getTimeStamp()344 AssertionResult FilterTests::getTimeStamp() {
345     if (!mTimeFilter) {
346         ALOGW("[vts] Test with openTimeFilterInDemux first.");
347         return failure();
348     }
349 
350     int64_t timeStamp;
351     auto status = mTimeFilter->getTimeStamp(&timeStamp);
352     return AssertionResult(status.isOk());
353 }
354 
setFilterDataSource(int64_t sourceFilterId,int64_t sinkFilterId)355 AssertionResult FilterTests::setFilterDataSource(int64_t sourceFilterId, int64_t sinkFilterId) {
356     if (!mFilters[sourceFilterId] || !mFilters[sinkFilterId]) {
357         ALOGE("[vts] setFilterDataSource filter not opened.");
358         return failure();
359     }
360 
361     auto status = mFilters[sinkFilterId]->setDataSource(mFilters[sourceFilterId]);
362     return AssertionResult(status.isOk());
363 }
364 
setFilterDataSourceToDemux(int64_t filterId)365 AssertionResult FilterTests::setFilterDataSourceToDemux(int64_t filterId) {
366     if (!mFilters[filterId]) {
367         ALOGE("[vts] setFilterDataSourceToDemux filter not opened.");
368         return failure();
369     }
370 
371     auto status = mFilters[filterId]->setDataSource(nullptr);
372     return AssertionResult(status.isOk());
373 }
374 
clearTimeStamp()375 AssertionResult FilterTests::clearTimeStamp() {
376     if (!mTimeFilter) {
377         ALOGW("[vts] Test with openTimeFilterInDemux first.");
378         return failure();
379     }
380 
381     return AssertionResult(mTimeFilter->clearTimeStamp().isOk());
382 }
383 
closeTimeFilter()384 AssertionResult FilterTests::closeTimeFilter() {
385     if (!mTimeFilter) {
386         ALOGW("[vts] Test with openTimeFilterInDemux first.");
387         return failure();
388     }
389 
390     return AssertionResult(mTimeFilter->close().isOk());
391 }
392