3dphotoshoot
diff src/android/native_glue.c @ 1:7eb73ce46dd0
fucking jni man ... wtf
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 14 May 2015 23:46:56 +0300 |
parents | src/android/android_native_app_glue.c@a4bf2687e406 |
children | cf5964db7ff3 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/android/native_glue.c Thu May 14 23:46:56 2015 +0300 1.3 @@ -0,0 +1,457 @@ 1.4 +/* 1.5 + * Copyright (C) 2010 The Android Open Source Project 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * Unless required by applicable law or agreed to in writing, software 1.14 + * distributed under the License is distributed on an "AS IS" BASIS, 1.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.16 + * See the License for the specific language governing permissions and 1.17 + * limitations under the License. 1.18 + * 1.19 + */ 1.20 + 1.21 +#include <jni.h> 1.22 + 1.23 +#include <errno.h> 1.24 +#include <string.h> 1.25 +#include <unistd.h> 1.26 +#include <sys/resource.h> 1.27 + 1.28 +#include "native_glue.h" 1.29 +#include <android/log.h> 1.30 + 1.31 +#define ACTIVITY_NAME "com/mutantstargoat/photoshoot3d/MainActivity" 1.32 + 1.33 +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, APP_NAME, __VA_ARGS__)) 1.34 +#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, APP_NAME, __VA_ARGS__)) 1.35 + 1.36 +/* For debug builds, always enable the debug traces in this library */ 1.37 +#ifndef NDEBUG 1.38 +# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, APP_NAME, __VA_ARGS__)) 1.39 +#else 1.40 +# define LOGV(...) ((void)0) 1.41 +#endif 1.42 + 1.43 +static void free_saved_state(struct android_app* android_app) { 1.44 + pthread_mutex_lock(&android_app->mutex); 1.45 + if (android_app->savedState != NULL) { 1.46 + free(android_app->savedState); 1.47 + android_app->savedState = NULL; 1.48 + android_app->savedStateSize = 0; 1.49 + } 1.50 + pthread_mutex_unlock(&android_app->mutex); 1.51 +} 1.52 + 1.53 +int8_t android_app_read_cmd(struct android_app* android_app) { 1.54 + int8_t cmd; 1.55 + if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) { 1.56 + switch (cmd) { 1.57 + case APP_CMD_SAVE_STATE: 1.58 + free_saved_state(android_app); 1.59 + break; 1.60 + } 1.61 + return cmd; 1.62 + } else { 1.63 + LOGE("No data on command pipe!"); 1.64 + } 1.65 + return -1; 1.66 +} 1.67 + 1.68 +static void print_cur_config(struct android_app* android_app) { 1.69 + char lang[2], country[2]; 1.70 + AConfiguration_getLanguage(android_app->config, lang); 1.71 + AConfiguration_getCountry(android_app->config, country); 1.72 + 1.73 + LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d " 1.74 + "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d " 1.75 + "modetype=%d modenight=%d", 1.76 + AConfiguration_getMcc(android_app->config), 1.77 + AConfiguration_getMnc(android_app->config), 1.78 + lang[0], lang[1], country[0], country[1], 1.79 + AConfiguration_getOrientation(android_app->config), 1.80 + AConfiguration_getTouchscreen(android_app->config), 1.81 + AConfiguration_getDensity(android_app->config), 1.82 + AConfiguration_getKeyboard(android_app->config), 1.83 + AConfiguration_getNavigation(android_app->config), 1.84 + AConfiguration_getKeysHidden(android_app->config), 1.85 + AConfiguration_getNavHidden(android_app->config), 1.86 + AConfiguration_getSdkVersion(android_app->config), 1.87 + AConfiguration_getScreenSize(android_app->config), 1.88 + AConfiguration_getScreenLong(android_app->config), 1.89 + AConfiguration_getUiModeType(android_app->config), 1.90 + AConfiguration_getUiModeNight(android_app->config)); 1.91 +} 1.92 + 1.93 +void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { 1.94 + switch (cmd) { 1.95 + case APP_CMD_INPUT_CHANGED: 1.96 + LOGV("APP_CMD_INPUT_CHANGED\n"); 1.97 + pthread_mutex_lock(&android_app->mutex); 1.98 + if (android_app->inputQueue != NULL) { 1.99 + AInputQueue_detachLooper(android_app->inputQueue); 1.100 + } 1.101 + android_app->inputQueue = android_app->pendingInputQueue; 1.102 + if (android_app->inputQueue != NULL) { 1.103 + LOGV("Attaching input queue to looper"); 1.104 + AInputQueue_attachLooper(android_app->inputQueue, 1.105 + android_app->looper, LOOPER_ID_INPUT, NULL, 1.106 + &android_app->inputPollSource); 1.107 + } 1.108 + pthread_cond_broadcast(&android_app->cond); 1.109 + pthread_mutex_unlock(&android_app->mutex); 1.110 + break; 1.111 + 1.112 + case APP_CMD_INIT_WINDOW: 1.113 + LOGV("APP_CMD_INIT_WINDOW\n"); 1.114 + pthread_mutex_lock(&android_app->mutex); 1.115 + android_app->window = android_app->pendingWindow; 1.116 + pthread_cond_broadcast(&android_app->cond); 1.117 + pthread_mutex_unlock(&android_app->mutex); 1.118 + break; 1.119 + 1.120 + case APP_CMD_TERM_WINDOW: 1.121 + LOGV("APP_CMD_TERM_WINDOW\n"); 1.122 + pthread_cond_broadcast(&android_app->cond); 1.123 + break; 1.124 + 1.125 + case APP_CMD_RESUME: 1.126 + case APP_CMD_START: 1.127 + case APP_CMD_PAUSE: 1.128 + case APP_CMD_STOP: 1.129 + LOGV("activityState=%d\n", cmd); 1.130 + pthread_mutex_lock(&android_app->mutex); 1.131 + android_app->activityState = cmd; 1.132 + pthread_cond_broadcast(&android_app->cond); 1.133 + pthread_mutex_unlock(&android_app->mutex); 1.134 + break; 1.135 + 1.136 + case APP_CMD_CONFIG_CHANGED: 1.137 + LOGV("APP_CMD_CONFIG_CHANGED\n"); 1.138 + AConfiguration_fromAssetManager(android_app->config, 1.139 + android_app->activity->assetManager); 1.140 + print_cur_config(android_app); 1.141 + break; 1.142 + 1.143 + case APP_CMD_DESTROY: 1.144 + LOGV("APP_CMD_DESTROY\n"); 1.145 + android_app->destroyRequested = 1; 1.146 + break; 1.147 + } 1.148 +} 1.149 + 1.150 +void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) { 1.151 + switch (cmd) { 1.152 + case APP_CMD_TERM_WINDOW: 1.153 + LOGV("APP_CMD_TERM_WINDOW\n"); 1.154 + pthread_mutex_lock(&android_app->mutex); 1.155 + android_app->window = NULL; 1.156 + pthread_cond_broadcast(&android_app->cond); 1.157 + pthread_mutex_unlock(&android_app->mutex); 1.158 + break; 1.159 + 1.160 + case APP_CMD_SAVE_STATE: 1.161 + LOGV("APP_CMD_SAVE_STATE\n"); 1.162 + pthread_mutex_lock(&android_app->mutex); 1.163 + android_app->stateSaved = 1; 1.164 + pthread_cond_broadcast(&android_app->cond); 1.165 + pthread_mutex_unlock(&android_app->mutex); 1.166 + break; 1.167 + 1.168 + case APP_CMD_RESUME: 1.169 + free_saved_state(android_app); 1.170 + break; 1.171 + } 1.172 +} 1.173 + 1.174 +void app_dummy() { 1.175 + 1.176 +} 1.177 + 1.178 +static void android_app_destroy(struct android_app* android_app) { 1.179 + LOGV("android_app_destroy!"); 1.180 + free_saved_state(android_app); 1.181 + pthread_mutex_lock(&android_app->mutex); 1.182 + if (android_app->inputQueue != NULL) { 1.183 + AInputQueue_detachLooper(android_app->inputQueue); 1.184 + } 1.185 + AConfiguration_delete(android_app->config); 1.186 + android_app->destroyed = 1; 1.187 + pthread_cond_broadcast(&android_app->cond); 1.188 + pthread_mutex_unlock(&android_app->mutex); 1.189 + // Can't touch android_app object after this. 1.190 +} 1.191 + 1.192 +static void process_input(struct android_app* app, struct android_poll_source* source) { 1.193 + AInputEvent* event = NULL; 1.194 + while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { 1.195 + LOGV("New input event: type=%d\n", AInputEvent_getType(event)); 1.196 + if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { 1.197 + continue; 1.198 + } 1.199 + int32_t handled = 0; 1.200 + if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); 1.201 + AInputQueue_finishEvent(app->inputQueue, event, handled); 1.202 + } 1.203 +} 1.204 + 1.205 +static void process_cmd(struct android_app* app, struct android_poll_source* source) { 1.206 + int8_t cmd = android_app_read_cmd(app); 1.207 + android_app_pre_exec_cmd(app, cmd); 1.208 + if (app->onAppCmd != NULL) app->onAppCmd(app, cmd); 1.209 + android_app_post_exec_cmd(app, cmd); 1.210 +} 1.211 + 1.212 +static void* android_app_entry(void* param) { 1.213 + struct android_app* android_app = (struct android_app*)param; 1.214 + 1.215 + android_app->config = AConfiguration_new(); 1.216 + AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); 1.217 + 1.218 + print_cur_config(android_app); 1.219 + 1.220 + android_app->cmdPollSource.id = LOOPER_ID_MAIN; 1.221 + android_app->cmdPollSource.app = android_app; 1.222 + android_app->cmdPollSource.process = process_cmd; 1.223 + android_app->inputPollSource.id = LOOPER_ID_INPUT; 1.224 + android_app->inputPollSource.app = android_app; 1.225 + android_app->inputPollSource.process = process_input; 1.226 + 1.227 + ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); 1.228 + ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, 1.229 + &android_app->cmdPollSource); 1.230 + android_app->looper = looper; 1.231 + 1.232 + pthread_mutex_lock(&android_app->mutex); 1.233 + android_app->running = 1; 1.234 + pthread_cond_broadcast(&android_app->cond); 1.235 + pthread_mutex_unlock(&android_app->mutex); 1.236 + 1.237 + android_main(android_app); 1.238 + 1.239 + android_app_destroy(android_app); 1.240 + return NULL; 1.241 +} 1.242 + 1.243 +// -------------------------------------------------------------------- 1.244 +// Native activity interaction (called from main thread) 1.245 +// -------------------------------------------------------------------- 1.246 + 1.247 +static struct android_app* android_app_create(ANativeActivity* activity, 1.248 + void* savedState, size_t savedStateSize) { 1.249 + JNIEnv *jni = activity->env; 1.250 + struct android_app* android_app = malloc(sizeof(struct android_app)); 1.251 + memset(android_app, 0, sizeof(struct android_app)); 1.252 + android_app->activity = activity; 1.253 + 1.254 + { 1.255 + jclass foo = (*jni)->FindClass(jni, "java/lang/String"); 1.256 + if(!foo) { 1.257 + LOGE("String class not found!!!!!!\n"); 1.258 + } else { 1.259 + LOGE("Found String class!!!!!!\n"); 1.260 + } 1.261 + } 1.262 + 1.263 + if(!(android_app->activity_class = (*jni)->FindClass(jni, ACTIVITY_NAME))) { 1.264 + LOGE("could not find activity: " ACTIVITY_NAME); 1.265 + return 0; 1.266 + } 1.267 + 1.268 + pthread_mutex_init(&android_app->mutex, NULL); 1.269 + pthread_cond_init(&android_app->cond, NULL); 1.270 + 1.271 + if (savedState != NULL) { 1.272 + android_app->savedState = malloc(savedStateSize); 1.273 + android_app->savedStateSize = savedStateSize; 1.274 + memcpy(android_app->savedState, savedState, savedStateSize); 1.275 + } 1.276 + 1.277 + int msgpipe[2]; 1.278 + if (pipe(msgpipe)) { 1.279 + LOGE("could not create pipe: %s", strerror(errno)); 1.280 + return NULL; 1.281 + } 1.282 + android_app->msgread = msgpipe[0]; 1.283 + android_app->msgwrite = msgpipe[1]; 1.284 + 1.285 + pthread_attr_t attr; 1.286 + pthread_attr_init(&attr); 1.287 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 1.288 + pthread_create(&android_app->thread, &attr, android_app_entry, android_app); 1.289 + 1.290 + // Wait for thread to start. 1.291 + pthread_mutex_lock(&android_app->mutex); 1.292 + while (!android_app->running) { 1.293 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 1.294 + } 1.295 + pthread_mutex_unlock(&android_app->mutex); 1.296 + 1.297 + return android_app; 1.298 +} 1.299 + 1.300 +static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) { 1.301 + if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) { 1.302 + LOGE("Failure writing android_app cmd: %s\n", strerror(errno)); 1.303 + } 1.304 +} 1.305 + 1.306 +static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) { 1.307 + pthread_mutex_lock(&android_app->mutex); 1.308 + android_app->pendingInputQueue = inputQueue; 1.309 + android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); 1.310 + while (android_app->inputQueue != android_app->pendingInputQueue) { 1.311 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 1.312 + } 1.313 + pthread_mutex_unlock(&android_app->mutex); 1.314 +} 1.315 + 1.316 +static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) { 1.317 + pthread_mutex_lock(&android_app->mutex); 1.318 + if (android_app->pendingWindow != NULL) { 1.319 + android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW); 1.320 + } 1.321 + android_app->pendingWindow = window; 1.322 + if (window != NULL) { 1.323 + android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW); 1.324 + } 1.325 + while (android_app->window != android_app->pendingWindow) { 1.326 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 1.327 + } 1.328 + pthread_mutex_unlock(&android_app->mutex); 1.329 +} 1.330 + 1.331 +static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) { 1.332 + pthread_mutex_lock(&android_app->mutex); 1.333 + android_app_write_cmd(android_app, cmd); 1.334 + while (android_app->activityState != cmd) { 1.335 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 1.336 + } 1.337 + pthread_mutex_unlock(&android_app->mutex); 1.338 +} 1.339 + 1.340 +static void android_app_free(struct android_app* android_app) { 1.341 + pthread_mutex_lock(&android_app->mutex); 1.342 + android_app_write_cmd(android_app, APP_CMD_DESTROY); 1.343 + while (!android_app->destroyed) { 1.344 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 1.345 + } 1.346 + pthread_mutex_unlock(&android_app->mutex); 1.347 + 1.348 + close(android_app->msgread); 1.349 + close(android_app->msgwrite); 1.350 + pthread_cond_destroy(&android_app->cond); 1.351 + pthread_mutex_destroy(&android_app->mutex); 1.352 + free(android_app); 1.353 +} 1.354 + 1.355 +static void onDestroy(ANativeActivity* activity) { 1.356 + LOGV("Destroy: %p\n", activity); 1.357 + android_app_free((struct android_app*)activity->instance); 1.358 +} 1.359 + 1.360 +static void onStart(ANativeActivity* activity) { 1.361 + LOGV("Start: %p\n", activity); 1.362 + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START); 1.363 +} 1.364 + 1.365 +static void onResume(ANativeActivity* activity) { 1.366 + LOGV("Resume: %p\n", activity); 1.367 + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME); 1.368 +} 1.369 + 1.370 +static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { 1.371 + struct android_app* android_app = (struct android_app*)activity->instance; 1.372 + void* savedState = NULL; 1.373 + 1.374 + LOGV("SaveInstanceState: %p\n", activity); 1.375 + pthread_mutex_lock(&android_app->mutex); 1.376 + android_app->stateSaved = 0; 1.377 + android_app_write_cmd(android_app, APP_CMD_SAVE_STATE); 1.378 + while (!android_app->stateSaved) { 1.379 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 1.380 + } 1.381 + 1.382 + if (android_app->savedState != NULL) { 1.383 + savedState = android_app->savedState; 1.384 + *outLen = android_app->savedStateSize; 1.385 + android_app->savedState = NULL; 1.386 + android_app->savedStateSize = 0; 1.387 + } 1.388 + 1.389 + pthread_mutex_unlock(&android_app->mutex); 1.390 + 1.391 + return savedState; 1.392 +} 1.393 + 1.394 +static void onPause(ANativeActivity* activity) { 1.395 + LOGV("Pause: %p\n", activity); 1.396 + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE); 1.397 +} 1.398 + 1.399 +static void onStop(ANativeActivity* activity) { 1.400 + LOGV("Stop: %p\n", activity); 1.401 + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP); 1.402 +} 1.403 + 1.404 +static void onConfigurationChanged(ANativeActivity* activity) { 1.405 + struct android_app* android_app = (struct android_app*)activity->instance; 1.406 + LOGV("ConfigurationChanged: %p\n", activity); 1.407 + android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED); 1.408 +} 1.409 + 1.410 +static void onLowMemory(ANativeActivity* activity) { 1.411 + struct android_app* android_app = (struct android_app*)activity->instance; 1.412 + LOGV("LowMemory: %p\n", activity); 1.413 + android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY); 1.414 +} 1.415 + 1.416 +static void onWindowFocusChanged(ANativeActivity* activity, int focused) { 1.417 + LOGV("WindowFocusChanged: %p -- %d\n", activity, focused); 1.418 + android_app_write_cmd((struct android_app*)activity->instance, 1.419 + focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); 1.420 +} 1.421 + 1.422 +static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) { 1.423 + LOGV("NativeWindowCreated: %p -- %p\n", activity, window); 1.424 + android_app_set_window((struct android_app*)activity->instance, window); 1.425 +} 1.426 + 1.427 +static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) { 1.428 + LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window); 1.429 + android_app_set_window((struct android_app*)activity->instance, NULL); 1.430 +} 1.431 + 1.432 +static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { 1.433 + LOGV("InputQueueCreated: %p -- %p\n", activity, queue); 1.434 + android_app_set_input((struct android_app*)activity->instance, queue); 1.435 +} 1.436 + 1.437 +static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) { 1.438 + LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue); 1.439 + android_app_set_input((struct android_app*)activity->instance, NULL); 1.440 +} 1.441 + 1.442 +void ANativeActivity_onCreate(ANativeActivity* activity, 1.443 + void* savedState, size_t savedStateSize) { 1.444 + LOGV("Creating: %p\n", activity); 1.445 + activity->callbacks->onDestroy = onDestroy; 1.446 + activity->callbacks->onStart = onStart; 1.447 + activity->callbacks->onResume = onResume; 1.448 + activity->callbacks->onSaveInstanceState = onSaveInstanceState; 1.449 + activity->callbacks->onPause = onPause; 1.450 + activity->callbacks->onStop = onStop; 1.451 + activity->callbacks->onConfigurationChanged = onConfigurationChanged; 1.452 + activity->callbacks->onLowMemory = onLowMemory; 1.453 + activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; 1.454 + activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; 1.455 + activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; 1.456 + activity->callbacks->onInputQueueCreated = onInputQueueCreated; 1.457 + activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; 1.458 + 1.459 + activity->instance = android_app_create(activity, savedState, savedStateSize); 1.460 +}