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 
testFilterDataOutput()19 void FilterCallback::testFilterDataOutput() {
20     android::Mutex::Autolock autoLock(mMsgLock);
21     while (mPidFilterOutputCount < 1) {
22         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
23             EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
24             return;
25         }
26     }
27     mPidFilterOutputCount = 0;
28     ALOGW("[vts] pass and stop");
29 }
30 
testFilterScramblingEvent()31 void FilterCallback::testFilterScramblingEvent() {
32     android::Mutex::Autolock autoLock(mMsgLock);
33     while (mScramblingStatusEvent < 1) {
34         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
35             EXPECT_TRUE(false) << "scrambling event does not output within timeout";
36             return;
37         }
38     }
39     mScramblingStatusEvent = 0;
40     ALOGW("[vts] pass and stop");
41 }
42 
testFilterIpCidEvent()43 void FilterCallback::testFilterIpCidEvent() {
44     android::Mutex::Autolock autoLock(mMsgLock);
45     while (mIpCidEvent < 1) {
46         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
47             EXPECT_TRUE(false) << "ip cid change event does not output within timeout";
48             return;
49         }
50     }
51     mIpCidEvent = 0;
52     ALOGW("[vts] pass and stop");
53 }
54 
testStartIdAfterReconfigure()55 void FilterCallback::testStartIdAfterReconfigure() {
56     android::Mutex::Autolock autoLock(mMsgLock);
57     while (!mStartIdReceived) {
58         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
59             EXPECT_TRUE(false) << "does not receive start id within timeout";
60             return;
61         }
62     }
63     mStartIdReceived = false;
64     ALOGW("[vts] pass and stop");
65 }
66 
readFilterEventData()67 void FilterCallback::readFilterEventData() {
68     ALOGW("[vts] reading filter event");
69     // todo separate filter handlers
70     for (int i = 0; i < mFilterEvent.events.size(); i++) {
71         auto event = mFilterEvent.events[i];
72         switch (event.getDiscriminator()) {
73             case DemuxFilterEvent::Event::hidl_discriminator::media:
74                 ALOGD("[vts] Media filter event, avMemHandle numFds=%d.",
75                       event.media().avMemory.getNativeHandle()->numFds);
76                 dumpAvData(event.media());
77                 break;
78             default:
79                 break;
80         }
81     }
82     for (int i = 0; i < mFilterEventExt.events.size(); i++) {
83         auto eventExt = mFilterEventExt.events[i];
84         switch (eventExt.getDiscriminator()) {
85             case DemuxFilterEventExt::Event::hidl_discriminator::tsRecord:
86                 ALOGD("[vts] Extended TS record filter event, pts=%" PRIu64 ", firstMbInSlice=%d",
87                       eventExt.tsRecord().pts, eventExt.tsRecord().firstMbInSlice);
88                 break;
89             case DemuxFilterEventExt::Event::hidl_discriminator::mmtpRecord:
90                 ALOGD("[vts] Extended MMTP record filter event, pts=%" PRIu64
91                       ", firstMbInSlice=%d, mpuSequenceNumber=%d, tsIndexMask=%d",
92                       eventExt.mmtpRecord().pts, eventExt.mmtpRecord().firstMbInSlice,
93                       eventExt.mmtpRecord().mpuSequenceNumber, eventExt.mmtpRecord().tsIndexMask);
94                 break;
95             case DemuxFilterEventExt::Event::hidl_discriminator::monitorEvent:
96                 switch (eventExt.monitorEvent().getDiscriminator()) {
97                     case DemuxFilterMonitorEvent::hidl_discriminator::scramblingStatus:
98                         mScramblingStatusEvent++;
99                         break;
100                     case DemuxFilterMonitorEvent::hidl_discriminator::cid:
101                         mIpCidEvent++;
102                         break;
103                     default:
104                         break;
105                 }
106                 break;
107             case DemuxFilterEventExt::Event::hidl_discriminator::startId:
108                 ALOGD("[vts] Extended restart filter event, startId=%d", eventExt.startId());
109                 mStartIdReceived = true;
110                 break;
111             default:
112                 break;
113         }
114     }
115 }
116 
dumpAvData(DemuxFilterMediaEvent event)117 bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
118     uint32_t length = event.dataLength;
119     uint32_t offset = event.offset;
120     // read data from buffer pointed by a handle
121     hidl_handle handle = event.avMemory;
122     if (handle.getNativeHandle()->numFds == 0) {
123         if (mAvSharedHandle == NULL) {
124             return false;
125         }
126         handle = mAvSharedHandle;
127     }
128 
129     int av_fd = handle.getNativeHandle()->data[0];
130     uint8_t* buffer = static_cast<uint8_t*>(
131             mmap(NULL, length + offset, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0));
132     if (buffer == MAP_FAILED) {
133         ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
134         return false;
135     }
136     uint8_t output[length + 1];
137     memcpy(output, buffer + offset, length);
138     // print buffer and check with golden output.
139     ::close(av_fd);
140     return true;
141 }
142 
openFilterInDemux(DemuxFilterType type,uint32_t bufferSize)143 AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, uint32_t bufferSize) {
144     Result status;
145     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
146 
147     // Create demux callback
148     mFilterCallback = new FilterCallback();
149 
150     // Add filter to the local demux
151     mDemux->openFilter(type, bufferSize, mFilterCallback,
152                        [&](Result result, const sp<IFilter>& filter) {
153                            mFilter = filter;
154                            status = result;
155                        });
156 
157     return AssertionResult(status == Result::SUCCESS);
158 }
159 
getNewlyOpenedFilterId_64bit(uint64_t & filterId)160 AssertionResult FilterTests::getNewlyOpenedFilterId_64bit(uint64_t& filterId) {
161     Result status;
162     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
163     EXPECT_TRUE(mFilter) << "Test with openFilterInDemux first.";
164     EXPECT_TRUE(mFilterCallback) << "Test with openFilterInDemux first.";
165 
166     sp<android::hardware::tv::tuner::V1_1::IFilter> filter_v1_1 =
167             android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilter);
168     if (filter_v1_1 != NULL) {
169         filter_v1_1->getId64Bit([&](Result result, uint64_t filterId) {
170             mFilterId = filterId;
171             status = result;
172         });
173     } else {
174         ALOGW("[vts] Can't cast IFilter into v1_1.");
175         return failure();
176     }
177 
178     if (status == Result::SUCCESS) {
179         mFilterCallback->setFilterId(mFilterId);
180         mFilterCallback->setFilterInterface(mFilter);
181         mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
182         mFilters[mFilterId] = mFilter;
183         mFilterCallbacks[mFilterId] = mFilterCallback;
184         filterId = mFilterId;
185     }
186 
187     return AssertionResult(status == Result::SUCCESS);
188 }
189 
getSharedAvMemoryHandle(uint64_t filterId)190 AssertionResult FilterTests::getSharedAvMemoryHandle(uint64_t filterId) {
191     EXPECT_TRUE(mFilters[filterId]) << "Open media filter first.";
192     Result status = Result::UNKNOWN_ERROR;
193     sp<android::hardware::tv::tuner::V1_1::IFilter> filter_v1_1 =
194             android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilters[filterId]);
195     if (filter_v1_1 != NULL) {
196         filter_v1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) {
197             status = r;
198             if (status == Result::SUCCESS) {
199                 mFilterCallbacks[mFilterId]->setSharedHandle(avMemory);
200                 mFilterCallbacks[mFilterId]->setMemSize(avMemSize);
201                 mAvSharedHandle = avMemory;
202             }
203         });
204     }
205     return AssertionResult(status == Result::SUCCESS);
206 }
207 
releaseShareAvHandle(uint64_t filterId)208 AssertionResult FilterTests::releaseShareAvHandle(uint64_t filterId) {
209     Result status;
210     EXPECT_TRUE(mFilters[filterId]) << "Open media filter first.";
211     EXPECT_TRUE(mAvSharedHandle) << "No shared av handle to release.";
212     status = mFilters[filterId]->releaseAvHandle(mAvSharedHandle, 0 /*dataId*/);
213 
214     return AssertionResult(status == Result::SUCCESS);
215 }
216 
configFilter(DemuxFilterSettings setting,uint64_t filterId)217 AssertionResult FilterTests::configFilter(DemuxFilterSettings setting, uint64_t filterId) {
218     Result status;
219     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
220     status = mFilters[filterId]->configure(setting);
221 
222     return AssertionResult(status == Result::SUCCESS);
223 }
224 
configAvFilterStreamType(AvStreamType type,uint64_t filterId)225 AssertionResult FilterTests::configAvFilterStreamType(AvStreamType type, uint64_t filterId) {
226     Result status;
227     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
228     sp<android::hardware::tv::tuner::V1_1::IFilter> filter_v1_1 =
229             android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilters[filterId]);
230     if (filter_v1_1 != NULL) {
231         status = filter_v1_1->configureAvStreamType(type);
232     } else {
233         ALOGW("[vts] Can't cast IFilter into v1_1.");
234         return failure();
235     }
236     return AssertionResult(status == Result::SUCCESS);
237 }
238 
configIpFilterCid(uint32_t ipCid,uint64_t filterId)239 AssertionResult FilterTests::configIpFilterCid(uint32_t ipCid, uint64_t filterId) {
240     Result status;
241     EXPECT_TRUE(mFilters[filterId]) << "Open Ip filter first.";
242 
243     sp<android::hardware::tv::tuner::V1_1::IFilter> filter_v1_1 =
244             android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilters[filterId]);
245     if (filter_v1_1 != NULL) {
246         status = filter_v1_1->configureIpCid(ipCid);
247     } else {
248         ALOGW("[vts] Can't cast IFilter into v1_1.");
249         return failure();
250     }
251 
252     return AssertionResult(status == Result::SUCCESS);
253 }
254 
getFilterMQDescriptor(uint64_t filterId,bool getMqDesc)255 AssertionResult FilterTests::getFilterMQDescriptor(uint64_t filterId, bool getMqDesc) {
256     if (!getMqDesc) {
257         ALOGE("[vts] Filter does not need FMQ.");
258         return success();
259     }
260     Result status;
261     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
262     EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
263 
264     mFilter->getQueueDesc([&](Result result, const MQDesc& filterMQDesc) {
265         mFilterMQDescriptor = filterMQDesc;
266         status = result;
267     });
268 
269     return AssertionResult(status == Result::SUCCESS);
270 }
271 
startFilter(uint64_t filterId)272 AssertionResult FilterTests::startFilter(uint64_t filterId) {
273     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
274     Result status = mFilters[filterId]->start();
275     return AssertionResult(status == Result::SUCCESS);
276 }
277 
stopFilter(uint64_t filterId)278 AssertionResult FilterTests::stopFilter(uint64_t filterId) {
279     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
280     Result status = mFilters[filterId]->stop();
281 
282     return AssertionResult(status == Result::SUCCESS);
283 }
284 
closeFilter(uint64_t filterId)285 AssertionResult FilterTests::closeFilter(uint64_t filterId) {
286     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
287     Result status = mFilters[filterId]->close();
288     if (status == Result::SUCCESS) {
289         for (int i = 0; i < mUsedFilterIds.size(); i++) {
290             if (mUsedFilterIds[i] == filterId) {
291                 mUsedFilterIds.erase(mUsedFilterIds.begin() + i);
292                 break;
293             }
294         }
295         mFilterCallbacks.erase(filterId);
296         mFilters.erase(filterId);
297     }
298     return AssertionResult(status == Result::SUCCESS);
299 }
300 
configureMonitorEvent(uint64_t filterId,uint32_t monitorEventTypes)301 AssertionResult FilterTests::configureMonitorEvent(uint64_t filterId, uint32_t monitorEventTypes) {
302     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
303     Result status;
304 
305     sp<android::hardware::tv::tuner::V1_1::IFilter> filter_v1_1 =
306             android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilters[filterId]);
307     if (filter_v1_1 != NULL) {
308         status = filter_v1_1->configureMonitorEvent(monitorEventTypes);
309         if (monitorEventTypes & DemuxFilterMonitorEventType::SCRAMBLING_STATUS) {
310             mFilterCallbacks[filterId]->testFilterScramblingEvent();
311         }
312         if (monitorEventTypes & DemuxFilterMonitorEventType::IP_CID_CHANGE) {
313             mFilterCallbacks[filterId]->testFilterIpCidEvent();
314         }
315     } else {
316         ALOGW("[vts] Can't cast IFilter into v1_1.");
317         return failure();
318     }
319     return AssertionResult(status == Result::SUCCESS);
320 }
321 
startIdTest(uint64_t filterId)322 AssertionResult FilterTests::startIdTest(uint64_t filterId) {
323     EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
324     mFilterCallbacks[filterId]->testStartIdAfterReconfigure();
325     return AssertionResult(true);
326 }
327