1 /* //device/apps/Quake/quake/src/QW/client/main.c
2 **
3 ** Copyright 2007, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include <nativehelper/jni.h>
19 #include <stdio.h>
20 #include <assert.h>
21 #include <dlfcn.h>
22
23 #if !defined(__clang__)
24 #include <bcc/bcc.h>
25 #endif
26
27 #include <android/log.h>
28
29 #define LOG_TAG "Quake masterMain"
30 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
31 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
32
33 #if !defined(__clang__)
34 int AndroidInit();
35 int AndroidEvent2(int type, int value);
36 int AndroidMotionEvent(unsigned long long eventTime, int action, float x, float y, float pressure, float size, int deviceId);
37 int AndroidTrackballEvent(unsigned long long eventTime, int action, float x, float y);
38 int AndroidStep(int width, int height);
39 void AndroidQuit();
40
41 typedef int (*pAndroidInitType)();
42 typedef int (*pAndroidEvent2Type)(int type, int value);
43 typedef int (*pAndroidMotionEventType)(unsigned long long eventTime, int action, float x, float y, float pressure, float size, int deviceId);
44 typedef int (*pAndroidTrackballEventType)(unsigned long long eventTime, int action, float x, float y);
45 typedef int (*pAndroidStepType)(int width, int height);
46 typedef void (*pAndroidQuitType)();
47
48 static pAndroidInitType pAndroidInit;
49 static pAndroidEvent2Type pAndroidEvent2;
50 static pAndroidMotionEventType pAndroidMotionEvent;
51 static pAndroidTrackballEventType pAndroidTrackballEvent;
52 static pAndroidStepType pAndroidStep;
53 static pAndroidQuitType pAndroidQuit;
54
55 static int use_llvm = 1;
56
57 jboolean
qinit(JNIEnv * env,jobject thiz)58 qinit(JNIEnv *env, jobject thiz) {
59 LOGI("qinit");
60 return pAndroidInit() ? JNI_TRUE : JNI_FALSE;
61 }
62
63 jboolean
qevent(JNIEnv * env,jobject thiz,jint type,jint value)64 qevent(JNIEnv *env, jobject thiz, jint type, jint value) {
65 return pAndroidEvent2(type, value) ? JNI_TRUE : JNI_FALSE;
66 }
67
68 jboolean
qmotionevent(JNIEnv * env,jobject thiz,jlong eventTime,jint action,jfloat x,jfloat y,jfloat pressure,jfloat size,jint deviceId)69 qmotionevent(JNIEnv *env, jobject thiz, jlong eventTime, jint action,
70 jfloat x, jfloat y, jfloat pressure, jfloat size, jint deviceId) {
71 return pAndroidMotionEvent((unsigned long long) eventTime,
72 action, x, y, pressure, size,
73 deviceId) ? JNI_TRUE : JNI_FALSE;
74 }
75
76 jboolean
qtrackballevent(JNIEnv * env,jobject thiz,jlong eventTime,jint action,jfloat x,jfloat y)77 qtrackballevent(JNIEnv *env, jobject thiz, jlong eventTime, jint action,
78 jfloat x, jfloat y) {
79 return pAndroidTrackballEvent((unsigned long long) eventTime,
80 action, x, y) ? JNI_TRUE : JNI_FALSE;
81 }
82
83 jboolean
qstep(JNIEnv * env,jobject thiz,jint width,jint height)84 qstep(JNIEnv *env, jobject thiz, jint width, jint height) {
85 return pAndroidStep(width, height) ? JNI_TRUE : JNI_FALSE;
86 }
87
88 void
qquit(JNIEnv * env,jobject thiz)89 qquit(JNIEnv *env, jobject thiz) {
90 LOGI("qquit");
91 return pAndroidQuit();
92 }
93
lookupSymbol(void * pContext,const char * name)94 static void* lookupSymbol(void* pContext, const char* name)
95 {
96 return (void*) dlsym(RTLD_DEFAULT, name);
97 }
98
99 jboolean
qcompile_bc(JNIEnv * env,jobject thiz,jbyteArray scriptRef,jint length)100 qcompile_bc(JNIEnv *env, jobject thiz, jbyteArray scriptRef, jint length)
101 {
102 if (!use_llvm)
103 return JNI_TRUE;
104
105 pAndroidInitType new_pAndroidInit;
106 pAndroidEvent2Type new_pAndroidEvent2;
107 pAndroidMotionEventType new_pAndroidMotionEvent;
108 pAndroidTrackballEventType new_pAndroidTrackballEvent;
109 pAndroidStepType new_pAndroidStep;
110 pAndroidQuitType new_pAndroidQuit;
111 int all_func_found = 1;
112
113 BCCScriptRef script_ref = bccCreateScript();
114 jbyte* script_ptr = (jbyte *)env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0);
115 LOGI("BCC Script Len: %d", length);
116 if (bccReadBC(script_ref, "libquake_portable.bc", (const char*)script_ptr, length, 0)) {
117 LOGE("Error! Cannot bccReadBc");
118 return JNI_FALSE;
119 }
120 if (script_ptr) {
121 env->ReleasePrimitiveArrayCritical(scriptRef, script_ptr, 0);
122 }
123 #if 0
124 if (bccLinkFile(script_ref, "/system/lib/libclcore.bc", 0)) {
125 LOGE("Error! Cannot bccLinkBC");
126 return JNI_FALSE;
127 }
128 #endif
129 bccRegisterSymbolCallback(script_ref, lookupSymbol, NULL);
130 if (bccPrepareExecutableEx(script_ref, ".", "/data/data/com.android.quake.llvm/quakeLLVM", 0)) {
131 LOGE("Error! Cannot bccPrepareExecutableEx");
132 return JNI_FALSE;
133 }
134
135 new_pAndroidInit = (pAndroidInitType)bccGetFuncAddr(script_ref, "AndroidInit_LLVM");
136 if (new_pAndroidInit == NULL) {
137 LOGE("Error! Cannot find AndroidInit_LLVM()");
138 all_func_found = 0;
139 //return JNI_FALSE;
140 }
141 LOGI("Found AndroidInit_LLVM() @ 0x%x", (unsigned)new_pAndroidInit);
142
143 new_pAndroidEvent2 = (pAndroidEvent2Type)bccGetFuncAddr(script_ref, "AndroidEvent2_LLVM");
144 if (new_pAndroidEvent2 == NULL) {
145 LOGE("Error! Cannot find AndroidEvent2_LLVM()");
146 all_func_found = 0;
147 //return JNI_FALSE;
148 }
149 LOGI("Found AndroidEvent2_LLVM() @ 0x%x", (unsigned)new_pAndroidEvent2);
150
151 new_pAndroidMotionEvent = (pAndroidMotionEventType)bccGetFuncAddr(script_ref, "AndroidMotionEvent_LLVM");
152 if (new_pAndroidMotionEvent == NULL) {
153 LOGE("Error! Cannot find AndroidMotionEvent_LLVM()");
154 all_func_found = 0;
155 //return JNI_FALSE;
156 }
157 LOGI("Found AndroidMotionEvent_LLVM() @ 0x%x", (unsigned)new_pAndroidMotionEvent);
158
159 new_pAndroidTrackballEvent = (pAndroidTrackballEventType)bccGetFuncAddr(script_ref, "AndroidTrackballEvent_LLVM");
160 if (new_pAndroidTrackballEvent == NULL) {
161 LOGE("Error! Cannot find AndroidTrackballEvent_LLVM()");
162 all_func_found = 0;
163 //return JNI_FALSE;
164 }
165 LOGI("Found AndroidTrackballEvent_LLVM() @ 0x%x", (unsigned)new_pAndroidTrackballEvent);
166
167 new_pAndroidStep = (pAndroidStepType)bccGetFuncAddr(script_ref, "AndroidStep_LLVM");
168 if (new_pAndroidStep == NULL) {
169 LOGE("Error! Cannot find AndroidStep_LLVM()");
170 all_func_found = 0;
171 //return JNI_FALSE;
172 }
173 LOGI("Found AndroidStep_LLVM() @ 0x%x", (unsigned)new_pAndroidStep);
174
175 new_pAndroidQuit = (pAndroidQuitType)bccGetFuncAddr(script_ref, "AndroidQuit_LLVM");
176 if (new_pAndroidQuit == NULL) {
177 LOGE("Error! Cannot find AndroidQuit_LLVM()");
178 all_func_found = 0;
179 //return JNI_FALSE;
180 }
181 LOGI("Found AndroidQuit_LLVM() @ 0x%x", (unsigned)new_pAndroidQuit);
182
183 //bccDisposeScript(script_ref);
184
185 //Uncomment the following
186 if (all_func_found)
187 {
188 LOGI("Use LLVM version");
189 pAndroidInit = new_pAndroidInit;
190 pAndroidEvent2 = new_pAndroidEvent2;
191 pAndroidMotionEvent = new_pAndroidMotionEvent;
192 pAndroidTrackballEvent = new_pAndroidTrackballEvent;
193 pAndroidStep = new_pAndroidStep;
194 pAndroidQuit = new_pAndroidQuit;
195 }
196
197 return JNI_TRUE;
198 }
199
200
201 static const char *classPathName = "com/android/quake/llvm/QuakeLib";
202
203 static JNINativeMethod methods[] = {
204 {"compile_bc", "([BI)Z", (void*)qcompile_bc },
205 {"init", "()Z", (void*)qinit },
206 {"event", "(II)Z", (void*)qevent },
207 {"motionEvent", "(JIFFFFI)Z", (void*) qmotionevent },
208 {"trackballEvent", "(JIFF)Z", (void*) qtrackballevent },
209 {"step", "(II)Z", (void*)qstep },
210 {"quit", "()V", (void*)qquit },
211 };
212
213 /*
214 * Register several native methods for one class.
215 */
registerNativeMethods(JNIEnv * env,const char * className,JNINativeMethod * gMethods,int numMethods)216 static int registerNativeMethods(JNIEnv* env, const char* className,
217 JNINativeMethod* gMethods, int numMethods)
218 {
219 jclass clazz;
220
221 clazz = env->FindClass(className);
222 if (clazz == NULL) {
223 fprintf(stderr,
224 "Native registration unable to find class '%s'\n", className);
225 return JNI_FALSE;
226 }
227 if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
228 fprintf(stderr, "RegisterNatives failed for '%s'\n", className);
229 return JNI_FALSE;
230 }
231
232 return JNI_TRUE;
233 }
234
235 /*
236 * Register native methods for all classes we know about.
237 */
registerNatives(JNIEnv * env)238 static int registerNatives(JNIEnv* env)
239 {
240 if (!registerNativeMethods(env, classPathName,
241 methods, sizeof(methods) / sizeof(methods[0]))) {
242 return JNI_FALSE;
243 }
244
245 return JNI_TRUE;
246 }
247
248 /*
249 * Set some test stuff up.
250 *
251 * Returns the JNI version on success, -1 on failure.
252 */
253
254 typedef union {
255 JNIEnv* env;
256 void* venv;
257 } UnionJNIEnvToVoid;
258
JNI_OnLoad(JavaVM * vm,void * reserved)259 jint JNI_OnLoad(JavaVM* vm, void* reserved)
260 {
261 UnionJNIEnvToVoid uenv;
262 uenv.venv = NULL;
263 jint result = -1;
264 JNIEnv* env = NULL;
265
266 if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
267 fprintf(stderr, "ERROR: GetEnv failed\n");
268 goto bail;
269 }
270 env = uenv.env;
271
272 assert(env != NULL);
273
274 printf("In mgmain JNI_OnLoad\n");
275
276 if (!registerNatives(env)) {
277 fprintf(stderr, "ERROR: quakemaster native registration failed\n");
278 goto bail;
279 }
280
281 /* success -- return valid version number */
282 result = JNI_VERSION_1_4;
283
284 pAndroidInit = AndroidInit;
285 pAndroidEvent2 = AndroidEvent2;
286 pAndroidMotionEvent = AndroidMotionEvent;
287 pAndroidTrackballEvent = AndroidTrackballEvent;
288 pAndroidStep = AndroidStep;
289 pAndroidQuit = AndroidQuit;
290
291 bail:
292 return result;
293 }
294
295
296 #endif // __clang__
297