blob: 599abfb0b9e3320e5edeef327d7c774ddf6aa882 [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 Zhang37719f32021-01-19 19:39:01 -080058 EXPECT_TRUE(fd >= 0) << "Failed to open: " + mInputDataFile;
Amy Zhang0fe25be2020-04-08 17:30:52 -070059 mPlaybackThreadRunning = false;
60 ALOGW("[vts] Error %s", strerror(errno));
61 }
62
63 while (mPlaybackThreadRunning) {
Amy Zhang6e8163a2020-04-24 15:41:21 -070064 while (mKeepWritingPlaybackFMQ) {
Amy Zhang6bda6392020-05-26 19:00:46 -070065 int totalWrite = mPlaybackMQ->availableToWrite();
66 if (totalWrite * 4 < mPlaybackMQ->getQuantumCount()) {
67 // Wait for the HAL implementation to read more data then write.
68 continue;
69 }
70 MessageQueue<uint8_t, kSynchronizedReadWrite>::MemTransaction memTx;
71 if (!mPlaybackMQ->beginWrite(totalWrite, &memTx)) {
72 ALOGW("[vts] Fail to write into Playback fmq.");
Amy Zhang0fe25be2020-04-08 17:30:52 -070073 mPlaybackThreadRunning = false;
74 break;
75 }
Amy Zhang6bda6392020-05-26 19:00:46 -070076 auto first = memTx.getFirstRegion();
77 buffer = first.getAddress();
78 regionSize = first.getLength();
79
80 if (regionSize > 0) {
81 readBytes = read(fd, buffer, regionSize);
82 if (readBytes <= 0) {
83 if (readBytes < 0) {
84 ALOGW("[vts] Read from %s failed.", mInputDataFile.c_str());
85 } else {
86 ALOGW("[vts] playback input EOF.");
87 }
88 mPlaybackThreadRunning = false;
89 break;
90 }
91 }
92 if (regionSize == 0 || (readBytes == regionSize && regionSize < totalWrite)) {
93 auto second = memTx.getSecondRegion();
94 buffer = second.getAddress();
95 regionSize = second.getLength();
96 int ret = read(fd, buffer, regionSize);
97 if (ret <= 0) {
98 if (ret < 0) {
99 ALOGW("[vts] Read from %s failed.", mInputDataFile.c_str());
100 } else {
101 ALOGW("[vts] playback input EOF.");
102 }
103 mPlaybackThreadRunning = false;
104 break;
105 }
106 readBytes += ret;
107 }
108 if (!mPlaybackMQ->commitWrite(readBytes)) {
109 ALOGW("[vts] Failed to commit write playback fmq.");
110 mPlaybackThreadRunning = false;
111 break;
112 }
Amy Zhang0fe25be2020-04-08 17:30:52 -0700113 playbackMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
Amy Zhang0fe25be2020-04-08 17:30:52 -0700114 }
115 }
116
Amy Zhang6bda6392020-05-26 19:00:46 -0700117 mPlaybackThreadRunning = false;
Amy Zhang0fe25be2020-04-08 17:30:52 -0700118 ALOGW("[vts] Playback thread end.");
Amy Zhang6bda6392020-05-26 19:00:46 -0700119 close(fd);
Amy Zhang0fe25be2020-04-08 17:30:52 -0700120}
121
122void DvrCallback::testRecordOutput() {
123 android::Mutex::Autolock autoLock(mMsgLock);
124 while (mDataOutputBuffer.empty()) {
125 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
126 EXPECT_TRUE(false) << "record output matching pid does not output within timeout";
Amy Zhang6e8163a2020-04-24 15:41:21 -0700127 stopRecordThread();
Amy Zhang0fe25be2020-04-08 17:30:52 -0700128 return;
129 }
130 }
131 stopRecordThread();
132 ALOGW("[vts] record pass and stop");
133}
134
135void DvrCallback::startRecordOutputThread(RecordSettings recordSettings,
136 MQDesc& recordMQDescriptor) {
137 mRecordMQ = std::make_unique<FilterMQ>(recordMQDescriptor, true /* resetPointers */);
138 EXPECT_TRUE(mRecordMQ);
139 struct RecordThreadArgs* threadArgs =
140 (struct RecordThreadArgs*)malloc(sizeof(struct RecordThreadArgs));
141 threadArgs->user = this;
142 threadArgs->recordSettings = &recordSettings;
143 threadArgs->keepReadingRecordFMQ = &mKeepReadingRecordFMQ;
144
145 pthread_create(&mRecordThread, NULL, __threadLoopRecord, (void*)threadArgs);
146 pthread_setname_np(mRecordThread, "test_record_input_loop");
147}
148
149void* DvrCallback::__threadLoopRecord(void* threadArgs) {
150 DvrCallback* const self =
151 static_cast<DvrCallback*>(((struct RecordThreadArgs*)threadArgs)->user);
152 self->recordThreadLoop(((struct RecordThreadArgs*)threadArgs)->recordSettings,
153 ((struct RecordThreadArgs*)threadArgs)->keepReadingRecordFMQ);
154 return 0;
155}
156
157void DvrCallback::recordThreadLoop(RecordSettings* /*recordSettings*/, bool* keepReadingRecordFMQ) {
158 ALOGD("[vts] DvrCallback record threadLoop start.");
159 android::Mutex::Autolock autoLock(mRecordThreadLock);
160 mRecordThreadRunning = true;
Amy Zhang6e8163a2020-04-24 15:41:21 -0700161 mKeepReadingRecordFMQ = true;
Amy Zhang0fe25be2020-04-08 17:30:52 -0700162
163 // Create the EventFlag that is used to signal the HAL impl that data have been
164 // read from the Record FMQ
165 EventFlag* recordMQEventFlag;
166 EXPECT_TRUE(EventFlag::createEventFlag(mRecordMQ->getEventFlagWord(), &recordMQEventFlag) ==
167 android::OK);
168
169 while (mRecordThreadRunning) {
170 while (*keepReadingRecordFMQ) {
171 uint32_t efState = 0;
172 android::status_t status = recordMQEventFlag->wait(
173 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
174 true /* retry on spurious wake */);
175 if (status != android::OK) {
176 ALOGD("[vts] wait for data ready on the record FMQ");
177 continue;
178 }
179 // Our current implementation filter the data and write it into the filter FMQ
180 // immediately after the DATA_READY from the VTS/framework
181 if (!readRecordFMQ()) {
Amy Zhang37719f32021-01-19 19:39:01 -0800182 ALOGW("[vts] record data failed to be filtered. Ending thread");
Amy Zhang0fe25be2020-04-08 17:30:52 -0700183 mRecordThreadRunning = false;
184 break;
185 }
186 }
187 }
188
189 mRecordThreadRunning = false;
190 ALOGD("[vts] record thread ended.");
191}
192
193bool DvrCallback::readRecordFMQ() {
194 android::Mutex::Autolock autoLock(mMsgLock);
195 bool result = false;
196 mDataOutputBuffer.clear();
197 mDataOutputBuffer.resize(mRecordMQ->availableToRead());
198 result = mRecordMQ->read(mDataOutputBuffer.data(), mRecordMQ->availableToRead());
199 EXPECT_TRUE(result) << "can't read from Record MQ";
200 mMsgCondition.signal();
201 return result;
202}
203
204void DvrCallback::stopRecordThread() {
205 mKeepReadingRecordFMQ = false;
206 mRecordThreadRunning = false;
Pierre Couillaudf8a4e2a2021-08-20 12:15:26 +0100207 android::Mutex::Autolock autoLock(mRecordThreadLock);
Amy Zhang0fe25be2020-04-08 17:30:52 -0700208}
209
Amy Zhanga305c1c2020-04-20 17:59:26 -0700210AssertionResult DvrTests::openDvrInDemux(DvrType type, uint32_t bufferSize) {
Amy Zhang0fe25be2020-04-08 17:30:52 -0700211 Result status;
212 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
213
214 // Create dvr callback
Amy Zhang6bda6392020-05-26 19:00:46 -0700215 if (type == DvrType::PLAYBACK) {
216 mDvrPlaybackCallback = new DvrCallback();
217 mDemux->openDvr(type, bufferSize, mDvrPlaybackCallback,
218 [&](Result result, const sp<IDvr>& dvr) {
219 mDvrPlayback = dvr;
220 status = result;
221 });
222 if (status == Result::SUCCESS) {
223 mDvrPlaybackCallback->setDvr(mDvrPlayback);
224 }
225 }
Amy Zhang0fe25be2020-04-08 17:30:52 -0700226
Amy Zhang6bda6392020-05-26 19:00:46 -0700227 if (type == DvrType::RECORD) {
228 mDvrRecordCallback = new DvrCallback();
229 mDemux->openDvr(type, bufferSize, mDvrRecordCallback,
230 [&](Result result, const sp<IDvr>& dvr) {
231 mDvrRecord = dvr;
232 status = result;
233 });
234 if (status == Result::SUCCESS) {
235 mDvrRecordCallback->setDvr(mDvrRecord);
236 }
237 }
238
239 return AssertionResult(status == Result::SUCCESS);
240}
241
242AssertionResult DvrTests::configDvrPlayback(DvrSettings setting) {
243 Result status = mDvrPlayback->configure(setting);
244
245 return AssertionResult(status == Result::SUCCESS);
246}
247
248AssertionResult DvrTests::configDvrRecord(DvrSettings setting) {
249 Result status = mDvrRecord->configure(setting);
250
251 return AssertionResult(status == Result::SUCCESS);
252}
253
254AssertionResult DvrTests::getDvrPlaybackMQDescriptor() {
255 Result status;
256 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
257 EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
258
259 mDvrPlayback->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
260 mDvrPlaybackMQDescriptor = dvrMQDesc;
Amy Zhang0fe25be2020-04-08 17:30:52 -0700261 status = result;
262 });
263
264 return AssertionResult(status == Result::SUCCESS);
265}
266
Amy Zhang6bda6392020-05-26 19:00:46 -0700267AssertionResult DvrTests::getDvrRecordMQDescriptor() {
Amy Zhang0fe25be2020-04-08 17:30:52 -0700268 Result status;
269 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
Amy Zhang6bda6392020-05-26 19:00:46 -0700270 EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
Amy Zhang0fe25be2020-04-08 17:30:52 -0700271
Amy Zhang6bda6392020-05-26 19:00:46 -0700272 mDvrRecord->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
273 mDvrRecordMQDescriptor = dvrMQDesc;
Amy Zhang0fe25be2020-04-08 17:30:52 -0700274 status = result;
275 });
276
277 return AssertionResult(status == Result::SUCCESS);
278}
279
280AssertionResult DvrTests::attachFilterToDvr(sp<IFilter> filter) {
281 Result status;
282 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
Amy Zhang6bda6392020-05-26 19:00:46 -0700283 EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
Amy Zhang0fe25be2020-04-08 17:30:52 -0700284
Amy Zhang6bda6392020-05-26 19:00:46 -0700285 status = mDvrRecord->attachFilter(filter);
Amy Zhang0fe25be2020-04-08 17:30:52 -0700286
287 return AssertionResult(status == Result::SUCCESS);
288}
289
290AssertionResult DvrTests::detachFilterToDvr(sp<IFilter> filter) {
291 Result status;
292 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
Amy Zhang6bda6392020-05-26 19:00:46 -0700293 EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
Amy Zhang0fe25be2020-04-08 17:30:52 -0700294
Amy Zhang6bda6392020-05-26 19:00:46 -0700295 status = mDvrRecord->detachFilter(filter);
Amy Zhang0fe25be2020-04-08 17:30:52 -0700296
297 return AssertionResult(status == Result::SUCCESS);
298}
299
Amy Zhang6bda6392020-05-26 19:00:46 -0700300AssertionResult DvrTests::startDvrPlayback() {
Amy Zhang0fe25be2020-04-08 17:30:52 -0700301 Result status;
302 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
Amy Zhang6bda6392020-05-26 19:00:46 -0700303 EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
Amy Zhang0fe25be2020-04-08 17:30:52 -0700304
Amy Zhang6bda6392020-05-26 19:00:46 -0700305 status = mDvrPlayback->start();
Amy Zhang0fe25be2020-04-08 17:30:52 -0700306
307 return AssertionResult(status == Result::SUCCESS);
308}
309
Amy Zhang6bda6392020-05-26 19:00:46 -0700310AssertionResult DvrTests::stopDvrPlayback() {
Amy Zhang0fe25be2020-04-08 17:30:52 -0700311 Result status;
312 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
Amy Zhang6bda6392020-05-26 19:00:46 -0700313 EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
Amy Zhang0fe25be2020-04-08 17:30:52 -0700314
Amy Zhang6bda6392020-05-26 19:00:46 -0700315 status = mDvrPlayback->stop();
Amy Zhang0fe25be2020-04-08 17:30:52 -0700316
317 return AssertionResult(status == Result::SUCCESS);
318}
319
Amy Zhang6bda6392020-05-26 19:00:46 -0700320void DvrTests::closeDvrPlayback() {
Amy Zhang0fe25be2020-04-08 17:30:52 -0700321 ASSERT_TRUE(mDemux);
Amy Zhang6bda6392020-05-26 19:00:46 -0700322 ASSERT_TRUE(mDvrPlayback);
323 ASSERT_TRUE(mDvrPlayback->close() == Result::SUCCESS);
324}
325
326AssertionResult DvrTests::startDvrRecord() {
327 Result status;
328 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
329 EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
330
331 status = mDvrRecord->start();
332
333 return AssertionResult(status == Result::SUCCESS);
334}
335
336AssertionResult DvrTests::stopDvrRecord() {
337 Result status;
338 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
339 EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
340
341 status = mDvrRecord->stop();
342
343 return AssertionResult(status == Result::SUCCESS);
344}
345
346void DvrTests::closeDvrRecord() {
347 ASSERT_TRUE(mDemux);
348 ASSERT_TRUE(mDvrRecord);
349 ASSERT_TRUE(mDvrRecord->close() == Result::SUCCESS);
Amy Zhanga305c1c2020-04-20 17:59:26 -0700350}