• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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