1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Android ExecServer.
22 *//*--------------------------------------------------------------------*/
24 #include "tcuAndroidExecService.hpp"
29 # define DBG_PRINT(ARGS) print ARGS
31 # define DBG_PRINT(ARGS)
39 static const char* LOG_FILE_NAME = "/sdcard/dEQP-log.qpa";
43 PROCESS_START_TIMEOUT = 5000*1000, //!< Timeout in usec.
44 PROCESS_QUERY_INTERVAL = 1000*1000 //!< Running query interval limit in usec.
47 static void checkJniException (JNIEnv* env, const char* file, int line)
49 if (env->ExceptionOccurred())
51 env->ExceptionDescribe();
52 env->ExceptionClear();
53 throw InternalError("JNI Exception", DE_NULL, file, line);
57 #define JNI_CHECK(EXPR) do { checkJniException(env, __FILE__, __LINE__); TCU_CHECK_INTERNAL(EXPR); } while (deGetFalse())
61 TestProcess::TestProcess (JavaVM* vm, jobject context)
70 , m_lastRunningStatus (false)
71 , m_logReader (xs::LOG_BUFFER_BLOCK_SIZE, xs::LOG_BUFFER_NUM_BLOCKS)
73 DBG_PRINT(("TestProcess::TestProcess(%p, %p)", vm, context));
75 JNIEnv* env = getCurrentThreadEnv();
77 jstring logFileName = 0;
84 remoteCls = env->FindClass("com/drawelements/deqp/testercore/RemoteAPI");
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);
93 ctorId = env->GetMethodID(m_remoteCls, "<init>", "(Landroid/content/Context;Ljava/lang/String;)V");
96 logFileName = env->NewStringUTF(LOG_FILE_NAME);
97 JNI_CHECK(logFileName);
99 // Create RemoteAPI instance.
100 remote = env->NewObject(m_remoteCls, ctorId, context, logFileName);
103 env->DeleteLocalRef(logFileName);
106 // Acquire global reference to remote.
107 m_remote = env->NewGlobalRef(remote);
109 env->DeleteLocalRef(remote);
112 m_start = env->GetMethodID(m_remoteCls, "start", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z");
115 m_kill = env->GetMethodID(m_remoteCls, "kill", "()Z");
118 m_isRunning = env->GetMethodID(m_remoteCls, "isRunning", "()Z");
119 JNI_CHECK(m_isRunning);
124 env->DeleteLocalRef(logFileName);
126 env->DeleteLocalRef(remote);
128 env->DeleteGlobalRef(reinterpret_cast<jobject>(m_remoteCls));
130 env->DeleteGlobalRef(m_remote);
135 TestProcess::~TestProcess (void)
137 DBG_PRINT(("TestProcess::~TestProcess()"));
141 JNIEnv* env = getCurrentThreadEnv();
142 env->DeleteGlobalRef(m_remote);
143 env->DeleteGlobalRef(m_remoteCls);
150 void TestProcess::start (const char* name, const char* params, const char* workingDir, const char* caseList)
152 DBG_PRINT(("TestProcess::start(%s, %s, %s, ...)", name, params, workingDir));
154 JNIEnv* env = getCurrentThreadEnv();
156 jstring paramsStr = 0;
157 jstring caseListStr = 0;
159 DE_UNREF(workingDir);
161 // Remove old log file if such exists.
162 if (deFileExists(LOG_FILE_NAME))
164 if (!deDeleteFile(LOG_FILE_NAME) || deFileExists(LOG_FILE_NAME))
165 throw xs::TestProcessException(std::string("Failed to remove '") + LOG_FILE_NAME + "'");
170 nameStr = env->NewStringUTF(name);
173 paramsStr = env->NewStringUTF(params);
174 JNI_CHECK(paramsStr);
176 caseListStr = env->NewStringUTF(caseList);
177 JNI_CHECK(caseListStr);
179 jboolean res = env->CallBooleanMethod(m_remote, m_start, nameStr, paramsStr, caseListStr);
180 checkJniException(env, __FILE__, __LINE__);
182 if (res == JNI_FALSE)
183 throw xs::TestProcessException("Failed to launch activity");
185 m_launchTime = deGetMicroseconds();
186 m_lastQueryTime = m_launchTime;
187 m_lastRunningStatus = true;
192 env->DeleteLocalRef(nameStr);
194 env->DeleteLocalRef(paramsStr);
196 env->DeleteLocalRef(caseListStr);
200 env->DeleteLocalRef(nameStr);
201 env->DeleteLocalRef(paramsStr);
202 env->DeleteLocalRef(caseListStr);
205 void TestProcess::terminate (void)
207 DBG_PRINT(("TestProcess::terminate()"));
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.
215 void TestProcess::cleanup (void)
217 DBG_PRINT(("TestProcess::cleanup()"));
223 bool TestProcess::isRunning (void)
225 deUint64 curTime = deGetMicroseconds();
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;
232 JNIEnv* env = getCurrentThreadEnv();
233 jboolean res = env->CallBooleanMethod(m_remote, m_isRunning);
234 checkJniException(env, __FILE__, __LINE__);
236 DBG_PRINT(("TestProcess::isRunning(): %s", res == JNI_TRUE ? "true" : "false"));
237 m_lastQueryTime = curTime;
238 m_lastRunningStatus = res == JNI_TRUE;
240 return m_lastRunningStatus;
243 JNIEnv* TestProcess::getCurrentThreadEnv (void)
245 JNIEnv* env = DE_NULL;
246 jint ret = m_vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
251 throw InternalError("GetEnv() failed");
254 int TestProcess::readTestLog (deUint8* dst, int numBytes)
256 if (!m_logReader.isRunning())
258 if (deGetMicroseconds() - m_launchTime > xs::LOG_FILE_TIMEOUT*1000)
260 // Timeout, kill process.
262 DBG_PRINT(("TestProcess:readTestLog(): Log file timeout occurred!"));
263 return 0; // \todo [2013-08-13 pyry] Throw exception?
266 if (!deFileExists(LOG_FILE_NAME))
270 m_logReader.start(LOG_FILE_NAME);
273 DE_ASSERT(m_logReader.isRunning());
274 return m_logReader.read(dst, numBytes);
277 int TestProcess::getExitCode (void) const
282 int TestProcess::readInfoLog (deUint8* dst, int numBytes)
284 // \todo [2012-11-12 pyry] Read device log.
285 DE_UNREF(dst && numBytes);
291 ExecutionServer::ExecutionServer (JavaVM* vm, xs::TestProcess* testProcess, deSocketFamily family, int port, RunMode runMode)
292 : xs::ExecutionServer (testProcess, family, port, runMode)
297 xs::ConnectionHandler* ExecutionServer::createHandler (de::Socket* socket, const de::SocketAddress& clientAddress)
299 DE_UNREF(clientAddress);
300 return new ConnectionHandler(m_vm, this, socket);
305 ConnectionHandler::ConnectionHandler (JavaVM* vm, xs::ExecutionServer* server, de::Socket* socket)
306 : xs::ExecutionRequestHandler (server, socket)
311 void ConnectionHandler::run (void)
313 JNIEnv* env = DE_NULL;
314 if (m_vm->AttachCurrentThread(&env, DE_NULL) != 0)
316 print("AttachCurrentThread() failed");
320 xs::ExecutionRequestHandler::run();
322 if (m_vm->DetachCurrentThread() != 0)
323 print("DetachCurrentThread() failed");
328 ServerThread::ServerThread (JavaVM* vm, xs::TestProcess* process, deSocketFamily family, int port)
329 : m_server(vm, process, family, port, xs::ExecutionServer::RUNMODE_FOREVER)
333 void ServerThread::run (void)
337 m_server.runServer();
339 catch (const std::exception& e)
341 die("ServerThread::run(): %s", e.what());
345 void ServerThread::stop (void)
347 m_server.stopServer();
353 ExecService::ExecService (JavaVM* vm, jobject context, int port, deSocketFamily family)
354 : m_process (vm, context)
355 , m_thread (vm, &m_process, family, port)
359 ExecService::~ExecService (void)
363 void ExecService::start (void)
368 void ExecService::stop (void)