Merge "Further relax line verification in primitive bbox tests" into nougat-cts-dev...
[platform/upstream/VK-GL-CTS.git] / framework / platform / android / tcuAndroidExecService.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
3  * ----------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Android ExecServer.
22  *//*--------------------------------------------------------------------*/
23
24 #include "tcuAndroidExecService.hpp"
25 #include "deFile.h"
26 #include "deClock.h"
27
28 #if 0
29 #       define DBG_PRINT(ARGS) print ARGS
30 #else
31 #       define DBG_PRINT(ARGS)
32 #endif
33
34 namespace tcu
35 {
36 namespace Android
37 {
38
39 static const char* LOG_FILE_NAME = "/sdcard/dEQP-log.qpa";
40
41 enum
42 {
43         PROCESS_START_TIMEOUT   = 5000*1000,    //!< Timeout in usec.
44         PROCESS_QUERY_INTERVAL  = 1000*1000             //!< Running query interval limit in usec.
45 };
46
47 static void checkJniException (JNIEnv* env, const char* file, int line)
48 {
49         if (env->ExceptionOccurred())
50         {
51                 env->ExceptionDescribe();
52                 env->ExceptionClear();
53                 throw InternalError("JNI Exception", DE_NULL, file, line);
54         }
55 }
56
57 #define JNI_CHECK(EXPR) do { checkJniException(env, __FILE__, __LINE__); TCU_CHECK_INTERNAL(EXPR); } while (deGetFalse())
58
59 // TestProcess
60
61 TestProcess::TestProcess (JavaVM* vm, jobject context)
62         : m_vm                                  (vm)
63         , m_remoteCls                   (0)
64         , m_remote                              (0)
65         , m_start                               (0)
66         , m_kill                                (0)
67         , m_isRunning                   (0)
68         , m_launchTime                  (0)
69         , m_lastQueryTime               (0)
70         , m_lastRunningStatus   (false)
71         , m_logReader                   (xs::LOG_BUFFER_BLOCK_SIZE, xs::LOG_BUFFER_NUM_BLOCKS)
72 {
73         DBG_PRINT(("TestProcess::TestProcess(%p, %p)", vm, context));
74
75         JNIEnv* env                     = getCurrentThreadEnv();
76         jobject remote          = 0;
77         jstring logFileName     = 0;
78
79         try
80         {
81                 jclass          remoteCls       = 0;
82                 jmethodID       ctorId          = 0;
83
84                 remoteCls = env->FindClass("com/drawelements/deqp/testercore/RemoteAPI");
85                 JNI_CHECK(remoteCls);
86
87                 // Acquire global reference to RemoteAPI class.
88                 m_remoteCls = reinterpret_cast<jclass>(env->NewGlobalRef(remoteCls));
89                 JNI_CHECK(m_remoteCls);
90                 env->DeleteLocalRef(remoteCls);
91                 remoteCls = 0;
92
93                 ctorId = env->GetMethodID(m_remoteCls, "<init>", "(Landroid/content/Context;Ljava/lang/String;)V");
94                 JNI_CHECK(ctorId);
95
96                 logFileName = env->NewStringUTF(LOG_FILE_NAME);
97                 JNI_CHECK(logFileName);
98
99                 // Create RemoteAPI instance.
100                 remote = env->NewObject(m_remoteCls, ctorId, context, logFileName);
101                 JNI_CHECK(remote);
102
103                 env->DeleteLocalRef(logFileName);
104                 logFileName = 0;
105
106                 // Acquire global reference to remote.
107                 m_remote = env->NewGlobalRef(remote);
108                 JNI_CHECK(m_remote);
109                 env->DeleteLocalRef(remote);
110                 remote = 0;
111
112                 m_start = env->GetMethodID(m_remoteCls, "start", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z");
113                 JNI_CHECK(m_start);
114
115                 m_kill = env->GetMethodID(m_remoteCls, "kill", "()Z");
116                 JNI_CHECK(m_kill);
117
118                 m_isRunning = env->GetMethodID(m_remoteCls, "isRunning", "()Z");
119                 JNI_CHECK(m_isRunning);
120         }
121         catch (...)
122         {
123                 if (logFileName)
124                         env->DeleteLocalRef(logFileName);
125                 if (remote)
126                         env->DeleteLocalRef(remote);
127                 if (m_remoteCls)
128                         env->DeleteGlobalRef(reinterpret_cast<jobject>(m_remoteCls));
129                 if (m_remote)
130                         env->DeleteGlobalRef(m_remote);
131                 throw;
132         }
133 }
134
135 TestProcess::~TestProcess (void)
136 {
137         DBG_PRINT(("TestProcess::~TestProcess()"));
138
139         try
140         {
141                 JNIEnv* env = getCurrentThreadEnv();
142                 env->DeleteGlobalRef(m_remote);
143                 env->DeleteGlobalRef(m_remoteCls);
144         }
145         catch (...)
146         {
147         }
148 }
149
150 void TestProcess::start (const char* name, const char* params, const char* workingDir, const char* caseList)
151 {
152         DBG_PRINT(("TestProcess::start(%s, %s, %s, ...)", name, params, workingDir));
153
154         JNIEnv* env                     = getCurrentThreadEnv();
155         jstring nameStr         = 0;
156         jstring paramsStr       = 0;
157         jstring caseListStr     = 0;
158
159         DE_UNREF(workingDir);
160
161         // Remove old log file if such exists.
162         if (deFileExists(LOG_FILE_NAME))
163         {
164                 if (!deDeleteFile(LOG_FILE_NAME) || deFileExists(LOG_FILE_NAME))
165                         throw xs::TestProcessException(std::string("Failed to remove '") + LOG_FILE_NAME + "'");
166         }
167
168         try
169         {
170                 nameStr = env->NewStringUTF(name);
171                 JNI_CHECK(nameStr);
172
173                 paramsStr = env->NewStringUTF(params);
174                 JNI_CHECK(paramsStr);
175
176                 caseListStr = env->NewStringUTF(caseList);
177                 JNI_CHECK(caseListStr);
178
179                 jboolean res = env->CallBooleanMethod(m_remote, m_start, nameStr, paramsStr, caseListStr);
180                 checkJniException(env, __FILE__, __LINE__);
181
182                 if (res == JNI_FALSE)
183                         throw xs::TestProcessException("Failed to launch activity");
184
185                 m_launchTime            = deGetMicroseconds();
186                 m_lastQueryTime         = m_launchTime;
187                 m_lastRunningStatus     = true;
188         }
189         catch (...)
190         {
191                 if (nameStr)
192                         env->DeleteLocalRef(nameStr);
193                 if (paramsStr)
194                         env->DeleteLocalRef(paramsStr);
195                 if (caseListStr)
196                         env->DeleteLocalRef(caseListStr);
197                 throw;
198         }
199
200         env->DeleteLocalRef(nameStr);
201         env->DeleteLocalRef(paramsStr);
202         env->DeleteLocalRef(caseListStr);
203 }
204
205 void TestProcess::terminate (void)
206 {
207         DBG_PRINT(("TestProcess::terminate()"));
208
209         JNIEnv*         env             = getCurrentThreadEnv();
210         jboolean        res             = env->CallBooleanMethod(m_remote, m_kill);
211         checkJniException(env, __FILE__, __LINE__);
212         DE_UNREF(res); // Failure to kill process is ignored.
213 }
214
215 void TestProcess::cleanup (void)
216 {
217         DBG_PRINT(("TestProcess::cleanup()"));
218
219         terminate();
220         m_logReader.stop();
221 }
222
223 bool TestProcess::isRunning (void)
224 {
225         deUint64 curTime = deGetMicroseconds();
226
227         // On Android process launch is asynchronous so we don't want to poll for process until after some time.
228         if (curTime-m_launchTime < PROCESS_START_TIMEOUT ||
229                 curTime-m_lastQueryTime < PROCESS_QUERY_INTERVAL)
230                 return m_lastRunningStatus;
231
232         JNIEnv*         env             = getCurrentThreadEnv();
233         jboolean        res             = env->CallBooleanMethod(m_remote, m_isRunning);
234         checkJniException(env, __FILE__, __LINE__);
235
236         DBG_PRINT(("TestProcess::isRunning(): %s", res == JNI_TRUE ? "true" : "false"));
237         m_lastQueryTime         = curTime;
238         m_lastRunningStatus     = res == JNI_TRUE;
239
240         return m_lastRunningStatus;
241 }
242
243 JNIEnv* TestProcess::getCurrentThreadEnv (void)
244 {
245         JNIEnv* env = DE_NULL;
246         jint    ret     = m_vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
247
248         if (ret == JNI_OK)
249                 return env;
250         else
251                 throw InternalError("GetEnv() failed");
252 }
253
254 int TestProcess::readTestLog (deUint8* dst, int numBytes)
255 {
256         if (!m_logReader.isRunning())
257         {
258                 if (deGetMicroseconds() - m_launchTime > xs::LOG_FILE_TIMEOUT*1000)
259                 {
260                         // Timeout, kill process.
261                         terminate();
262                         DBG_PRINT(("TestProcess:readTestLog(): Log file timeout occurred!"));
263                         return 0; // \todo [2013-08-13 pyry] Throw exception?
264                 }
265
266                 if (!deFileExists(LOG_FILE_NAME))
267                         return 0;
268
269                 // Start reader.
270                 m_logReader.start(LOG_FILE_NAME);
271         }
272
273         DE_ASSERT(m_logReader.isRunning());
274         return m_logReader.read(dst, numBytes);
275 }
276
277 int     TestProcess::getExitCode (void) const
278 {
279         return 0;
280 }
281
282 int TestProcess::readInfoLog (deUint8* dst, int numBytes)
283 {
284         // \todo [2012-11-12 pyry] Read device log.
285         DE_UNREF(dst && numBytes);
286         return 0;
287 }
288
289 // ExecutionServer
290
291 ExecutionServer::ExecutionServer (JavaVM* vm, xs::TestProcess* testProcess, deSocketFamily family, int port, RunMode runMode)
292         : xs::ExecutionServer   (testProcess, family, port, runMode)
293         , m_vm                                  (vm)
294 {
295 }
296
297 xs::ConnectionHandler* ExecutionServer::createHandler (de::Socket* socket, const de::SocketAddress& clientAddress)
298 {
299         DE_UNREF(clientAddress);
300         return new ConnectionHandler(m_vm, this, socket);
301 }
302
303 // ConnectionHandler
304
305 ConnectionHandler::ConnectionHandler (JavaVM* vm, xs::ExecutionServer* server, de::Socket* socket)
306         : xs::ExecutionRequestHandler   (server, socket)
307         , m_vm                                                  (vm)
308 {
309 }
310
311 void ConnectionHandler::run (void)
312 {
313         JNIEnv* env = DE_NULL;
314         if (m_vm->AttachCurrentThread(&env, DE_NULL) != 0)
315         {
316                 print("AttachCurrentThread() failed");
317                 return;
318         }
319
320         xs::ExecutionRequestHandler::run();
321
322         if (m_vm->DetachCurrentThread() != 0)
323                 print("DetachCurrentThread() failed");
324 }
325
326 // ServerThread
327
328 ServerThread::ServerThread (JavaVM* vm, xs::TestProcess* process, deSocketFamily family, int port)
329         : m_server(vm, process, family, port, xs::ExecutionServer::RUNMODE_FOREVER)
330 {
331 }
332
333 void ServerThread::run (void)
334 {
335         try
336         {
337                 m_server.runServer();
338         }
339         catch (const std::exception& e)
340         {
341                 die("ServerThread::run(): %s", e.what());
342         }
343 }
344
345 void ServerThread::stop (void)
346 {
347         m_server.stopServer();
348         join();
349 }
350
351 // ExecService
352
353 ExecService::ExecService (JavaVM* vm, jobject context, int port, deSocketFamily family)
354         : m_process             (vm, context)
355         , m_thread              (vm, &m_process, family, port)
356 {
357 }
358
359 ExecService::~ExecService (void)
360 {
361 }
362
363 void ExecService::start (void)
364 {
365         m_thread.start();
366 }
367
368 void ExecService::stop (void)
369 {
370         m_thread.stop();
371 }
372
373 } // Android
374 } // tcu