blob: 9b24aa7a083972e58b53ca90373ef3102a8b2884 [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
19void DvrCallback::startPlaybackInputThread(PlaybackConf playbackConf,
20 MQDesc& playbackMQDescriptor) {
21 mPlaybackMQ = std::make_unique<FilterMQ>(playbackMQDescriptor, true /* resetPointers */);
22 EXPECT_TRUE(mPlaybackMQ);
23 struct PlaybackThreadArgs* threadArgs =
24 (struct PlaybackThreadArgs*)malloc(sizeof(struct PlaybackThreadArgs));
25 threadArgs->user = this;
26 threadArgs->playbackConf = &playbackConf;
27 threadArgs->keepWritingPlaybackFMQ = &mKeepWritingPlaybackFMQ;
28
29 pthread_create(&mPlaybackThread, NULL, __threadLoopPlayback, (void*)threadArgs);
30 pthread_setname_np(mPlaybackThread, "test_playback_input_loop");
31}
32
33void DvrCallback::stopPlaybackThread() {
34 mPlaybackThreadRunning = false;
35 mKeepWritingPlaybackFMQ = false;
36
37 android::Mutex::Autolock autoLock(mPlaybackThreadLock);
38}
39
40void* DvrCallback::__threadLoopPlayback(void* threadArgs) {
41 DvrCallback* const self =
42 static_cast<DvrCallback*>(((struct PlaybackThreadArgs*)threadArgs)->user);
43 self->playbackThreadLoop(((struct PlaybackThreadArgs*)threadArgs)->playbackConf,
44 ((struct PlaybackThreadArgs*)threadArgs)->keepWritingPlaybackFMQ);
45 return 0;
46}
47
48void DvrCallback::playbackThreadLoop(PlaybackConf* playbackConf, bool* keepWritingPlaybackFMQ) {
49 android::Mutex::Autolock autoLock(mPlaybackThreadLock);
50 mPlaybackThreadRunning = true;
51
52 // Create the EventFlag that is used to signal the HAL impl that data have been
53 // written into the Playback FMQ
54 EventFlag* playbackMQEventFlag;
55 EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) ==
56 android::OK);
57
58 // open the stream and get its length
59 std::ifstream inputData(playbackConf->inputDataFile, std::ifstream::binary);
60 int writeSize = playbackConf->setting.packetSize * 6;
61 char* buffer = new char[writeSize];
62 ALOGW("[vts] playback thread loop start %s", playbackConf->inputDataFile.c_str());
63 if (!inputData.is_open()) {
64 mPlaybackThreadRunning = false;
65 ALOGW("[vts] Error %s", strerror(errno));
66 }
67
68 while (mPlaybackThreadRunning) {
69 // move the stream pointer for packet size * 6 every read until the end
70 while (*keepWritingPlaybackFMQ) {
71 inputData.read(buffer, writeSize);
72 if (!inputData) {
73 int leftSize = inputData.gcount();
74 if (leftSize == 0) {
75 mPlaybackThreadRunning = false;
76 break;
77 }
78 inputData.clear();
79 inputData.read(buffer, leftSize);
80 // Write the left over of the input data and quit the thread
81 if (leftSize > 0) {
82 EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], leftSize));
83 playbackMQEventFlag->wake(
84 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
85 }
86 mPlaybackThreadRunning = false;
87 break;
88 }
89 // Write input FMQ and notify the Tuner Implementation
90 EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], writeSize));
91 playbackMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
92 inputData.seekg(writeSize, inputData.cur);
93 sleep(1);
94 }
95 }
96
97 ALOGW("[vts] Playback thread end.");
98
99 delete[] buffer;
100 inputData.close();
101}
102
103void DvrCallback::testRecordOutput() {
104 android::Mutex::Autolock autoLock(mMsgLock);
105 while (mDataOutputBuffer.empty()) {
106 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
107 EXPECT_TRUE(false) << "record output matching pid does not output within timeout";
108 return;
109 }
110 }
111 stopRecordThread();
112 ALOGW("[vts] record pass and stop");
113}
114
115void DvrCallback::startRecordOutputThread(RecordSettings recordSettings,
116 MQDesc& recordMQDescriptor) {
117 mRecordMQ = std::make_unique<FilterMQ>(recordMQDescriptor, true /* resetPointers */);
118 EXPECT_TRUE(mRecordMQ);
119 struct RecordThreadArgs* threadArgs =
120 (struct RecordThreadArgs*)malloc(sizeof(struct RecordThreadArgs));
121 threadArgs->user = this;
122 threadArgs->recordSettings = &recordSettings;
123 threadArgs->keepReadingRecordFMQ = &mKeepReadingRecordFMQ;
124
125 pthread_create(&mRecordThread, NULL, __threadLoopRecord, (void*)threadArgs);
126 pthread_setname_np(mRecordThread, "test_record_input_loop");
127}
128
129void* DvrCallback::__threadLoopRecord(void* threadArgs) {
130 DvrCallback* const self =
131 static_cast<DvrCallback*>(((struct RecordThreadArgs*)threadArgs)->user);
132 self->recordThreadLoop(((struct RecordThreadArgs*)threadArgs)->recordSettings,
133 ((struct RecordThreadArgs*)threadArgs)->keepReadingRecordFMQ);
134 return 0;
135}
136
137void DvrCallback::recordThreadLoop(RecordSettings* /*recordSettings*/, bool* keepReadingRecordFMQ) {
138 ALOGD("[vts] DvrCallback record threadLoop start.");
139 android::Mutex::Autolock autoLock(mRecordThreadLock);
140 mRecordThreadRunning = true;
141
142 // Create the EventFlag that is used to signal the HAL impl that data have been
143 // read from the Record FMQ
144 EventFlag* recordMQEventFlag;
145 EXPECT_TRUE(EventFlag::createEventFlag(mRecordMQ->getEventFlagWord(), &recordMQEventFlag) ==
146 android::OK);
147
148 while (mRecordThreadRunning) {
149 while (*keepReadingRecordFMQ) {
150 uint32_t efState = 0;
151 android::status_t status = recordMQEventFlag->wait(
152 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
153 true /* retry on spurious wake */);
154 if (status != android::OK) {
155 ALOGD("[vts] wait for data ready on the record FMQ");
156 continue;
157 }
158 // Our current implementation filter the data and write it into the filter FMQ
159 // immediately after the DATA_READY from the VTS/framework
160 if (!readRecordFMQ()) {
161 ALOGD("[vts] record data failed to be filtered. Ending thread");
162 mRecordThreadRunning = false;
163 break;
164 }
165 }
166 }
167
168 mRecordThreadRunning = false;
169 ALOGD("[vts] record thread ended.");
170}
171
172bool DvrCallback::readRecordFMQ() {
173 android::Mutex::Autolock autoLock(mMsgLock);
174 bool result = false;
175 mDataOutputBuffer.clear();
176 mDataOutputBuffer.resize(mRecordMQ->availableToRead());
177 result = mRecordMQ->read(mDataOutputBuffer.data(), mRecordMQ->availableToRead());
178 EXPECT_TRUE(result) << "can't read from Record MQ";
179 mMsgCondition.signal();
180 return result;
181}
182
183void DvrCallback::stopRecordThread() {
184 mKeepReadingRecordFMQ = false;
185 mRecordThreadRunning = false;
186 android::Mutex::Autolock autoLock(mRecordThreadLock);
187}
188
Amy Zhanga305c1c2020-04-20 17:59:26 -0700189AssertionResult DvrTests::openDvrInDemux(DvrType type, uint32_t bufferSize) {
Amy Zhang0fe25be2020-04-08 17:30:52 -0700190 Result status;
191 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
192
193 // Create dvr callback
194 mDvrCallback = new DvrCallback();
195
Amy Zhanga305c1c2020-04-20 17:59:26 -0700196 mDemux->openDvr(type, bufferSize, mDvrCallback, [&](Result result, const sp<IDvr>& dvr) {
Amy Zhang0fe25be2020-04-08 17:30:52 -0700197 mDvr = dvr;
198 status = result;
199 });
200
201 return AssertionResult(status == Result::SUCCESS);
202}
203
204AssertionResult DvrTests::configDvr(DvrSettings setting) {
205 Result status = mDvr->configure(setting);
206
207 return AssertionResult(status == Result::SUCCESS);
208}
209
210AssertionResult DvrTests::getDvrMQDescriptor() {
211 Result status;
212 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
213 EXPECT_TRUE(mDvr) << "Test with openDvr first.";
214
215 mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
216 mDvrMQDescriptor = dvrMQDesc;
217 status = result;
218 });
219
220 return AssertionResult(status == Result::SUCCESS);
221}
222
223AssertionResult DvrTests::attachFilterToDvr(sp<IFilter> filter) {
224 Result status;
225 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
226 EXPECT_TRUE(mDvr) << "Test with openDvr first.";
227
228 status = mDvr->attachFilter(filter);
229
230 return AssertionResult(status == Result::SUCCESS);
231}
232
233AssertionResult DvrTests::detachFilterToDvr(sp<IFilter> filter) {
234 Result status;
235 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
236 EXPECT_TRUE(mDvr) << "Test with openDvr first.";
237
238 status = mDvr->detachFilter(filter);
239
240 return AssertionResult(status == Result::SUCCESS);
241}
242
243AssertionResult DvrTests::startDvr() {
244 Result status;
245 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
246 EXPECT_TRUE(mDvr) << "Test with openDvr first.";
247
248 status = mDvr->start();
249
250 return AssertionResult(status == Result::SUCCESS);
251}
252
253AssertionResult DvrTests::stopDvr() {
254 Result status;
255 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
256 EXPECT_TRUE(mDvr) << "Test with openDvr first.";
257
258 status = mDvr->stop();
259
260 return AssertionResult(status == Result::SUCCESS);
261}
262
263void DvrTests::closeDvr() {
264 ASSERT_TRUE(mDemux);
265 ASSERT_TRUE(mDvr);
266 ASSERT_TRUE(mDvr->close() == Result::SUCCESS);
Amy Zhanga305c1c2020-04-20 17:59:26 -0700267}