blob: 0dfc032d1958415d279a56ba6548a50ea9ea83d6 [file] [log] [blame]
Amy Zhang0fe25be2020-04-08 17:30:52 -07001/*
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 "DvrTests.h"
18
Amy Zhang6e8163a2020-04-24 15:41:21 -070019void DvrCallback::startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings,
Amy Zhang0fe25be2020-04-08 17:30:52 -070020 MQDesc& playbackMQDescriptor) {
Amy Zhang6e8163a2020-04-24 15:41:21 -070021 mInputDataFile = dataInputFile;
22 mPlaybackSettings = settings;
Amy Zhang0fe25be2020-04-08 17:30:52 -070023 mPlaybackMQ = std::make_unique<FilterMQ>(playbackMQDescriptor, true /* resetPointers */);
24 EXPECT_TRUE(mPlaybackMQ);
Amy Zhang6e8163a2020-04-24 15:41:21 -070025 pthread_create(&mPlaybackThread, NULL, __threadLoopPlayback, this);
Amy Zhang0fe25be2020-04-08 17:30:52 -070026 pthread_setname_np(mPlaybackThread, "test_playback_input_loop");
27}
28
29void DvrCallback::stopPlaybackThread() {
30 mPlaybackThreadRunning = false;
31 mKeepWritingPlaybackFMQ = false;
32
33 android::Mutex::Autolock autoLock(mPlaybackThreadLock);
34}
35
Amy Zhang6e8163a2020-04-24 15:41:21 -070036void* DvrCallback::__threadLoopPlayback(void* user) {
37 DvrCallback* const self = static_cast<DvrCallback*>(user);
38 self->playbackThreadLoop();
Amy Zhang0fe25be2020-04-08 17:30:52 -070039 return 0;
40}
41
Amy Zhang6e8163a2020-04-24 15:41:21 -070042void DvrCallback::playbackThreadLoop() {
Amy Zhang0fe25be2020-04-08 17:30:52 -070043 android::Mutex::Autolock autoLock(mPlaybackThreadLock);
44 mPlaybackThreadRunning = true;
45
46 // Create the EventFlag that is used to signal the HAL impl that data have been
47 // written into the Playback FMQ
48 EventFlag* playbackMQEventFlag;
49 EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) ==
50 android::OK);
51
Amy Zhang6bda6392020-05-26 19:00:46 -070052 int fd = open(mInputDataFile.c_str(), O_RDONLY | O_LARGEFILE);
53 int readBytes;
54 uint32_t regionSize = 0;
55 uint8_t* buffer;
56 ALOGW("[vts] playback thread loop start %s", mInputDataFile.c_str());
57 if (fd < 0) {
Amy Zhang0fe25be2020-04-08 17:30:52 -070058 mPlaybackThreadRunning = false;
59 ALOGW("[vts] Error %s", strerror(errno));
60 }
61
62 while (mPlaybackThreadRunning) {
Amy Zhang6e8163a2020-04-24 15:41:21 -070063 while (mKeepWritingPlaybackFMQ) {
Amy Zhang6bda6392020-05-26 19:00:46 -070064 int totalWrite = mPlaybackMQ->availableToWrite();
65 if (totalWrite * 4 < mPlaybackMQ->getQuantumCount()) {
66 // Wait for the HAL implementation to read more data then write.
67 continue;
68 }
69 MessageQueue<uint8_t, kSynchronizedReadWrite>::MemTransaction memTx;
70 if (!mPlaybackMQ->beginWrite(totalWrite, &memTx)) {
71 ALOGW("[vts] Fail to write into Playback fmq.");
Amy Zhang0fe25be2020-04-08 17:30:52 -070072 mPlaybackThreadRunning = false;
73 break;
74 }
Amy Zhang6bda6392020-05-26 19:00:46 -070075 auto first = memTx.getFirstRegion();
76 buffer = first.getAddress();
77 regionSize = first.getLength();
78
79 if (regionSize > 0) {
80 readBytes = read(fd, buffer, regionSize);
81 if (readBytes <= 0) {
82 if (readBytes < 0) {
83 ALOGW("[vts] Read from %s failed.", mInputDataFile.c_str());
84 } else {
85 ALOGW("[vts] playback input EOF.");
86 }
87 mPlaybackThreadRunning = false;
88 break;
89 }
90 }
91 if (regionSize == 0 || (readBytes == regionSize && regionSize < totalWrite)) {
92 auto second = memTx.getSecondRegion();
93 buffer = second.getAddress();
94 regionSize = second.getLength();
95 int ret = read(fd, buffer, regionSize);
96 if (ret <= 0) {
97 if (ret < 0) {
98 ALOGW("[vts] Read from %s failed.", mInputDataFile.c_str());
99 } else {
100 ALOGW("[vts] playback input EOF.");
101 }
102 mPlaybackThreadRunning = false;
103 break;
104 }
105 readBytes += ret;
106 }
107 if (!mPlaybackMQ->commitWrite(readBytes)) {
108 ALOGW("[vts] Failed to commit write playback fmq.");
109 mPlaybackThreadRunning = false;
110 break;
111 }
Amy Zhang0fe25be2020-04-08 17:30:52 -0700112 playbackMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
Amy Zhang0fe25be2020-04-08 17:30:52 -0700113 }
114 }
115
Amy Zhang6bda6392020-05-26 19:00:46 -0700116 mPlaybackThreadRunning = false;
Amy Zhang0fe25be2020-04-08 17:30:52 -0700117 ALOGW("[vts] Playback thread end.");
Amy Zhang6bda6392020-05-26 19:00:46 -0700118 close(fd);
Amy Zhang0fe25be2020-04-08 17:30:52 -0700119}
120
121void DvrCallback::testRecordOutput() {
122 android::Mutex::Autolock autoLock(mMsgLock);
123 while (mDataOutputBuffer.empty()) {
124 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
125 EXPECT_TRUE(false) << "record output matching pid does not output within timeout";
Amy Zhang6e8163a2020-04-24 15:41:21 -0700126 stopRecordThread();
Amy Zhang0fe25be2020-04-08 17:30:52 -0700127 return;
128 }
129 }
130 stopRecordThread();
131 ALOGW("[vts] record pass and stop");
132}
133
134void DvrCallback::startRecordOutputThread(RecordSettings recordSettings,
135 MQDesc& recordMQDescriptor) {
136 mRecordMQ = std::make_unique<FilterMQ>(recordMQDescriptor, true /* resetPointers */);
137 EXPECT_TRUE(mRecordMQ);
138 struct RecordThreadArgs* threadArgs =
139 (struct RecordThreadArgs*)malloc(sizeof(struct RecordThreadArgs));
140 threadArgs->user = this;
141 threadArgs->recordSettings = &recordSettings;
142 threadArgs->keepReadingRecordFMQ = &mKeepReadingRecordFMQ;
143
144 pthread_create(&mRecordThread, NULL, __threadLoopRecord, (void*)threadArgs);
145 pthread_setname_np(mRecordThread, "test_record_input_loop");
146}
147
148void* DvrCallback::__threadLoopRecord(void* threadArgs) {
149 DvrCallback* const self =
150 static_cast<DvrCallback*>(((struct RecordThreadArgs*)threadArgs)->user);
151 self->recordThreadLoop(((struct RecordThreadArgs*)threadArgs)->recordSettings,
152 ((struct RecordThreadArgs*)threadArgs)->keepReadingRecordFMQ);
153 return 0;
154}
155
156void DvrCallback::recordThreadLoop(RecordSettings* /*recordSettings*/, bool* keepReadingRecordFMQ) {
157 ALOGD("[vts] DvrCallback record threadLoop start.");
158 android::Mutex::Autolock autoLock(mRecordThreadLock);
159 mRecordThreadRunning = true;
Amy Zhang6e8163a2020-04-24 15:41:21 -0700160 mKeepReadingRecordFMQ = true;
Amy Zhang0fe25be2020-04-08 17:30:52 -0700161
162 // Create the EventFlag that is used to signal the HAL impl that data have been
163 // read from the Record FMQ
164 EventFlag* recordMQEventFlag;
165 EXPECT_TRUE(EventFlag::createEventFlag(mRecordMQ->getEventFlagWord(), &recordMQEventFlag) ==
166 android::OK);
167
168 while (mRecordThreadRunning) {
169 while (*keepReadingRecordFMQ) {
170 uint32_t efState = 0;
171 android::status_t status = recordMQEventFlag->wait(
172 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
173 true /* retry on spurious wake */);
174 if (status != android::OK) {
175 ALOGD("[vts] wait for data ready on the record FMQ");
176 continue;
177 }
178 // Our current implementation filter the data and write it into the filter FMQ
179 // immediately after the DATA_READY from the VTS/framework
180 if (!readRecordFMQ()) {
181 ALOGD("[vts] record data failed to be filtered. Ending thread");
182 mRecordThreadRunning = false;
183 break;
184 }
185 }
186 }
187
188 mRecordThreadRunning = false;
189 ALOGD("[vts] record thread ended.");
190}
191
192bool DvrCallback::readRecordFMQ() {
193 android::Mutex::Autolock autoLock(mMsgLock);
194 bool result = false;
195 mDataOutputBuffer.clear();
196 mDataOutputBuffer.resize(mRecordMQ->availableToRead());
197 result = mRecordMQ->read(mDataOutputBuffer.data(), mRecordMQ->availableToRead());
198 EXPECT_TRUE(result) << "can't read from Record MQ";
199 mMsgCondition.signal();
200 return result;
201}
202
203void DvrCallback::stopRecordThread() {
204 mKeepReadingRecordFMQ = false;
205 mRecordThreadRunning = false;
Amy Zhang0fe25be2020-04-08 17:30:52 -0700206}
207
Amy Zhanga305c1c2020-04-20 17:59:26 -0700208AssertionResult DvrTests::openDvrInDemux(DvrType type, uint32_t bufferSize) {
Amy Zhang0fe25be2020-04-08 17:30:52 -0700209 Result status;
210 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
211
212 // Create dvr callback
Amy Zhang6bda6392020-05-26 19:00:46 -0700213 if (type == DvrType::PLAYBACK) {
214 mDvrPlaybackCallback = new DvrCallback();
215 mDemux->openDvr(type, bufferSize, mDvrPlaybackCallback,
216 [&](Result result, const sp<IDvr>& dvr) {
217 mDvrPlayback = dvr;
218 status = result;
219 });
220 if (status == Result::SUCCESS) {
221 mDvrPlaybackCallback->setDvr(mDvrPlayback);
222 }
223 }
Amy Zhang0fe25be2020-04-08 17:30:52 -0700224
Amy Zhang6bda6392020-05-26 19:00:46 -0700225 if (type == DvrType::RECORD) {
226 mDvrRecordCallback = new DvrCallback();
227 mDemux->openDvr(type, bufferSize, mDvrRecordCallback,
228 [&](Result result, const sp<IDvr>& dvr) {
229 mDvrRecord = dvr;
230 status = result;
231 });
232 if (status == Result::SUCCESS) {
233 mDvrRecordCallback->setDvr(mDvrRecord);
234 }
235 }
236
237 return AssertionResult(status == Result::SUCCESS);
238}
239
240AssertionResult DvrTests::configDvrPlayback(DvrSettings setting) {
241 Result status = mDvrPlayback->configure(setting);
242
243 return AssertionResult(status == Result::SUCCESS);
244}
245
246AssertionResult DvrTests::configDvrRecord(DvrSettings setting) {
247 Result status = mDvrRecord->configure(setting);
248
249 return AssertionResult(status == Result::SUCCESS);
250}
251
252AssertionResult DvrTests::getDvrPlaybackMQDescriptor() {
253 Result status;
254 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
255 EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
256
257 mDvrPlayback->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
258 mDvrPlaybackMQDescriptor = dvrMQDesc;
Amy Zhang0fe25be2020-04-08 17:30:52 -0700259 status = result;
260 });
261
262 return AssertionResult(status == Result::SUCCESS);
263}
264
Amy Zhang6bda6392020-05-26 19:00:46 -0700265AssertionResult DvrTests::getDvrRecordMQDescriptor() {
Amy Zhang0fe25be2020-04-08 17:30:52 -0700266 Result status;
267 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
Amy Zhang6bda6392020-05-26 19:00:46 -0700268 EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
Amy Zhang0fe25be2020-04-08 17:30:52 -0700269
Amy Zhang6bda6392020-05-26 19:00:46 -0700270 mDvrRecord->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
271 mDvrRecordMQDescriptor = dvrMQDesc;
Amy Zhang0fe25be2020-04-08 17:30:52 -0700272 status = result;
273 });
274
275 return AssertionResult(status == Result::SUCCESS);
276}
277
278AssertionResult DvrTests::attachFilterToDvr(sp<IFilter> filter) {
279 Result status;
280 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
Amy Zhang6bda6392020-05-26 19:00:46 -0700281 EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
Amy Zhang0fe25be2020-04-08 17:30:52 -0700282
Amy Zhang6bda6392020-05-26 19:00:46 -0700283 status = mDvrRecord->attachFilter(filter);
Amy Zhang0fe25be2020-04-08 17:30:52 -0700284
285 return AssertionResult(status == Result::SUCCESS);
286}
287
288AssertionResult DvrTests::detachFilterToDvr(sp<IFilter> filter) {
289 Result status;
290 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
Amy Zhang6bda6392020-05-26 19:00:46 -0700291 EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
Amy Zhang0fe25be2020-04-08 17:30:52 -0700292
Amy Zhang6bda6392020-05-26 19:00:46 -0700293 status = mDvrRecord->detachFilter(filter);
Amy Zhang0fe25be2020-04-08 17:30:52 -0700294
295 return AssertionResult(status == Result::SUCCESS);
296}
297
Amy Zhang6bda6392020-05-26 19:00:46 -0700298AssertionResult DvrTests::startDvrPlayback() {
Amy Zhang0fe25be2020-04-08 17:30:52 -0700299 Result status;
300 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
Amy Zhang6bda6392020-05-26 19:00:46 -0700301 EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
Amy Zhang0fe25be2020-04-08 17:30:52 -0700302
Amy Zhang6bda6392020-05-26 19:00:46 -0700303 status = mDvrPlayback->start();
Amy Zhang0fe25be2020-04-08 17:30:52 -0700304
305 return AssertionResult(status == Result::SUCCESS);
306}
307
Amy Zhang6bda6392020-05-26 19:00:46 -0700308AssertionResult DvrTests::stopDvrPlayback() {
Amy Zhang0fe25be2020-04-08 17:30:52 -0700309 Result status;
310 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
Amy Zhang6bda6392020-05-26 19:00:46 -0700311 EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
Amy Zhang0fe25be2020-04-08 17:30:52 -0700312
Amy Zhang6bda6392020-05-26 19:00:46 -0700313 status = mDvrPlayback->stop();
Amy Zhang0fe25be2020-04-08 17:30:52 -0700314
315 return AssertionResult(status == Result::SUCCESS);
316}
317
Amy Zhang6bda6392020-05-26 19:00:46 -0700318void DvrTests::closeDvrPlayback() {
Amy Zhang0fe25be2020-04-08 17:30:52 -0700319 ASSERT_TRUE(mDemux);
Amy Zhang6bda6392020-05-26 19:00:46 -0700320 ASSERT_TRUE(mDvrPlayback);
321 ASSERT_TRUE(mDvrPlayback->close() == Result::SUCCESS);
322}
323
324AssertionResult DvrTests::startDvrRecord() {
325 Result status;
326 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
327 EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
328
329 status = mDvrRecord->start();
330
331 return AssertionResult(status == Result::SUCCESS);
332}
333
334AssertionResult DvrTests::stopDvrRecord() {
335 Result status;
336 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
337 EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
338
339 status = mDvrRecord->stop();
340
341 return AssertionResult(status == Result::SUCCESS);
342}
343
344void DvrTests::closeDvrRecord() {
345 ASSERT_TRUE(mDemux);
346 ASSERT_TRUE(mDvrRecord);
347 ASSERT_TRUE(mDvrRecord->close() == Result::SUCCESS);
Amy Zhanga305c1c2020-04-20 17:59:26 -0700348}