1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker * drawElements Quality Program Execution Server
3*35238bceSAndroid Build Coastguard Worker * ---------------------------------------------
4*35238bceSAndroid Build Coastguard Worker *
5*35238bceSAndroid Build Coastguard Worker * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker *
7*35238bceSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker *
11*35238bceSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker *
13*35238bceSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker *
19*35238bceSAndroid Build Coastguard Worker *//*!
20*35238bceSAndroid Build Coastguard Worker * \file
21*35238bceSAndroid Build Coastguard Worker * \brief TestProcess implementation for Unix-like systems.
22*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker
24*35238bceSAndroid Build Coastguard Worker #include "xsPosixTestProcess.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "deFilePath.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "deClock.h"
27*35238bceSAndroid Build Coastguard Worker
28*35238bceSAndroid Build Coastguard Worker #include <string.h>
29*35238bceSAndroid Build Coastguard Worker #include <stdio.h>
30*35238bceSAndroid Build Coastguard Worker
31*35238bceSAndroid Build Coastguard Worker using std::string;
32*35238bceSAndroid Build Coastguard Worker using std::vector;
33*35238bceSAndroid Build Coastguard Worker
34*35238bceSAndroid Build Coastguard Worker namespace xs
35*35238bceSAndroid Build Coastguard Worker {
36*35238bceSAndroid Build Coastguard Worker
37*35238bceSAndroid Build Coastguard Worker namespace posix
38*35238bceSAndroid Build Coastguard Worker {
39*35238bceSAndroid Build Coastguard Worker
CaseListWriter(void)40*35238bceSAndroid Build Coastguard Worker CaseListWriter::CaseListWriter(void) : m_file(DE_NULL), m_run(false)
41*35238bceSAndroid Build Coastguard Worker {
42*35238bceSAndroid Build Coastguard Worker }
43*35238bceSAndroid Build Coastguard Worker
~CaseListWriter(void)44*35238bceSAndroid Build Coastguard Worker CaseListWriter::~CaseListWriter(void)
45*35238bceSAndroid Build Coastguard Worker {
46*35238bceSAndroid Build Coastguard Worker }
47*35238bceSAndroid Build Coastguard Worker
start(const char * caseList,deFile * dst)48*35238bceSAndroid Build Coastguard Worker void CaseListWriter::start(const char *caseList, deFile *dst)
49*35238bceSAndroid Build Coastguard Worker {
50*35238bceSAndroid Build Coastguard Worker DE_ASSERT(!isStarted());
51*35238bceSAndroid Build Coastguard Worker m_file = dst;
52*35238bceSAndroid Build Coastguard Worker m_run = true;
53*35238bceSAndroid Build Coastguard Worker
54*35238bceSAndroid Build Coastguard Worker int caseListSize = (int)strlen(caseList) + 1;
55*35238bceSAndroid Build Coastguard Worker m_caseList.resize(caseListSize);
56*35238bceSAndroid Build Coastguard Worker std::copy(caseList, caseList + caseListSize, m_caseList.begin());
57*35238bceSAndroid Build Coastguard Worker
58*35238bceSAndroid Build Coastguard Worker // Set to non-blocking mode.
59*35238bceSAndroid Build Coastguard Worker if (!deFile_setFlags(m_file, DE_FILE_NONBLOCKING))
60*35238bceSAndroid Build Coastguard Worker XS_FAIL("Failed to set non-blocking mode");
61*35238bceSAndroid Build Coastguard Worker
62*35238bceSAndroid Build Coastguard Worker de::Thread::start();
63*35238bceSAndroid Build Coastguard Worker }
64*35238bceSAndroid Build Coastguard Worker
run(void)65*35238bceSAndroid Build Coastguard Worker void CaseListWriter::run(void)
66*35238bceSAndroid Build Coastguard Worker {
67*35238bceSAndroid Build Coastguard Worker int64_t pos = 0;
68*35238bceSAndroid Build Coastguard Worker
69*35238bceSAndroid Build Coastguard Worker while (m_run && pos < (int64_t)m_caseList.size())
70*35238bceSAndroid Build Coastguard Worker {
71*35238bceSAndroid Build Coastguard Worker int64_t numWritten = 0;
72*35238bceSAndroid Build Coastguard Worker deFileResult result = deFile_write(m_file, &m_caseList[0] + pos, m_caseList.size() - pos, &numWritten);
73*35238bceSAndroid Build Coastguard Worker
74*35238bceSAndroid Build Coastguard Worker if (result == DE_FILERESULT_SUCCESS)
75*35238bceSAndroid Build Coastguard Worker pos += numWritten;
76*35238bceSAndroid Build Coastguard Worker else if (result == DE_FILERESULT_WOULD_BLOCK)
77*35238bceSAndroid Build Coastguard Worker deSleep(1); // Yield.
78*35238bceSAndroid Build Coastguard Worker else
79*35238bceSAndroid Build Coastguard Worker break; // Error.
80*35238bceSAndroid Build Coastguard Worker }
81*35238bceSAndroid Build Coastguard Worker }
82*35238bceSAndroid Build Coastguard Worker
stop(void)83*35238bceSAndroid Build Coastguard Worker void CaseListWriter::stop(void)
84*35238bceSAndroid Build Coastguard Worker {
85*35238bceSAndroid Build Coastguard Worker if (!isStarted())
86*35238bceSAndroid Build Coastguard Worker return; // Nothing to do.
87*35238bceSAndroid Build Coastguard Worker
88*35238bceSAndroid Build Coastguard Worker m_run = false;
89*35238bceSAndroid Build Coastguard Worker
90*35238bceSAndroid Build Coastguard Worker // Join thread.
91*35238bceSAndroid Build Coastguard Worker join();
92*35238bceSAndroid Build Coastguard Worker
93*35238bceSAndroid Build Coastguard Worker m_file = DE_NULL;
94*35238bceSAndroid Build Coastguard Worker }
95*35238bceSAndroid Build Coastguard Worker
PipeReader(ThreadedByteBuffer * dst)96*35238bceSAndroid Build Coastguard Worker PipeReader::PipeReader(ThreadedByteBuffer *dst) : m_file(DE_NULL), m_buf(dst)
97*35238bceSAndroid Build Coastguard Worker {
98*35238bceSAndroid Build Coastguard Worker }
99*35238bceSAndroid Build Coastguard Worker
~PipeReader(void)100*35238bceSAndroid Build Coastguard Worker PipeReader::~PipeReader(void)
101*35238bceSAndroid Build Coastguard Worker {
102*35238bceSAndroid Build Coastguard Worker }
103*35238bceSAndroid Build Coastguard Worker
start(deFile * file)104*35238bceSAndroid Build Coastguard Worker void PipeReader::start(deFile *file)
105*35238bceSAndroid Build Coastguard Worker {
106*35238bceSAndroid Build Coastguard Worker DE_ASSERT(!isStarted());
107*35238bceSAndroid Build Coastguard Worker
108*35238bceSAndroid Build Coastguard Worker // Set to non-blocking mode.
109*35238bceSAndroid Build Coastguard Worker if (!deFile_setFlags(file, DE_FILE_NONBLOCKING))
110*35238bceSAndroid Build Coastguard Worker XS_FAIL("Failed to set non-blocking mode");
111*35238bceSAndroid Build Coastguard Worker
112*35238bceSAndroid Build Coastguard Worker m_file = file;
113*35238bceSAndroid Build Coastguard Worker
114*35238bceSAndroid Build Coastguard Worker de::Thread::start();
115*35238bceSAndroid Build Coastguard Worker }
116*35238bceSAndroid Build Coastguard Worker
run(void)117*35238bceSAndroid Build Coastguard Worker void PipeReader::run(void)
118*35238bceSAndroid Build Coastguard Worker {
119*35238bceSAndroid Build Coastguard Worker std::vector<uint8_t> tmpBuf(FILEREADER_TMP_BUFFER_SIZE);
120*35238bceSAndroid Build Coastguard Worker int64_t numRead = 0;
121*35238bceSAndroid Build Coastguard Worker
122*35238bceSAndroid Build Coastguard Worker while (!m_buf->isCanceled())
123*35238bceSAndroid Build Coastguard Worker {
124*35238bceSAndroid Build Coastguard Worker deFileResult result = deFile_read(m_file, &tmpBuf[0], (int64_t)tmpBuf.size(), &numRead);
125*35238bceSAndroid Build Coastguard Worker
126*35238bceSAndroid Build Coastguard Worker if (result == DE_FILERESULT_SUCCESS)
127*35238bceSAndroid Build Coastguard Worker {
128*35238bceSAndroid Build Coastguard Worker // Write to buffer.
129*35238bceSAndroid Build Coastguard Worker try
130*35238bceSAndroid Build Coastguard Worker {
131*35238bceSAndroid Build Coastguard Worker m_buf->write((int)numRead, &tmpBuf[0]);
132*35238bceSAndroid Build Coastguard Worker m_buf->flush();
133*35238bceSAndroid Build Coastguard Worker }
134*35238bceSAndroid Build Coastguard Worker catch (const ThreadedByteBuffer::CanceledException &)
135*35238bceSAndroid Build Coastguard Worker {
136*35238bceSAndroid Build Coastguard Worker // Canceled.
137*35238bceSAndroid Build Coastguard Worker break;
138*35238bceSAndroid Build Coastguard Worker }
139*35238bceSAndroid Build Coastguard Worker }
140*35238bceSAndroid Build Coastguard Worker else if (result == DE_FILERESULT_END_OF_FILE || result == DE_FILERESULT_WOULD_BLOCK)
141*35238bceSAndroid Build Coastguard Worker {
142*35238bceSAndroid Build Coastguard Worker // Wait for more data.
143*35238bceSAndroid Build Coastguard Worker deSleep(FILEREADER_IDLE_SLEEP);
144*35238bceSAndroid Build Coastguard Worker }
145*35238bceSAndroid Build Coastguard Worker else
146*35238bceSAndroid Build Coastguard Worker break; // Error.
147*35238bceSAndroid Build Coastguard Worker }
148*35238bceSAndroid Build Coastguard Worker }
149*35238bceSAndroid Build Coastguard Worker
stop(void)150*35238bceSAndroid Build Coastguard Worker void PipeReader::stop(void)
151*35238bceSAndroid Build Coastguard Worker {
152*35238bceSAndroid Build Coastguard Worker if (!isStarted())
153*35238bceSAndroid Build Coastguard Worker return; // Nothing to do.
154*35238bceSAndroid Build Coastguard Worker
155*35238bceSAndroid Build Coastguard Worker // Buffer must be in canceled state or otherwise stopping reader might block.
156*35238bceSAndroid Build Coastguard Worker DE_ASSERT(m_buf->isCanceled());
157*35238bceSAndroid Build Coastguard Worker
158*35238bceSAndroid Build Coastguard Worker // Join thread.
159*35238bceSAndroid Build Coastguard Worker join();
160*35238bceSAndroid Build Coastguard Worker
161*35238bceSAndroid Build Coastguard Worker m_file = DE_NULL;
162*35238bceSAndroid Build Coastguard Worker }
163*35238bceSAndroid Build Coastguard Worker
164*35238bceSAndroid Build Coastguard Worker } // namespace posix
165*35238bceSAndroid Build Coastguard Worker
PosixTestProcess(void)166*35238bceSAndroid Build Coastguard Worker PosixTestProcess::PosixTestProcess(void)
167*35238bceSAndroid Build Coastguard Worker : m_process(DE_NULL)
168*35238bceSAndroid Build Coastguard Worker , m_processStartTime(0)
169*35238bceSAndroid Build Coastguard Worker , m_infoBuffer(INFO_BUFFER_BLOCK_SIZE, INFO_BUFFER_NUM_BLOCKS)
170*35238bceSAndroid Build Coastguard Worker , m_stdOutReader(&m_infoBuffer)
171*35238bceSAndroid Build Coastguard Worker , m_stdErrReader(&m_infoBuffer)
172*35238bceSAndroid Build Coastguard Worker , m_logReader(LOG_BUFFER_BLOCK_SIZE, LOG_BUFFER_NUM_BLOCKS)
173*35238bceSAndroid Build Coastguard Worker {
174*35238bceSAndroid Build Coastguard Worker }
175*35238bceSAndroid Build Coastguard Worker
~PosixTestProcess(void)176*35238bceSAndroid Build Coastguard Worker PosixTestProcess::~PosixTestProcess(void)
177*35238bceSAndroid Build Coastguard Worker {
178*35238bceSAndroid Build Coastguard Worker delete m_process;
179*35238bceSAndroid Build Coastguard Worker }
180*35238bceSAndroid Build Coastguard Worker
start(const char * name,const char * params,const char * workingDir,const char * caseList)181*35238bceSAndroid Build Coastguard Worker void PosixTestProcess::start(const char *name, const char *params, const char *workingDir, const char *caseList)
182*35238bceSAndroid Build Coastguard Worker {
183*35238bceSAndroid Build Coastguard Worker bool hasCaseList = strlen(caseList) > 0;
184*35238bceSAndroid Build Coastguard Worker
185*35238bceSAndroid Build Coastguard Worker XS_CHECK(!m_process);
186*35238bceSAndroid Build Coastguard Worker
187*35238bceSAndroid Build Coastguard Worker de::FilePath logFilePath = de::FilePath::join(workingDir, "TestResults.qpa");
188*35238bceSAndroid Build Coastguard Worker m_logFileName = logFilePath.getPath();
189*35238bceSAndroid Build Coastguard Worker
190*35238bceSAndroid Build Coastguard Worker // Remove old file if such exists.
191*35238bceSAndroid Build Coastguard Worker if (deFileExists(m_logFileName.c_str()))
192*35238bceSAndroid Build Coastguard Worker {
193*35238bceSAndroid Build Coastguard Worker if (!deDeleteFile(m_logFileName.c_str()) || deFileExists(m_logFileName.c_str()))
194*35238bceSAndroid Build Coastguard Worker throw TestProcessException(string("Failed to remove '") + m_logFileName + "'");
195*35238bceSAndroid Build Coastguard Worker }
196*35238bceSAndroid Build Coastguard Worker
197*35238bceSAndroid Build Coastguard Worker // Construct command line.
198*35238bceSAndroid Build Coastguard Worker string cmdLine = de::FilePath(name).isAbsolutePath() ? name : de::FilePath::join(workingDir, name).getPath();
199*35238bceSAndroid Build Coastguard Worker cmdLine += string(" --deqp-log-filename=") + logFilePath.getBaseName();
200*35238bceSAndroid Build Coastguard Worker
201*35238bceSAndroid Build Coastguard Worker if (hasCaseList)
202*35238bceSAndroid Build Coastguard Worker cmdLine += " --deqp-stdin-caselist";
203*35238bceSAndroid Build Coastguard Worker
204*35238bceSAndroid Build Coastguard Worker if (strlen(params) > 0)
205*35238bceSAndroid Build Coastguard Worker cmdLine += string(" ") + params;
206*35238bceSAndroid Build Coastguard Worker
207*35238bceSAndroid Build Coastguard Worker DE_ASSERT(!m_process);
208*35238bceSAndroid Build Coastguard Worker m_process = new de::Process();
209*35238bceSAndroid Build Coastguard Worker
210*35238bceSAndroid Build Coastguard Worker try
211*35238bceSAndroid Build Coastguard Worker {
212*35238bceSAndroid Build Coastguard Worker m_process->start(cmdLine.c_str(), strlen(workingDir) > 0 ? workingDir : DE_NULL);
213*35238bceSAndroid Build Coastguard Worker }
214*35238bceSAndroid Build Coastguard Worker catch (const de::ProcessError &e)
215*35238bceSAndroid Build Coastguard Worker {
216*35238bceSAndroid Build Coastguard Worker delete m_process;
217*35238bceSAndroid Build Coastguard Worker m_process = DE_NULL;
218*35238bceSAndroid Build Coastguard Worker throw TestProcessException(e.what());
219*35238bceSAndroid Build Coastguard Worker }
220*35238bceSAndroid Build Coastguard Worker
221*35238bceSAndroid Build Coastguard Worker m_processStartTime = deGetMicroseconds();
222*35238bceSAndroid Build Coastguard Worker
223*35238bceSAndroid Build Coastguard Worker // Create stdout & stderr readers.
224*35238bceSAndroid Build Coastguard Worker if (m_process->getStdOut())
225*35238bceSAndroid Build Coastguard Worker m_stdOutReader.start(m_process->getStdOut());
226*35238bceSAndroid Build Coastguard Worker
227*35238bceSAndroid Build Coastguard Worker if (m_process->getStdErr())
228*35238bceSAndroid Build Coastguard Worker m_stdErrReader.start(m_process->getStdErr());
229*35238bceSAndroid Build Coastguard Worker
230*35238bceSAndroid Build Coastguard Worker // Start case list writer.
231*35238bceSAndroid Build Coastguard Worker if (hasCaseList)
232*35238bceSAndroid Build Coastguard Worker {
233*35238bceSAndroid Build Coastguard Worker deFile *dst = m_process->getStdIn();
234*35238bceSAndroid Build Coastguard Worker if (dst)
235*35238bceSAndroid Build Coastguard Worker m_caseListWriter.start(caseList, dst);
236*35238bceSAndroid Build Coastguard Worker else
237*35238bceSAndroid Build Coastguard Worker {
238*35238bceSAndroid Build Coastguard Worker cleanup();
239*35238bceSAndroid Build Coastguard Worker throw TestProcessException("Failed to write case list");
240*35238bceSAndroid Build Coastguard Worker }
241*35238bceSAndroid Build Coastguard Worker }
242*35238bceSAndroid Build Coastguard Worker }
243*35238bceSAndroid Build Coastguard Worker
terminate(void)244*35238bceSAndroid Build Coastguard Worker void PosixTestProcess::terminate(void)
245*35238bceSAndroid Build Coastguard Worker {
246*35238bceSAndroid Build Coastguard Worker if (m_process)
247*35238bceSAndroid Build Coastguard Worker {
248*35238bceSAndroid Build Coastguard Worker try
249*35238bceSAndroid Build Coastguard Worker {
250*35238bceSAndroid Build Coastguard Worker m_process->kill();
251*35238bceSAndroid Build Coastguard Worker }
252*35238bceSAndroid Build Coastguard Worker catch (const std::exception &e)
253*35238bceSAndroid Build Coastguard Worker {
254*35238bceSAndroid Build Coastguard Worker printf("PosixTestProcess::terminate(): Failed to kill process: %s\n", e.what());
255*35238bceSAndroid Build Coastguard Worker }
256*35238bceSAndroid Build Coastguard Worker }
257*35238bceSAndroid Build Coastguard Worker }
258*35238bceSAndroid Build Coastguard Worker
cleanup(void)259*35238bceSAndroid Build Coastguard Worker void PosixTestProcess::cleanup(void)
260*35238bceSAndroid Build Coastguard Worker {
261*35238bceSAndroid Build Coastguard Worker m_caseListWriter.stop();
262*35238bceSAndroid Build Coastguard Worker m_logReader.stop();
263*35238bceSAndroid Build Coastguard Worker
264*35238bceSAndroid Build Coastguard Worker // \note Info buffer must be canceled before stopping pipe readers.
265*35238bceSAndroid Build Coastguard Worker m_infoBuffer.cancel();
266*35238bceSAndroid Build Coastguard Worker
267*35238bceSAndroid Build Coastguard Worker m_stdErrReader.stop();
268*35238bceSAndroid Build Coastguard Worker m_stdOutReader.stop();
269*35238bceSAndroid Build Coastguard Worker
270*35238bceSAndroid Build Coastguard Worker // Reset info buffer.
271*35238bceSAndroid Build Coastguard Worker m_infoBuffer.clear();
272*35238bceSAndroid Build Coastguard Worker
273*35238bceSAndroid Build Coastguard Worker if (m_process)
274*35238bceSAndroid Build Coastguard Worker {
275*35238bceSAndroid Build Coastguard Worker try
276*35238bceSAndroid Build Coastguard Worker {
277*35238bceSAndroid Build Coastguard Worker if (m_process->isRunning())
278*35238bceSAndroid Build Coastguard Worker {
279*35238bceSAndroid Build Coastguard Worker m_process->kill();
280*35238bceSAndroid Build Coastguard Worker m_process->waitForFinish();
281*35238bceSAndroid Build Coastguard Worker }
282*35238bceSAndroid Build Coastguard Worker }
283*35238bceSAndroid Build Coastguard Worker catch (const de::ProcessError &e)
284*35238bceSAndroid Build Coastguard Worker {
285*35238bceSAndroid Build Coastguard Worker printf("PosixTestProcess::stop(): Failed to kill process: %s\n", e.what());
286*35238bceSAndroid Build Coastguard Worker }
287*35238bceSAndroid Build Coastguard Worker
288*35238bceSAndroid Build Coastguard Worker delete m_process;
289*35238bceSAndroid Build Coastguard Worker m_process = DE_NULL;
290*35238bceSAndroid Build Coastguard Worker }
291*35238bceSAndroid Build Coastguard Worker }
292*35238bceSAndroid Build Coastguard Worker
isRunning(void)293*35238bceSAndroid Build Coastguard Worker bool PosixTestProcess::isRunning(void)
294*35238bceSAndroid Build Coastguard Worker {
295*35238bceSAndroid Build Coastguard Worker if (m_process)
296*35238bceSAndroid Build Coastguard Worker return m_process->isRunning();
297*35238bceSAndroid Build Coastguard Worker else
298*35238bceSAndroid Build Coastguard Worker return false;
299*35238bceSAndroid Build Coastguard Worker }
300*35238bceSAndroid Build Coastguard Worker
getExitCode(void) const301*35238bceSAndroid Build Coastguard Worker int PosixTestProcess::getExitCode(void) const
302*35238bceSAndroid Build Coastguard Worker {
303*35238bceSAndroid Build Coastguard Worker if (m_process)
304*35238bceSAndroid Build Coastguard Worker return m_process->getExitCode();
305*35238bceSAndroid Build Coastguard Worker else
306*35238bceSAndroid Build Coastguard Worker return -1;
307*35238bceSAndroid Build Coastguard Worker }
308*35238bceSAndroid Build Coastguard Worker
readTestLog(uint8_t * dst,int numBytes)309*35238bceSAndroid Build Coastguard Worker int PosixTestProcess::readTestLog(uint8_t *dst, int numBytes)
310*35238bceSAndroid Build Coastguard Worker {
311*35238bceSAndroid Build Coastguard Worker if (!m_logReader.isRunning())
312*35238bceSAndroid Build Coastguard Worker {
313*35238bceSAndroid Build Coastguard Worker if (deGetMicroseconds() - m_processStartTime > LOG_FILE_TIMEOUT * 1000)
314*35238bceSAndroid Build Coastguard Worker {
315*35238bceSAndroid Build Coastguard Worker // Timeout, kill process.
316*35238bceSAndroid Build Coastguard Worker terminate();
317*35238bceSAndroid Build Coastguard Worker return 0; // \todo [2013-08-13 pyry] Throw exception?
318*35238bceSAndroid Build Coastguard Worker }
319*35238bceSAndroid Build Coastguard Worker
320*35238bceSAndroid Build Coastguard Worker if (!deFileExists(m_logFileName.c_str()))
321*35238bceSAndroid Build Coastguard Worker return 0;
322*35238bceSAndroid Build Coastguard Worker
323*35238bceSAndroid Build Coastguard Worker // Start reader.
324*35238bceSAndroid Build Coastguard Worker m_logReader.start(m_logFileName.c_str());
325*35238bceSAndroid Build Coastguard Worker }
326*35238bceSAndroid Build Coastguard Worker
327*35238bceSAndroid Build Coastguard Worker DE_ASSERT(m_logReader.isRunning());
328*35238bceSAndroid Build Coastguard Worker return m_logReader.read(dst, numBytes);
329*35238bceSAndroid Build Coastguard Worker }
330*35238bceSAndroid Build Coastguard Worker
331*35238bceSAndroid Build Coastguard Worker } // namespace xs
332