3dphotoshoot

view src/android/native_glue.c @ 7:7f6e6eb3d20e

some progress...
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 23 May 2015 23:14:44 +0300
parents 7eb73ce46dd0
children
line source
1 /*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
18 #include <jni.h>
20 #include <errno.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <sys/resource.h>
25 #include "native_glue.h"
26 #include <android/log.h>
28 #define ACTIVITY_NAME "com/mutantstargoat/photoshoot3d/MainActivity"
30 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, APP_NAME, __VA_ARGS__))
31 #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, APP_NAME, __VA_ARGS__))
33 /* For debug builds, always enable the debug traces in this library */
34 #ifndef NDEBUG
35 # define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, APP_NAME, __VA_ARGS__))
36 #else
37 # define LOGV(...) ((void)0)
38 #endif
40 /*
41 jint JNI_OnLoad(JavaVM *jvm, void *unused)
42 {
43 JNIEnv *jni;
44 jclass act_cls_local;
46 LOGI("OnLoad called ! <------------------\n");
48 if((*jvm)->GetEnv(jvm, (void**)&jni, JNI_VERSION_1_6) != JNI_OK) {
49 LOGE("OnLoad: failed to get JNIEnv from VM\n");
50 return -1;
51 }
53 jclass foo = (*jni)->FindClass(jni, "java/lang/String");
54 if(!foo) {
55 LOGE("String class not found!!!!!!\n");
56 } else {
57 LOGE("Found String class!!!!!!\n");
58 }
60 if(!(act_cls_local = (*jni)->FindClass(jni, ACTIVITY_NAME))) {
61 LOGE("could not find activity: " ACTIVITY_NAME);
62 return 0;
63 }
64 activity_class = (*jni)->NewGlobalRef(jni, act_cls_local);
66 return JNI_VERSION_1_6;
67 }
68 */
70 static void free_saved_state(struct android_app* android_app) {
71 pthread_mutex_lock(&android_app->mutex);
72 if (android_app->savedState != NULL) {
73 free(android_app->savedState);
74 android_app->savedState = NULL;
75 android_app->savedStateSize = 0;
76 }
77 pthread_mutex_unlock(&android_app->mutex);
78 }
80 int8_t android_app_read_cmd(struct android_app* android_app) {
81 int8_t cmd;
82 if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {
83 switch (cmd) {
84 case APP_CMD_SAVE_STATE:
85 free_saved_state(android_app);
86 break;
87 }
88 return cmd;
89 } else {
90 LOGE("No data on command pipe!");
91 }
92 return -1;
93 }
95 static void print_cur_config(struct android_app* android_app) {
96 char lang[2], country[2];
97 AConfiguration_getLanguage(android_app->config, lang);
98 AConfiguration_getCountry(android_app->config, country);
100 LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
101 "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
102 "modetype=%d modenight=%d",
103 AConfiguration_getMcc(android_app->config),
104 AConfiguration_getMnc(android_app->config),
105 lang[0], lang[1], country[0], country[1],
106 AConfiguration_getOrientation(android_app->config),
107 AConfiguration_getTouchscreen(android_app->config),
108 AConfiguration_getDensity(android_app->config),
109 AConfiguration_getKeyboard(android_app->config),
110 AConfiguration_getNavigation(android_app->config),
111 AConfiguration_getKeysHidden(android_app->config),
112 AConfiguration_getNavHidden(android_app->config),
113 AConfiguration_getSdkVersion(android_app->config),
114 AConfiguration_getScreenSize(android_app->config),
115 AConfiguration_getScreenLong(android_app->config),
116 AConfiguration_getUiModeType(android_app->config),
117 AConfiguration_getUiModeNight(android_app->config));
118 }
120 void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
121 switch (cmd) {
122 case APP_CMD_INPUT_CHANGED:
123 LOGV("APP_CMD_INPUT_CHANGED\n");
124 pthread_mutex_lock(&android_app->mutex);
125 if (android_app->inputQueue != NULL) {
126 AInputQueue_detachLooper(android_app->inputQueue);
127 }
128 android_app->inputQueue = android_app->pendingInputQueue;
129 if (android_app->inputQueue != NULL) {
130 LOGV("Attaching input queue to looper");
131 AInputQueue_attachLooper(android_app->inputQueue,
132 android_app->looper, LOOPER_ID_INPUT, NULL,
133 &android_app->inputPollSource);
134 }
135 pthread_cond_broadcast(&android_app->cond);
136 pthread_mutex_unlock(&android_app->mutex);
137 break;
139 case APP_CMD_INIT_WINDOW:
140 LOGV("APP_CMD_INIT_WINDOW\n");
141 pthread_mutex_lock(&android_app->mutex);
142 android_app->window = android_app->pendingWindow;
143 pthread_cond_broadcast(&android_app->cond);
144 pthread_mutex_unlock(&android_app->mutex);
145 break;
147 case APP_CMD_TERM_WINDOW:
148 LOGV("APP_CMD_TERM_WINDOW\n");
149 pthread_cond_broadcast(&android_app->cond);
150 break;
152 case APP_CMD_RESUME:
153 case APP_CMD_START:
154 case APP_CMD_PAUSE:
155 case APP_CMD_STOP:
156 LOGV("activityState=%d\n", cmd);
157 pthread_mutex_lock(&android_app->mutex);
158 android_app->activityState = cmd;
159 pthread_cond_broadcast(&android_app->cond);
160 pthread_mutex_unlock(&android_app->mutex);
161 break;
163 case APP_CMD_CONFIG_CHANGED:
164 LOGV("APP_CMD_CONFIG_CHANGED\n");
165 AConfiguration_fromAssetManager(android_app->config,
166 android_app->activity->assetManager);
167 print_cur_config(android_app);
168 break;
170 case APP_CMD_DESTROY:
171 LOGV("APP_CMD_DESTROY\n");
172 android_app->destroyRequested = 1;
173 break;
174 }
175 }
177 void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
178 switch (cmd) {
179 case APP_CMD_TERM_WINDOW:
180 LOGV("APP_CMD_TERM_WINDOW\n");
181 pthread_mutex_lock(&android_app->mutex);
182 android_app->window = NULL;
183 pthread_cond_broadcast(&android_app->cond);
184 pthread_mutex_unlock(&android_app->mutex);
185 break;
187 case APP_CMD_SAVE_STATE:
188 LOGV("APP_CMD_SAVE_STATE\n");
189 pthread_mutex_lock(&android_app->mutex);
190 android_app->stateSaved = 1;
191 pthread_cond_broadcast(&android_app->cond);
192 pthread_mutex_unlock(&android_app->mutex);
193 break;
195 case APP_CMD_RESUME:
196 free_saved_state(android_app);
197 break;
198 }
199 }
201 void app_dummy() {
203 }
205 static void android_app_destroy(struct android_app* android_app) {
206 LOGV("android_app_destroy!");
207 free_saved_state(android_app);
208 pthread_mutex_lock(&android_app->mutex);
209 if (android_app->inputQueue != NULL) {
210 AInputQueue_detachLooper(android_app->inputQueue);
211 }
212 AConfiguration_delete(android_app->config);
214 android_app->destroyed = 1;
215 pthread_cond_broadcast(&android_app->cond);
216 pthread_mutex_unlock(&android_app->mutex);
217 // Can't touch android_app object after this.
218 }
220 static void process_input(struct android_app* app, struct android_poll_source* source) {
221 AInputEvent* event = NULL;
222 while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
223 LOGV("New input event: type=%d\n", AInputEvent_getType(event));
224 if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
225 continue;
226 }
227 int32_t handled = 0;
228 if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
229 AInputQueue_finishEvent(app->inputQueue, event, handled);
230 }
231 }
233 static void process_cmd(struct android_app* app, struct android_poll_source* source) {
234 int8_t cmd = android_app_read_cmd(app);
235 android_app_pre_exec_cmd(app, cmd);
236 if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
237 android_app_post_exec_cmd(app, cmd);
238 }
240 static void* android_app_entry(void* param) {
241 struct android_app* android_app = (struct android_app*)param;
243 android_app->config = AConfiguration_new();
244 AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);
246 print_cur_config(android_app);
248 android_app->cmdPollSource.id = LOOPER_ID_MAIN;
249 android_app->cmdPollSource.app = android_app;
250 android_app->cmdPollSource.process = process_cmd;
251 android_app->inputPollSource.id = LOOPER_ID_INPUT;
252 android_app->inputPollSource.app = android_app;
253 android_app->inputPollSource.process = process_input;
255 ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
256 ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
257 &android_app->cmdPollSource);
258 android_app->looper = looper;
260 pthread_mutex_lock(&android_app->mutex);
261 android_app->running = 1;
262 pthread_cond_broadcast(&android_app->cond);
263 pthread_mutex_unlock(&android_app->mutex);
265 android_main(android_app);
267 android_app_destroy(android_app);
268 return NULL;
269 }
271 // --------------------------------------------------------------------
272 // Native activity interaction (called from main thread)
273 // --------------------------------------------------------------------
275 static struct android_app* android_app_create(ANativeActivity* activity,
276 void* savedState, size_t savedStateSize) {
277 struct android_app* android_app = malloc(sizeof(struct android_app));
278 memset(android_app, 0, sizeof(struct android_app));
279 android_app->activity = activity;
281 pthread_mutex_init(&android_app->mutex, NULL);
282 pthread_cond_init(&android_app->cond, NULL);
284 if (savedState != NULL) {
285 android_app->savedState = malloc(savedStateSize);
286 android_app->savedStateSize = savedStateSize;
287 memcpy(android_app->savedState, savedState, savedStateSize);
288 }
290 int msgpipe[2];
291 if (pipe(msgpipe)) {
292 LOGE("could not create pipe: %s", strerror(errno));
293 return NULL;
294 }
295 android_app->msgread = msgpipe[0];
296 android_app->msgwrite = msgpipe[1];
298 pthread_attr_t attr;
299 pthread_attr_init(&attr);
300 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
301 pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
303 // Wait for thread to start.
304 pthread_mutex_lock(&android_app->mutex);
305 while (!android_app->running) {
306 pthread_cond_wait(&android_app->cond, &android_app->mutex);
307 }
308 pthread_mutex_unlock(&android_app->mutex);
310 return android_app;
311 }
313 static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
314 if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
315 LOGE("Failure writing android_app cmd: %s\n", strerror(errno));
316 }
317 }
319 static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
320 pthread_mutex_lock(&android_app->mutex);
321 android_app->pendingInputQueue = inputQueue;
322 android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
323 while (android_app->inputQueue != android_app->pendingInputQueue) {
324 pthread_cond_wait(&android_app->cond, &android_app->mutex);
325 }
326 pthread_mutex_unlock(&android_app->mutex);
327 }
329 static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
330 pthread_mutex_lock(&android_app->mutex);
331 if (android_app->pendingWindow != NULL) {
332 android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
333 }
334 android_app->pendingWindow = window;
335 if (window != NULL) {
336 android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
337 }
338 while (android_app->window != android_app->pendingWindow) {
339 pthread_cond_wait(&android_app->cond, &android_app->mutex);
340 }
341 pthread_mutex_unlock(&android_app->mutex);
342 }
344 static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
345 pthread_mutex_lock(&android_app->mutex);
346 android_app_write_cmd(android_app, cmd);
347 while (android_app->activityState != cmd) {
348 pthread_cond_wait(&android_app->cond, &android_app->mutex);
349 }
350 pthread_mutex_unlock(&android_app->mutex);
351 }
353 static void android_app_free(struct android_app* android_app) {
354 pthread_mutex_lock(&android_app->mutex);
355 android_app_write_cmd(android_app, APP_CMD_DESTROY);
356 while (!android_app->destroyed) {
357 pthread_cond_wait(&android_app->cond, &android_app->mutex);
358 }
359 pthread_mutex_unlock(&android_app->mutex);
361 close(android_app->msgread);
362 close(android_app->msgwrite);
363 pthread_cond_destroy(&android_app->cond);
364 pthread_mutex_destroy(&android_app->mutex);
365 free(android_app);
366 }
368 static void onDestroy(ANativeActivity* activity) {
369 LOGV("Destroy: %p\n", activity);
370 android_app_free((struct android_app*)activity->instance);
371 }
373 static void onStart(ANativeActivity* activity) {
374 LOGV("Start: %p\n", activity);
375 android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START);
376 }
378 static void onResume(ANativeActivity* activity) {
379 LOGV("Resume: %p\n", activity);
380 android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME);
381 }
383 static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
384 struct android_app* android_app = (struct android_app*)activity->instance;
385 void* savedState = NULL;
387 LOGV("SaveInstanceState: %p\n", activity);
388 pthread_mutex_lock(&android_app->mutex);
389 android_app->stateSaved = 0;
390 android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
391 while (!android_app->stateSaved) {
392 pthread_cond_wait(&android_app->cond, &android_app->mutex);
393 }
395 if (android_app->savedState != NULL) {
396 savedState = android_app->savedState;
397 *outLen = android_app->savedStateSize;
398 android_app->savedState = NULL;
399 android_app->savedStateSize = 0;
400 }
402 pthread_mutex_unlock(&android_app->mutex);
404 return savedState;
405 }
407 static void onPause(ANativeActivity* activity) {
408 LOGV("Pause: %p\n", activity);
409 android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE);
410 }
412 static void onStop(ANativeActivity* activity) {
413 LOGV("Stop: %p\n", activity);
414 android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP);
415 }
417 static void onConfigurationChanged(ANativeActivity* activity) {
418 struct android_app* android_app = (struct android_app*)activity->instance;
419 LOGV("ConfigurationChanged: %p\n", activity);
420 android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED);
421 }
423 static void onLowMemory(ANativeActivity* activity) {
424 struct android_app* android_app = (struct android_app*)activity->instance;
425 LOGV("LowMemory: %p\n", activity);
426 android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY);
427 }
429 static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
430 LOGV("WindowFocusChanged: %p -- %d\n", activity, focused);
431 android_app_write_cmd((struct android_app*)activity->instance,
432 focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
433 }
435 static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
436 LOGV("NativeWindowCreated: %p -- %p\n", activity, window);
437 android_app_set_window((struct android_app*)activity->instance, window);
438 }
440 static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
441 LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window);
442 android_app_set_window((struct android_app*)activity->instance, NULL);
443 }
445 static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
446 LOGV("InputQueueCreated: %p -- %p\n", activity, queue);
447 android_app_set_input((struct android_app*)activity->instance, queue);
448 }
450 static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
451 LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue);
452 android_app_set_input((struct android_app*)activity->instance, NULL);
453 }
455 void ANativeActivity_onCreate(ANativeActivity* activity,
456 void* savedState, size_t savedStateSize) {
457 LOGV("Creating: %p\n", activity);
458 activity->callbacks->onDestroy = onDestroy;
459 activity->callbacks->onStart = onStart;
460 activity->callbacks->onResume = onResume;
461 activity->callbacks->onSaveInstanceState = onSaveInstanceState;
462 activity->callbacks->onPause = onPause;
463 activity->callbacks->onStop = onStop;
464 activity->callbacks->onConfigurationChanged = onConfigurationChanged;
465 activity->callbacks->onLowMemory = onLowMemory;
466 activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
467 activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
468 activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
469 activity->callbacks->onInputQueueCreated = onInputQueueCreated;
470 activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
472 activity->instance = android_app_create(activity, savedState, savedStateSize);
473 }