3dphotoshoot
changeset 1:7eb73ce46dd0
fucking jni man ... wtf
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 14 May 2015 23:46:56 +0300 |
parents | a4bf2687e406 |
children | cf5964db7ff3 |
files | src/android/MainActivity.java src/android/amain.c src/android/android_native_app_glue.c src/android/android_native_app_glue.h src/android/native_glue.c src/android/native_glue.h |
diffstat | 6 files changed, 844 insertions(+), 791 deletions(-) [+] |
line diff
1.1 --- a/src/android/MainActivity.java Tue May 12 05:31:21 2015 +0300 1.2 +++ b/src/android/MainActivity.java Thu May 14 23:46:56 2015 +0300 1.3 @@ -4,7 +4,7 @@ 1.4 import android.util.Log; 1.5 1.6 public class MainActivity extends NativeActivity { 1.7 - final public void foo(String s, int n) 1.8 + public static void foo(String s, int n) 1.9 { 1.10 Log.i("3DPS", s + ": " + n); 1.11 }
2.1 --- a/src/android/amain.c Tue May 12 05:31:21 2015 +0300 2.2 +++ b/src/android/amain.c Thu May 14 23:46:56 2015 +0300 2.3 @@ -1,7 +1,8 @@ 2.4 #include <stdio.h> 2.5 #include <stdlib.h> 2.6 #include <EGL/egl.h> 2.7 -#include "android_native_app_glue.h" 2.8 +#include <jni.h> 2.9 +#include "native_glue.h" 2.10 #include "logger.h" 2.11 #include "game.h" 2.12 #include "timer.h" 2.13 @@ -21,6 +22,28 @@ 2.14 static int win_width, win_height; 2.15 static int init_done; 2.16 2.17 +static JavaVM *jvm; 2.18 +static JNIEnv *jni; 2.19 +static jclass activity_class; 2.20 + 2.21 +static int call_foo(const char *s, int n) 2.22 +{ 2.23 + jmethodID foo_id; 2.24 + jstring jstr; 2.25 + int res; 2.26 + 2.27 + if(!(foo_id = (*jni)->GetStaticMethodID(jni, activity_class, "foo", "(Ljava/lang/String;I)V"))) { 2.28 + fprintf(stderr, "static method foo not found\n"); 2.29 + return -1; 2.30 + } 2.31 + 2.32 + jstr = (*jni)->NewStringUTF(jni, s); 2.33 + res = (*jni)->CallStaticIntMethod(jni, activity_class, foo_id, jstr, n); 2.34 + (*jni)->DeleteLocalRef(jni, jstr); 2.35 + 2.36 + return res; 2.37 +} 2.38 + 2.39 void android_main(struct android_app *app_ptr) 2.40 { 2.41 app_dummy(); 2.42 @@ -31,6 +54,15 @@ 2.43 2.44 start_logger(); 2.45 2.46 + jvm = app->activity->vm; 2.47 + if((*jvm)->AttachCurrentThread(jvm, &jni, 0) != 0) { 2.48 + fprintf(stderr, "failed to attach native thread to Java VM\n"); 2.49 + exit(1); 2.50 + } 2.51 + activity_class = app->activity_class; 2.52 + 2.53 + printf("JNI call returned: %d\n", call_foo("testing C->java jni calls", 42)); 2.54 + 2.55 for(;;) { 2.56 int num_events; 2.57 struct android_poll_source *pollsrc; 2.58 @@ -42,6 +74,7 @@ 2.59 } 2.60 2.61 if(app->destroyRequested) { 2.62 + (*jvm)->DetachCurrentThread(jvm); 2.63 return; 2.64 } 2.65
3.1 --- a/src/android/android_native_app_glue.c Tue May 12 05:31:21 2015 +0300 3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 3.3 @@ -1,440 +0,0 @@ 3.4 -/* 3.5 - * Copyright (C) 2010 The Android Open Source Project 3.6 - * 3.7 - * Licensed under the Apache License, Version 2.0 (the "License"); 3.8 - * you may not use this file except in compliance with the License. 3.9 - * You may obtain a copy of the License at 3.10 - * 3.11 - * http://www.apache.org/licenses/LICENSE-2.0 3.12 - * 3.13 - * Unless required by applicable law or agreed to in writing, software 3.14 - * distributed under the License is distributed on an "AS IS" BASIS, 3.15 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3.16 - * See the License for the specific language governing permissions and 3.17 - * limitations under the License. 3.18 - * 3.19 - */ 3.20 - 3.21 -#include <jni.h> 3.22 - 3.23 -#include <errno.h> 3.24 -#include <string.h> 3.25 -#include <unistd.h> 3.26 -#include <sys/resource.h> 3.27 - 3.28 -#include "android_native_app_glue.h" 3.29 -#include <android/log.h> 3.30 - 3.31 -#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__)) 3.32 -#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__)) 3.33 - 3.34 -/* For debug builds, always enable the debug traces in this library */ 3.35 -#ifndef NDEBUG 3.36 -# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__)) 3.37 -#else 3.38 -# define LOGV(...) ((void)0) 3.39 -#endif 3.40 - 3.41 -static void free_saved_state(struct android_app* android_app) { 3.42 - pthread_mutex_lock(&android_app->mutex); 3.43 - if (android_app->savedState != NULL) { 3.44 - free(android_app->savedState); 3.45 - android_app->savedState = NULL; 3.46 - android_app->savedStateSize = 0; 3.47 - } 3.48 - pthread_mutex_unlock(&android_app->mutex); 3.49 -} 3.50 - 3.51 -int8_t android_app_read_cmd(struct android_app* android_app) { 3.52 - int8_t cmd; 3.53 - if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) { 3.54 - switch (cmd) { 3.55 - case APP_CMD_SAVE_STATE: 3.56 - free_saved_state(android_app); 3.57 - break; 3.58 - } 3.59 - return cmd; 3.60 - } else { 3.61 - LOGE("No data on command pipe!"); 3.62 - } 3.63 - return -1; 3.64 -} 3.65 - 3.66 -static void print_cur_config(struct android_app* android_app) { 3.67 - char lang[2], country[2]; 3.68 - AConfiguration_getLanguage(android_app->config, lang); 3.69 - AConfiguration_getCountry(android_app->config, country); 3.70 - 3.71 - LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d " 3.72 - "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d " 3.73 - "modetype=%d modenight=%d", 3.74 - AConfiguration_getMcc(android_app->config), 3.75 - AConfiguration_getMnc(android_app->config), 3.76 - lang[0], lang[1], country[0], country[1], 3.77 - AConfiguration_getOrientation(android_app->config), 3.78 - AConfiguration_getTouchscreen(android_app->config), 3.79 - AConfiguration_getDensity(android_app->config), 3.80 - AConfiguration_getKeyboard(android_app->config), 3.81 - AConfiguration_getNavigation(android_app->config), 3.82 - AConfiguration_getKeysHidden(android_app->config), 3.83 - AConfiguration_getNavHidden(android_app->config), 3.84 - AConfiguration_getSdkVersion(android_app->config), 3.85 - AConfiguration_getScreenSize(android_app->config), 3.86 - AConfiguration_getScreenLong(android_app->config), 3.87 - AConfiguration_getUiModeType(android_app->config), 3.88 - AConfiguration_getUiModeNight(android_app->config)); 3.89 -} 3.90 - 3.91 -void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { 3.92 - switch (cmd) { 3.93 - case APP_CMD_INPUT_CHANGED: 3.94 - LOGV("APP_CMD_INPUT_CHANGED\n"); 3.95 - pthread_mutex_lock(&android_app->mutex); 3.96 - if (android_app->inputQueue != NULL) { 3.97 - AInputQueue_detachLooper(android_app->inputQueue); 3.98 - } 3.99 - android_app->inputQueue = android_app->pendingInputQueue; 3.100 - if (android_app->inputQueue != NULL) { 3.101 - LOGV("Attaching input queue to looper"); 3.102 - AInputQueue_attachLooper(android_app->inputQueue, 3.103 - android_app->looper, LOOPER_ID_INPUT, NULL, 3.104 - &android_app->inputPollSource); 3.105 - } 3.106 - pthread_cond_broadcast(&android_app->cond); 3.107 - pthread_mutex_unlock(&android_app->mutex); 3.108 - break; 3.109 - 3.110 - case APP_CMD_INIT_WINDOW: 3.111 - LOGV("APP_CMD_INIT_WINDOW\n"); 3.112 - pthread_mutex_lock(&android_app->mutex); 3.113 - android_app->window = android_app->pendingWindow; 3.114 - pthread_cond_broadcast(&android_app->cond); 3.115 - pthread_mutex_unlock(&android_app->mutex); 3.116 - break; 3.117 - 3.118 - case APP_CMD_TERM_WINDOW: 3.119 - LOGV("APP_CMD_TERM_WINDOW\n"); 3.120 - pthread_cond_broadcast(&android_app->cond); 3.121 - break; 3.122 - 3.123 - case APP_CMD_RESUME: 3.124 - case APP_CMD_START: 3.125 - case APP_CMD_PAUSE: 3.126 - case APP_CMD_STOP: 3.127 - LOGV("activityState=%d\n", cmd); 3.128 - pthread_mutex_lock(&android_app->mutex); 3.129 - android_app->activityState = cmd; 3.130 - pthread_cond_broadcast(&android_app->cond); 3.131 - pthread_mutex_unlock(&android_app->mutex); 3.132 - break; 3.133 - 3.134 - case APP_CMD_CONFIG_CHANGED: 3.135 - LOGV("APP_CMD_CONFIG_CHANGED\n"); 3.136 - AConfiguration_fromAssetManager(android_app->config, 3.137 - android_app->activity->assetManager); 3.138 - print_cur_config(android_app); 3.139 - break; 3.140 - 3.141 - case APP_CMD_DESTROY: 3.142 - LOGV("APP_CMD_DESTROY\n"); 3.143 - android_app->destroyRequested = 1; 3.144 - break; 3.145 - } 3.146 -} 3.147 - 3.148 -void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) { 3.149 - switch (cmd) { 3.150 - case APP_CMD_TERM_WINDOW: 3.151 - LOGV("APP_CMD_TERM_WINDOW\n"); 3.152 - pthread_mutex_lock(&android_app->mutex); 3.153 - android_app->window = NULL; 3.154 - pthread_cond_broadcast(&android_app->cond); 3.155 - pthread_mutex_unlock(&android_app->mutex); 3.156 - break; 3.157 - 3.158 - case APP_CMD_SAVE_STATE: 3.159 - LOGV("APP_CMD_SAVE_STATE\n"); 3.160 - pthread_mutex_lock(&android_app->mutex); 3.161 - android_app->stateSaved = 1; 3.162 - pthread_cond_broadcast(&android_app->cond); 3.163 - pthread_mutex_unlock(&android_app->mutex); 3.164 - break; 3.165 - 3.166 - case APP_CMD_RESUME: 3.167 - free_saved_state(android_app); 3.168 - break; 3.169 - } 3.170 -} 3.171 - 3.172 -void app_dummy() { 3.173 - 3.174 -} 3.175 - 3.176 -static void android_app_destroy(struct android_app* android_app) { 3.177 - LOGV("android_app_destroy!"); 3.178 - free_saved_state(android_app); 3.179 - pthread_mutex_lock(&android_app->mutex); 3.180 - if (android_app->inputQueue != NULL) { 3.181 - AInputQueue_detachLooper(android_app->inputQueue); 3.182 - } 3.183 - AConfiguration_delete(android_app->config); 3.184 - android_app->destroyed = 1; 3.185 - pthread_cond_broadcast(&android_app->cond); 3.186 - pthread_mutex_unlock(&android_app->mutex); 3.187 - // Can't touch android_app object after this. 3.188 -} 3.189 - 3.190 -static void process_input(struct android_app* app, struct android_poll_source* source) { 3.191 - AInputEvent* event = NULL; 3.192 - while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { 3.193 - LOGV("New input event: type=%d\n", AInputEvent_getType(event)); 3.194 - if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { 3.195 - continue; 3.196 - } 3.197 - int32_t handled = 0; 3.198 - if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); 3.199 - AInputQueue_finishEvent(app->inputQueue, event, handled); 3.200 - } 3.201 -} 3.202 - 3.203 -static void process_cmd(struct android_app* app, struct android_poll_source* source) { 3.204 - int8_t cmd = android_app_read_cmd(app); 3.205 - android_app_pre_exec_cmd(app, cmd); 3.206 - if (app->onAppCmd != NULL) app->onAppCmd(app, cmd); 3.207 - android_app_post_exec_cmd(app, cmd); 3.208 -} 3.209 - 3.210 -static void* android_app_entry(void* param) { 3.211 - struct android_app* android_app = (struct android_app*)param; 3.212 - 3.213 - android_app->config = AConfiguration_new(); 3.214 - AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); 3.215 - 3.216 - print_cur_config(android_app); 3.217 - 3.218 - android_app->cmdPollSource.id = LOOPER_ID_MAIN; 3.219 - android_app->cmdPollSource.app = android_app; 3.220 - android_app->cmdPollSource.process = process_cmd; 3.221 - android_app->inputPollSource.id = LOOPER_ID_INPUT; 3.222 - android_app->inputPollSource.app = android_app; 3.223 - android_app->inputPollSource.process = process_input; 3.224 - 3.225 - ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); 3.226 - ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, 3.227 - &android_app->cmdPollSource); 3.228 - android_app->looper = looper; 3.229 - 3.230 - pthread_mutex_lock(&android_app->mutex); 3.231 - android_app->running = 1; 3.232 - pthread_cond_broadcast(&android_app->cond); 3.233 - pthread_mutex_unlock(&android_app->mutex); 3.234 - 3.235 - android_main(android_app); 3.236 - 3.237 - android_app_destroy(android_app); 3.238 - return NULL; 3.239 -} 3.240 - 3.241 -// -------------------------------------------------------------------- 3.242 -// Native activity interaction (called from main thread) 3.243 -// -------------------------------------------------------------------- 3.244 - 3.245 -static struct android_app* android_app_create(ANativeActivity* activity, 3.246 - void* savedState, size_t savedStateSize) { 3.247 - struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app)); 3.248 - memset(android_app, 0, sizeof(struct android_app)); 3.249 - android_app->activity = activity; 3.250 - 3.251 - pthread_mutex_init(&android_app->mutex, NULL); 3.252 - pthread_cond_init(&android_app->cond, NULL); 3.253 - 3.254 - if (savedState != NULL) { 3.255 - android_app->savedState = malloc(savedStateSize); 3.256 - android_app->savedStateSize = savedStateSize; 3.257 - memcpy(android_app->savedState, savedState, savedStateSize); 3.258 - } 3.259 - 3.260 - int msgpipe[2]; 3.261 - if (pipe(msgpipe)) { 3.262 - LOGE("could not create pipe: %s", strerror(errno)); 3.263 - return NULL; 3.264 - } 3.265 - android_app->msgread = msgpipe[0]; 3.266 - android_app->msgwrite = msgpipe[1]; 3.267 - 3.268 - pthread_attr_t attr; 3.269 - pthread_attr_init(&attr); 3.270 - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 3.271 - pthread_create(&android_app->thread, &attr, android_app_entry, android_app); 3.272 - 3.273 - // Wait for thread to start. 3.274 - pthread_mutex_lock(&android_app->mutex); 3.275 - while (!android_app->running) { 3.276 - pthread_cond_wait(&android_app->cond, &android_app->mutex); 3.277 - } 3.278 - pthread_mutex_unlock(&android_app->mutex); 3.279 - 3.280 - return android_app; 3.281 -} 3.282 - 3.283 -static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) { 3.284 - if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) { 3.285 - LOGE("Failure writing android_app cmd: %s\n", strerror(errno)); 3.286 - } 3.287 -} 3.288 - 3.289 -static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) { 3.290 - pthread_mutex_lock(&android_app->mutex); 3.291 - android_app->pendingInputQueue = inputQueue; 3.292 - android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); 3.293 - while (android_app->inputQueue != android_app->pendingInputQueue) { 3.294 - pthread_cond_wait(&android_app->cond, &android_app->mutex); 3.295 - } 3.296 - pthread_mutex_unlock(&android_app->mutex); 3.297 -} 3.298 - 3.299 -static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) { 3.300 - pthread_mutex_lock(&android_app->mutex); 3.301 - if (android_app->pendingWindow != NULL) { 3.302 - android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW); 3.303 - } 3.304 - android_app->pendingWindow = window; 3.305 - if (window != NULL) { 3.306 - android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW); 3.307 - } 3.308 - while (android_app->window != android_app->pendingWindow) { 3.309 - pthread_cond_wait(&android_app->cond, &android_app->mutex); 3.310 - } 3.311 - pthread_mutex_unlock(&android_app->mutex); 3.312 -} 3.313 - 3.314 -static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) { 3.315 - pthread_mutex_lock(&android_app->mutex); 3.316 - android_app_write_cmd(android_app, cmd); 3.317 - while (android_app->activityState != cmd) { 3.318 - pthread_cond_wait(&android_app->cond, &android_app->mutex); 3.319 - } 3.320 - pthread_mutex_unlock(&android_app->mutex); 3.321 -} 3.322 - 3.323 -static void android_app_free(struct android_app* android_app) { 3.324 - pthread_mutex_lock(&android_app->mutex); 3.325 - android_app_write_cmd(android_app, APP_CMD_DESTROY); 3.326 - while (!android_app->destroyed) { 3.327 - pthread_cond_wait(&android_app->cond, &android_app->mutex); 3.328 - } 3.329 - pthread_mutex_unlock(&android_app->mutex); 3.330 - 3.331 - close(android_app->msgread); 3.332 - close(android_app->msgwrite); 3.333 - pthread_cond_destroy(&android_app->cond); 3.334 - pthread_mutex_destroy(&android_app->mutex); 3.335 - free(android_app); 3.336 -} 3.337 - 3.338 -static void onDestroy(ANativeActivity* activity) { 3.339 - LOGV("Destroy: %p\n", activity); 3.340 - android_app_free((struct android_app*)activity->instance); 3.341 -} 3.342 - 3.343 -static void onStart(ANativeActivity* activity) { 3.344 - LOGV("Start: %p\n", activity); 3.345 - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START); 3.346 -} 3.347 - 3.348 -static void onResume(ANativeActivity* activity) { 3.349 - LOGV("Resume: %p\n", activity); 3.350 - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME); 3.351 -} 3.352 - 3.353 -static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { 3.354 - struct android_app* android_app = (struct android_app*)activity->instance; 3.355 - void* savedState = NULL; 3.356 - 3.357 - LOGV("SaveInstanceState: %p\n", activity); 3.358 - pthread_mutex_lock(&android_app->mutex); 3.359 - android_app->stateSaved = 0; 3.360 - android_app_write_cmd(android_app, APP_CMD_SAVE_STATE); 3.361 - while (!android_app->stateSaved) { 3.362 - pthread_cond_wait(&android_app->cond, &android_app->mutex); 3.363 - } 3.364 - 3.365 - if (android_app->savedState != NULL) { 3.366 - savedState = android_app->savedState; 3.367 - *outLen = android_app->savedStateSize; 3.368 - android_app->savedState = NULL; 3.369 - android_app->savedStateSize = 0; 3.370 - } 3.371 - 3.372 - pthread_mutex_unlock(&android_app->mutex); 3.373 - 3.374 - return savedState; 3.375 -} 3.376 - 3.377 -static void onPause(ANativeActivity* activity) { 3.378 - LOGV("Pause: %p\n", activity); 3.379 - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE); 3.380 -} 3.381 - 3.382 -static void onStop(ANativeActivity* activity) { 3.383 - LOGV("Stop: %p\n", activity); 3.384 - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP); 3.385 -} 3.386 - 3.387 -static void onConfigurationChanged(ANativeActivity* activity) { 3.388 - struct android_app* android_app = (struct android_app*)activity->instance; 3.389 - LOGV("ConfigurationChanged: %p\n", activity); 3.390 - android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED); 3.391 -} 3.392 - 3.393 -static void onLowMemory(ANativeActivity* activity) { 3.394 - struct android_app* android_app = (struct android_app*)activity->instance; 3.395 - LOGV("LowMemory: %p\n", activity); 3.396 - android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY); 3.397 -} 3.398 - 3.399 -static void onWindowFocusChanged(ANativeActivity* activity, int focused) { 3.400 - LOGV("WindowFocusChanged: %p -- %d\n", activity, focused); 3.401 - android_app_write_cmd((struct android_app*)activity->instance, 3.402 - focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); 3.403 -} 3.404 - 3.405 -static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) { 3.406 - LOGV("NativeWindowCreated: %p -- %p\n", activity, window); 3.407 - android_app_set_window((struct android_app*)activity->instance, window); 3.408 -} 3.409 - 3.410 -static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) { 3.411 - LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window); 3.412 - android_app_set_window((struct android_app*)activity->instance, NULL); 3.413 -} 3.414 - 3.415 -static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { 3.416 - LOGV("InputQueueCreated: %p -- %p\n", activity, queue); 3.417 - android_app_set_input((struct android_app*)activity->instance, queue); 3.418 -} 3.419 - 3.420 -static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) { 3.421 - LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue); 3.422 - android_app_set_input((struct android_app*)activity->instance, NULL); 3.423 -} 3.424 - 3.425 -void ANativeActivity_onCreate(ANativeActivity* activity, 3.426 - void* savedState, size_t savedStateSize) { 3.427 - LOGV("Creating: %p\n", activity); 3.428 - activity->callbacks->onDestroy = onDestroy; 3.429 - activity->callbacks->onStart = onStart; 3.430 - activity->callbacks->onResume = onResume; 3.431 - activity->callbacks->onSaveInstanceState = onSaveInstanceState; 3.432 - activity->callbacks->onPause = onPause; 3.433 - activity->callbacks->onStop = onStop; 3.434 - activity->callbacks->onConfigurationChanged = onConfigurationChanged; 3.435 - activity->callbacks->onLowMemory = onLowMemory; 3.436 - activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; 3.437 - activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; 3.438 - activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; 3.439 - activity->callbacks->onInputQueueCreated = onInputQueueCreated; 3.440 - activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; 3.441 - 3.442 - activity->instance = android_app_create(activity, savedState, savedStateSize); 3.443 -}
4.1 --- a/src/android/android_native_app_glue.h Tue May 12 05:31:21 2015 +0300 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,349 +0,0 @@ 4.4 -/* 4.5 - * Copyright (C) 2010 The Android Open Source Project 4.6 - * 4.7 - * Licensed under the Apache License, Version 2.0 (the "License"); 4.8 - * you may not use this file except in compliance with the License. 4.9 - * You may obtain a copy of the License at 4.10 - * 4.11 - * http://www.apache.org/licenses/LICENSE-2.0 4.12 - * 4.13 - * Unless required by applicable law or agreed to in writing, software 4.14 - * distributed under the License is distributed on an "AS IS" BASIS, 4.15 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4.16 - * See the License for the specific language governing permissions and 4.17 - * limitations under the License. 4.18 - * 4.19 - */ 4.20 - 4.21 -#ifndef _ANDROID_NATIVE_APP_GLUE_H 4.22 -#define _ANDROID_NATIVE_APP_GLUE_H 4.23 - 4.24 -#include <poll.h> 4.25 -#include <pthread.h> 4.26 -#include <sched.h> 4.27 - 4.28 -#include <android/configuration.h> 4.29 -#include <android/looper.h> 4.30 -#include <android/native_activity.h> 4.31 - 4.32 -#ifdef __cplusplus 4.33 -extern "C" { 4.34 -#endif 4.35 - 4.36 -/** 4.37 - * The native activity interface provided by <android/native_activity.h> 4.38 - * is based on a set of application-provided callbacks that will be called 4.39 - * by the Activity's main thread when certain events occur. 4.40 - * 4.41 - * This means that each one of this callbacks _should_ _not_ block, or they 4.42 - * risk having the system force-close the application. This programming 4.43 - * model is direct, lightweight, but constraining. 4.44 - * 4.45 - * The 'android_native_app_glue' static library is used to provide a different 4.46 - * execution model where the application can implement its own main event 4.47 - * loop in a different thread instead. Here's how it works: 4.48 - * 4.49 - * 1/ The application must provide a function named "android_main()" that 4.50 - * will be called when the activity is created, in a new thread that is 4.51 - * distinct from the activity's main thread. 4.52 - * 4.53 - * 2/ android_main() receives a pointer to a valid "android_app" structure 4.54 - * that contains references to other important objects, e.g. the 4.55 - * ANativeActivity obejct instance the application is running in. 4.56 - * 4.57 - * 3/ the "android_app" object holds an ALooper instance that already 4.58 - * listens to two important things: 4.59 - * 4.60 - * - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX 4.61 - * declarations below. 4.62 - * 4.63 - * - input events coming from the AInputQueue attached to the activity. 4.64 - * 4.65 - * Each of these correspond to an ALooper identifier returned by 4.66 - * ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT, 4.67 - * respectively. 4.68 - * 4.69 - * Your application can use the same ALooper to listen to additional 4.70 - * file-descriptors. They can either be callback based, or with return 4.71 - * identifiers starting with LOOPER_ID_USER. 4.72 - * 4.73 - * 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event, 4.74 - * the returned data will point to an android_poll_source structure. You 4.75 - * can call the process() function on it, and fill in android_app->onAppCmd 4.76 - * and android_app->onInputEvent to be called for your own processing 4.77 - * of the event. 4.78 - * 4.79 - * Alternatively, you can call the low-level functions to read and process 4.80 - * the data directly... look at the process_cmd() and process_input() 4.81 - * implementations in the glue to see how to do this. 4.82 - * 4.83 - * See the sample named "native-activity" that comes with the NDK with a 4.84 - * full usage example. Also look at the JavaDoc of NativeActivity. 4.85 - */ 4.86 - 4.87 -struct android_app; 4.88 - 4.89 -/** 4.90 - * Data associated with an ALooper fd that will be returned as the "outData" 4.91 - * when that source has data ready. 4.92 - */ 4.93 -struct android_poll_source { 4.94 - // The identifier of this source. May be LOOPER_ID_MAIN or 4.95 - // LOOPER_ID_INPUT. 4.96 - int32_t id; 4.97 - 4.98 - // The android_app this ident is associated with. 4.99 - struct android_app* app; 4.100 - 4.101 - // Function to call to perform the standard processing of data from 4.102 - // this source. 4.103 - void (*process)(struct android_app* app, struct android_poll_source* source); 4.104 -}; 4.105 - 4.106 -/** 4.107 - * This is the interface for the standard glue code of a threaded 4.108 - * application. In this model, the application's code is running 4.109 - * in its own thread separate from the main thread of the process. 4.110 - * It is not required that this thread be associated with the Java 4.111 - * VM, although it will need to be in order to make JNI calls any 4.112 - * Java objects. 4.113 - */ 4.114 -struct android_app { 4.115 - // The application can place a pointer to its own state object 4.116 - // here if it likes. 4.117 - void* userData; 4.118 - 4.119 - // Fill this in with the function to process main app commands (APP_CMD_*) 4.120 - void (*onAppCmd)(struct android_app* app, int32_t cmd); 4.121 - 4.122 - // Fill this in with the function to process input events. At this point 4.123 - // the event has already been pre-dispatched, and it will be finished upon 4.124 - // return. Return 1 if you have handled the event, 0 for any default 4.125 - // dispatching. 4.126 - int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event); 4.127 - 4.128 - // The ANativeActivity object instance that this app is running in. 4.129 - ANativeActivity* activity; 4.130 - 4.131 - // The current configuration the app is running in. 4.132 - AConfiguration* config; 4.133 - 4.134 - // This is the last instance's saved state, as provided at creation time. 4.135 - // It is NULL if there was no state. You can use this as you need; the 4.136 - // memory will remain around until you call android_app_exec_cmd() for 4.137 - // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL. 4.138 - // These variables should only be changed when processing a APP_CMD_SAVE_STATE, 4.139 - // at which point they will be initialized to NULL and you can malloc your 4.140 - // state and place the information here. In that case the memory will be 4.141 - // freed for you later. 4.142 - void* savedState; 4.143 - size_t savedStateSize; 4.144 - 4.145 - // The ALooper associated with the app's thread. 4.146 - ALooper* looper; 4.147 - 4.148 - // When non-NULL, this is the input queue from which the app will 4.149 - // receive user input events. 4.150 - AInputQueue* inputQueue; 4.151 - 4.152 - // When non-NULL, this is the window surface that the app can draw in. 4.153 - ANativeWindow* window; 4.154 - 4.155 - // Current content rectangle of the window; this is the area where the 4.156 - // window's content should be placed to be seen by the user. 4.157 - ARect contentRect; 4.158 - 4.159 - // Current state of the app's activity. May be either APP_CMD_START, 4.160 - // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below. 4.161 - int activityState; 4.162 - 4.163 - // This is non-zero when the application's NativeActivity is being 4.164 - // destroyed and waiting for the app thread to complete. 4.165 - int destroyRequested; 4.166 - 4.167 - // ------------------------------------------------- 4.168 - // Below are "private" implementation of the glue code. 4.169 - 4.170 - pthread_mutex_t mutex; 4.171 - pthread_cond_t cond; 4.172 - 4.173 - int msgread; 4.174 - int msgwrite; 4.175 - 4.176 - pthread_t thread; 4.177 - 4.178 - struct android_poll_source cmdPollSource; 4.179 - struct android_poll_source inputPollSource; 4.180 - 4.181 - int running; 4.182 - int stateSaved; 4.183 - int destroyed; 4.184 - int redrawNeeded; 4.185 - AInputQueue* pendingInputQueue; 4.186 - ANativeWindow* pendingWindow; 4.187 - ARect pendingContentRect; 4.188 -}; 4.189 - 4.190 -enum { 4.191 - /** 4.192 - * Looper data ID of commands coming from the app's main thread, which 4.193 - * is returned as an identifier from ALooper_pollOnce(). The data for this 4.194 - * identifier is a pointer to an android_poll_source structure. 4.195 - * These can be retrieved and processed with android_app_read_cmd() 4.196 - * and android_app_exec_cmd(). 4.197 - */ 4.198 - LOOPER_ID_MAIN = 1, 4.199 - 4.200 - /** 4.201 - * Looper data ID of events coming from the AInputQueue of the 4.202 - * application's window, which is returned as an identifier from 4.203 - * ALooper_pollOnce(). The data for this identifier is a pointer to an 4.204 - * android_poll_source structure. These can be read via the inputQueue 4.205 - * object of android_app. 4.206 - */ 4.207 - LOOPER_ID_INPUT = 2, 4.208 - 4.209 - /** 4.210 - * Start of user-defined ALooper identifiers. 4.211 - */ 4.212 - LOOPER_ID_USER = 3, 4.213 -}; 4.214 - 4.215 -enum { 4.216 - /** 4.217 - * Command from main thread: the AInputQueue has changed. Upon processing 4.218 - * this command, android_app->inputQueue will be updated to the new queue 4.219 - * (or NULL). 4.220 - */ 4.221 - APP_CMD_INPUT_CHANGED, 4.222 - 4.223 - /** 4.224 - * Command from main thread: a new ANativeWindow is ready for use. Upon 4.225 - * receiving this command, android_app->window will contain the new window 4.226 - * surface. 4.227 - */ 4.228 - APP_CMD_INIT_WINDOW, 4.229 - 4.230 - /** 4.231 - * Command from main thread: the existing ANativeWindow needs to be 4.232 - * terminated. Upon receiving this command, android_app->window still 4.233 - * contains the existing window; after calling android_app_exec_cmd 4.234 - * it will be set to NULL. 4.235 - */ 4.236 - APP_CMD_TERM_WINDOW, 4.237 - 4.238 - /** 4.239 - * Command from main thread: the current ANativeWindow has been resized. 4.240 - * Please redraw with its new size. 4.241 - */ 4.242 - APP_CMD_WINDOW_RESIZED, 4.243 - 4.244 - /** 4.245 - * Command from main thread: the system needs that the current ANativeWindow 4.246 - * be redrawn. You should redraw the window before handing this to 4.247 - * android_app_exec_cmd() in order to avoid transient drawing glitches. 4.248 - */ 4.249 - APP_CMD_WINDOW_REDRAW_NEEDED, 4.250 - 4.251 - /** 4.252 - * Command from main thread: the content area of the window has changed, 4.253 - * such as from the soft input window being shown or hidden. You can 4.254 - * find the new content rect in android_app::contentRect. 4.255 - */ 4.256 - APP_CMD_CONTENT_RECT_CHANGED, 4.257 - 4.258 - /** 4.259 - * Command from main thread: the app's activity window has gained 4.260 - * input focus. 4.261 - */ 4.262 - APP_CMD_GAINED_FOCUS, 4.263 - 4.264 - /** 4.265 - * Command from main thread: the app's activity window has lost 4.266 - * input focus. 4.267 - */ 4.268 - APP_CMD_LOST_FOCUS, 4.269 - 4.270 - /** 4.271 - * Command from main thread: the current device configuration has changed. 4.272 - */ 4.273 - APP_CMD_CONFIG_CHANGED, 4.274 - 4.275 - /** 4.276 - * Command from main thread: the system is running low on memory. 4.277 - * Try to reduce your memory use. 4.278 - */ 4.279 - APP_CMD_LOW_MEMORY, 4.280 - 4.281 - /** 4.282 - * Command from main thread: the app's activity has been started. 4.283 - */ 4.284 - APP_CMD_START, 4.285 - 4.286 - /** 4.287 - * Command from main thread: the app's activity has been resumed. 4.288 - */ 4.289 - APP_CMD_RESUME, 4.290 - 4.291 - /** 4.292 - * Command from main thread: the app should generate a new saved state 4.293 - * for itself, to restore from later if needed. If you have saved state, 4.294 - * allocate it with malloc and place it in android_app.savedState with 4.295 - * the size in android_app.savedStateSize. The will be freed for you 4.296 - * later. 4.297 - */ 4.298 - APP_CMD_SAVE_STATE, 4.299 - 4.300 - /** 4.301 - * Command from main thread: the app's activity has been paused. 4.302 - */ 4.303 - APP_CMD_PAUSE, 4.304 - 4.305 - /** 4.306 - * Command from main thread: the app's activity has been stopped. 4.307 - */ 4.308 - APP_CMD_STOP, 4.309 - 4.310 - /** 4.311 - * Command from main thread: the app's activity is being destroyed, 4.312 - * and waiting for the app thread to clean up and exit before proceeding. 4.313 - */ 4.314 - APP_CMD_DESTROY, 4.315 -}; 4.316 - 4.317 -/** 4.318 - * Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next 4.319 - * app command message. 4.320 - */ 4.321 -int8_t android_app_read_cmd(struct android_app* android_app); 4.322 - 4.323 -/** 4.324 - * Call with the command returned by android_app_read_cmd() to do the 4.325 - * initial pre-processing of the given command. You can perform your own 4.326 - * actions for the command after calling this function. 4.327 - */ 4.328 -void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd); 4.329 - 4.330 -/** 4.331 - * Call with the command returned by android_app_read_cmd() to do the 4.332 - * final post-processing of the given command. You must have done your own 4.333 - * actions for the command before calling this function. 4.334 - */ 4.335 -void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd); 4.336 - 4.337 -/** 4.338 - * Dummy function you can call to ensure glue code isn't stripped. 4.339 - */ 4.340 -void app_dummy(); 4.341 - 4.342 -/** 4.343 - * This is the function that application code must implement, representing 4.344 - * the main entry to the app. 4.345 - */ 4.346 -extern void android_main(struct android_app* app); 4.347 - 4.348 -#ifdef __cplusplus 4.349 -} 4.350 -#endif 4.351 - 4.352 -#endif /* _ANDROID_NATIVE_APP_GLUE_H */
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/android/native_glue.c Thu May 14 23:46:56 2015 +0300 5.3 @@ -0,0 +1,457 @@ 5.4 +/* 5.5 + * Copyright (C) 2010 The Android Open Source Project 5.6 + * 5.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 5.8 + * you may not use this file except in compliance with the License. 5.9 + * You may obtain a copy of the License at 5.10 + * 5.11 + * http://www.apache.org/licenses/LICENSE-2.0 5.12 + * 5.13 + * Unless required by applicable law or agreed to in writing, software 5.14 + * distributed under the License is distributed on an "AS IS" BASIS, 5.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 5.16 + * See the License for the specific language governing permissions and 5.17 + * limitations under the License. 5.18 + * 5.19 + */ 5.20 + 5.21 +#include <jni.h> 5.22 + 5.23 +#include <errno.h> 5.24 +#include <string.h> 5.25 +#include <unistd.h> 5.26 +#include <sys/resource.h> 5.27 + 5.28 +#include "native_glue.h" 5.29 +#include <android/log.h> 5.30 + 5.31 +#define ACTIVITY_NAME "com/mutantstargoat/photoshoot3d/MainActivity" 5.32 + 5.33 +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, APP_NAME, __VA_ARGS__)) 5.34 +#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, APP_NAME, __VA_ARGS__)) 5.35 + 5.36 +/* For debug builds, always enable the debug traces in this library */ 5.37 +#ifndef NDEBUG 5.38 +# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, APP_NAME, __VA_ARGS__)) 5.39 +#else 5.40 +# define LOGV(...) ((void)0) 5.41 +#endif 5.42 + 5.43 +static void free_saved_state(struct android_app* android_app) { 5.44 + pthread_mutex_lock(&android_app->mutex); 5.45 + if (android_app->savedState != NULL) { 5.46 + free(android_app->savedState); 5.47 + android_app->savedState = NULL; 5.48 + android_app->savedStateSize = 0; 5.49 + } 5.50 + pthread_mutex_unlock(&android_app->mutex); 5.51 +} 5.52 + 5.53 +int8_t android_app_read_cmd(struct android_app* android_app) { 5.54 + int8_t cmd; 5.55 + if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) { 5.56 + switch (cmd) { 5.57 + case APP_CMD_SAVE_STATE: 5.58 + free_saved_state(android_app); 5.59 + break; 5.60 + } 5.61 + return cmd; 5.62 + } else { 5.63 + LOGE("No data on command pipe!"); 5.64 + } 5.65 + return -1; 5.66 +} 5.67 + 5.68 +static void print_cur_config(struct android_app* android_app) { 5.69 + char lang[2], country[2]; 5.70 + AConfiguration_getLanguage(android_app->config, lang); 5.71 + AConfiguration_getCountry(android_app->config, country); 5.72 + 5.73 + LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d " 5.74 + "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d " 5.75 + "modetype=%d modenight=%d", 5.76 + AConfiguration_getMcc(android_app->config), 5.77 + AConfiguration_getMnc(android_app->config), 5.78 + lang[0], lang[1], country[0], country[1], 5.79 + AConfiguration_getOrientation(android_app->config), 5.80 + AConfiguration_getTouchscreen(android_app->config), 5.81 + AConfiguration_getDensity(android_app->config), 5.82 + AConfiguration_getKeyboard(android_app->config), 5.83 + AConfiguration_getNavigation(android_app->config), 5.84 + AConfiguration_getKeysHidden(android_app->config), 5.85 + AConfiguration_getNavHidden(android_app->config), 5.86 + AConfiguration_getSdkVersion(android_app->config), 5.87 + AConfiguration_getScreenSize(android_app->config), 5.88 + AConfiguration_getScreenLong(android_app->config), 5.89 + AConfiguration_getUiModeType(android_app->config), 5.90 + AConfiguration_getUiModeNight(android_app->config)); 5.91 +} 5.92 + 5.93 +void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { 5.94 + switch (cmd) { 5.95 + case APP_CMD_INPUT_CHANGED: 5.96 + LOGV("APP_CMD_INPUT_CHANGED\n"); 5.97 + pthread_mutex_lock(&android_app->mutex); 5.98 + if (android_app->inputQueue != NULL) { 5.99 + AInputQueue_detachLooper(android_app->inputQueue); 5.100 + } 5.101 + android_app->inputQueue = android_app->pendingInputQueue; 5.102 + if (android_app->inputQueue != NULL) { 5.103 + LOGV("Attaching input queue to looper"); 5.104 + AInputQueue_attachLooper(android_app->inputQueue, 5.105 + android_app->looper, LOOPER_ID_INPUT, NULL, 5.106 + &android_app->inputPollSource); 5.107 + } 5.108 + pthread_cond_broadcast(&android_app->cond); 5.109 + pthread_mutex_unlock(&android_app->mutex); 5.110 + break; 5.111 + 5.112 + case APP_CMD_INIT_WINDOW: 5.113 + LOGV("APP_CMD_INIT_WINDOW\n"); 5.114 + pthread_mutex_lock(&android_app->mutex); 5.115 + android_app->window = android_app->pendingWindow; 5.116 + pthread_cond_broadcast(&android_app->cond); 5.117 + pthread_mutex_unlock(&android_app->mutex); 5.118 + break; 5.119 + 5.120 + case APP_CMD_TERM_WINDOW: 5.121 + LOGV("APP_CMD_TERM_WINDOW\n"); 5.122 + pthread_cond_broadcast(&android_app->cond); 5.123 + break; 5.124 + 5.125 + case APP_CMD_RESUME: 5.126 + case APP_CMD_START: 5.127 + case APP_CMD_PAUSE: 5.128 + case APP_CMD_STOP: 5.129 + LOGV("activityState=%d\n", cmd); 5.130 + pthread_mutex_lock(&android_app->mutex); 5.131 + android_app->activityState = cmd; 5.132 + pthread_cond_broadcast(&android_app->cond); 5.133 + pthread_mutex_unlock(&android_app->mutex); 5.134 + break; 5.135 + 5.136 + case APP_CMD_CONFIG_CHANGED: 5.137 + LOGV("APP_CMD_CONFIG_CHANGED\n"); 5.138 + AConfiguration_fromAssetManager(android_app->config, 5.139 + android_app->activity->assetManager); 5.140 + print_cur_config(android_app); 5.141 + break; 5.142 + 5.143 + case APP_CMD_DESTROY: 5.144 + LOGV("APP_CMD_DESTROY\n"); 5.145 + android_app->destroyRequested = 1; 5.146 + break; 5.147 + } 5.148 +} 5.149 + 5.150 +void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) { 5.151 + switch (cmd) { 5.152 + case APP_CMD_TERM_WINDOW: 5.153 + LOGV("APP_CMD_TERM_WINDOW\n"); 5.154 + pthread_mutex_lock(&android_app->mutex); 5.155 + android_app->window = NULL; 5.156 + pthread_cond_broadcast(&android_app->cond); 5.157 + pthread_mutex_unlock(&android_app->mutex); 5.158 + break; 5.159 + 5.160 + case APP_CMD_SAVE_STATE: 5.161 + LOGV("APP_CMD_SAVE_STATE\n"); 5.162 + pthread_mutex_lock(&android_app->mutex); 5.163 + android_app->stateSaved = 1; 5.164 + pthread_cond_broadcast(&android_app->cond); 5.165 + pthread_mutex_unlock(&android_app->mutex); 5.166 + break; 5.167 + 5.168 + case APP_CMD_RESUME: 5.169 + free_saved_state(android_app); 5.170 + break; 5.171 + } 5.172 +} 5.173 + 5.174 +void app_dummy() { 5.175 + 5.176 +} 5.177 + 5.178 +static void android_app_destroy(struct android_app* android_app) { 5.179 + LOGV("android_app_destroy!"); 5.180 + free_saved_state(android_app); 5.181 + pthread_mutex_lock(&android_app->mutex); 5.182 + if (android_app->inputQueue != NULL) { 5.183 + AInputQueue_detachLooper(android_app->inputQueue); 5.184 + } 5.185 + AConfiguration_delete(android_app->config); 5.186 + android_app->destroyed = 1; 5.187 + pthread_cond_broadcast(&android_app->cond); 5.188 + pthread_mutex_unlock(&android_app->mutex); 5.189 + // Can't touch android_app object after this. 5.190 +} 5.191 + 5.192 +static void process_input(struct android_app* app, struct android_poll_source* source) { 5.193 + AInputEvent* event = NULL; 5.194 + while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { 5.195 + LOGV("New input event: type=%d\n", AInputEvent_getType(event)); 5.196 + if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { 5.197 + continue; 5.198 + } 5.199 + int32_t handled = 0; 5.200 + if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); 5.201 + AInputQueue_finishEvent(app->inputQueue, event, handled); 5.202 + } 5.203 +} 5.204 + 5.205 +static void process_cmd(struct android_app* app, struct android_poll_source* source) { 5.206 + int8_t cmd = android_app_read_cmd(app); 5.207 + android_app_pre_exec_cmd(app, cmd); 5.208 + if (app->onAppCmd != NULL) app->onAppCmd(app, cmd); 5.209 + android_app_post_exec_cmd(app, cmd); 5.210 +} 5.211 + 5.212 +static void* android_app_entry(void* param) { 5.213 + struct android_app* android_app = (struct android_app*)param; 5.214 + 5.215 + android_app->config = AConfiguration_new(); 5.216 + AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); 5.217 + 5.218 + print_cur_config(android_app); 5.219 + 5.220 + android_app->cmdPollSource.id = LOOPER_ID_MAIN; 5.221 + android_app->cmdPollSource.app = android_app; 5.222 + android_app->cmdPollSource.process = process_cmd; 5.223 + android_app->inputPollSource.id = LOOPER_ID_INPUT; 5.224 + android_app->inputPollSource.app = android_app; 5.225 + android_app->inputPollSource.process = process_input; 5.226 + 5.227 + ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); 5.228 + ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, 5.229 + &android_app->cmdPollSource); 5.230 + android_app->looper = looper; 5.231 + 5.232 + pthread_mutex_lock(&android_app->mutex); 5.233 + android_app->running = 1; 5.234 + pthread_cond_broadcast(&android_app->cond); 5.235 + pthread_mutex_unlock(&android_app->mutex); 5.236 + 5.237 + android_main(android_app); 5.238 + 5.239 + android_app_destroy(android_app); 5.240 + return NULL; 5.241 +} 5.242 + 5.243 +// -------------------------------------------------------------------- 5.244 +// Native activity interaction (called from main thread) 5.245 +// -------------------------------------------------------------------- 5.246 + 5.247 +static struct android_app* android_app_create(ANativeActivity* activity, 5.248 + void* savedState, size_t savedStateSize) { 5.249 + JNIEnv *jni = activity->env; 5.250 + struct android_app* android_app = malloc(sizeof(struct android_app)); 5.251 + memset(android_app, 0, sizeof(struct android_app)); 5.252 + android_app->activity = activity; 5.253 + 5.254 + { 5.255 + jclass foo = (*jni)->FindClass(jni, "java/lang/String"); 5.256 + if(!foo) { 5.257 + LOGE("String class not found!!!!!!\n"); 5.258 + } else { 5.259 + LOGE("Found String class!!!!!!\n"); 5.260 + } 5.261 + } 5.262 + 5.263 + if(!(android_app->activity_class = (*jni)->FindClass(jni, ACTIVITY_NAME))) { 5.264 + LOGE("could not find activity: " ACTIVITY_NAME); 5.265 + return 0; 5.266 + } 5.267 + 5.268 + pthread_mutex_init(&android_app->mutex, NULL); 5.269 + pthread_cond_init(&android_app->cond, NULL); 5.270 + 5.271 + if (savedState != NULL) { 5.272 + android_app->savedState = malloc(savedStateSize); 5.273 + android_app->savedStateSize = savedStateSize; 5.274 + memcpy(android_app->savedState, savedState, savedStateSize); 5.275 + } 5.276 + 5.277 + int msgpipe[2]; 5.278 + if (pipe(msgpipe)) { 5.279 + LOGE("could not create pipe: %s", strerror(errno)); 5.280 + return NULL; 5.281 + } 5.282 + android_app->msgread = msgpipe[0]; 5.283 + android_app->msgwrite = msgpipe[1]; 5.284 + 5.285 + pthread_attr_t attr; 5.286 + pthread_attr_init(&attr); 5.287 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 5.288 + pthread_create(&android_app->thread, &attr, android_app_entry, android_app); 5.289 + 5.290 + // Wait for thread to start. 5.291 + pthread_mutex_lock(&android_app->mutex); 5.292 + while (!android_app->running) { 5.293 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 5.294 + } 5.295 + pthread_mutex_unlock(&android_app->mutex); 5.296 + 5.297 + return android_app; 5.298 +} 5.299 + 5.300 +static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) { 5.301 + if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) { 5.302 + LOGE("Failure writing android_app cmd: %s\n", strerror(errno)); 5.303 + } 5.304 +} 5.305 + 5.306 +static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) { 5.307 + pthread_mutex_lock(&android_app->mutex); 5.308 + android_app->pendingInputQueue = inputQueue; 5.309 + android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); 5.310 + while (android_app->inputQueue != android_app->pendingInputQueue) { 5.311 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 5.312 + } 5.313 + pthread_mutex_unlock(&android_app->mutex); 5.314 +} 5.315 + 5.316 +static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) { 5.317 + pthread_mutex_lock(&android_app->mutex); 5.318 + if (android_app->pendingWindow != NULL) { 5.319 + android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW); 5.320 + } 5.321 + android_app->pendingWindow = window; 5.322 + if (window != NULL) { 5.323 + android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW); 5.324 + } 5.325 + while (android_app->window != android_app->pendingWindow) { 5.326 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 5.327 + } 5.328 + pthread_mutex_unlock(&android_app->mutex); 5.329 +} 5.330 + 5.331 +static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) { 5.332 + pthread_mutex_lock(&android_app->mutex); 5.333 + android_app_write_cmd(android_app, cmd); 5.334 + while (android_app->activityState != cmd) { 5.335 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 5.336 + } 5.337 + pthread_mutex_unlock(&android_app->mutex); 5.338 +} 5.339 + 5.340 +static void android_app_free(struct android_app* android_app) { 5.341 + pthread_mutex_lock(&android_app->mutex); 5.342 + android_app_write_cmd(android_app, APP_CMD_DESTROY); 5.343 + while (!android_app->destroyed) { 5.344 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 5.345 + } 5.346 + pthread_mutex_unlock(&android_app->mutex); 5.347 + 5.348 + close(android_app->msgread); 5.349 + close(android_app->msgwrite); 5.350 + pthread_cond_destroy(&android_app->cond); 5.351 + pthread_mutex_destroy(&android_app->mutex); 5.352 + free(android_app); 5.353 +} 5.354 + 5.355 +static void onDestroy(ANativeActivity* activity) { 5.356 + LOGV("Destroy: %p\n", activity); 5.357 + android_app_free((struct android_app*)activity->instance); 5.358 +} 5.359 + 5.360 +static void onStart(ANativeActivity* activity) { 5.361 + LOGV("Start: %p\n", activity); 5.362 + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START); 5.363 +} 5.364 + 5.365 +static void onResume(ANativeActivity* activity) { 5.366 + LOGV("Resume: %p\n", activity); 5.367 + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME); 5.368 +} 5.369 + 5.370 +static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { 5.371 + struct android_app* android_app = (struct android_app*)activity->instance; 5.372 + void* savedState = NULL; 5.373 + 5.374 + LOGV("SaveInstanceState: %p\n", activity); 5.375 + pthread_mutex_lock(&android_app->mutex); 5.376 + android_app->stateSaved = 0; 5.377 + android_app_write_cmd(android_app, APP_CMD_SAVE_STATE); 5.378 + while (!android_app->stateSaved) { 5.379 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 5.380 + } 5.381 + 5.382 + if (android_app->savedState != NULL) { 5.383 + savedState = android_app->savedState; 5.384 + *outLen = android_app->savedStateSize; 5.385 + android_app->savedState = NULL; 5.386 + android_app->savedStateSize = 0; 5.387 + } 5.388 + 5.389 + pthread_mutex_unlock(&android_app->mutex); 5.390 + 5.391 + return savedState; 5.392 +} 5.393 + 5.394 +static void onPause(ANativeActivity* activity) { 5.395 + LOGV("Pause: %p\n", activity); 5.396 + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE); 5.397 +} 5.398 + 5.399 +static void onStop(ANativeActivity* activity) { 5.400 + LOGV("Stop: %p\n", activity); 5.401 + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP); 5.402 +} 5.403 + 5.404 +static void onConfigurationChanged(ANativeActivity* activity) { 5.405 + struct android_app* android_app = (struct android_app*)activity->instance; 5.406 + LOGV("ConfigurationChanged: %p\n", activity); 5.407 + android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED); 5.408 +} 5.409 + 5.410 +static void onLowMemory(ANativeActivity* activity) { 5.411 + struct android_app* android_app = (struct android_app*)activity->instance; 5.412 + LOGV("LowMemory: %p\n", activity); 5.413 + android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY); 5.414 +} 5.415 + 5.416 +static void onWindowFocusChanged(ANativeActivity* activity, int focused) { 5.417 + LOGV("WindowFocusChanged: %p -- %d\n", activity, focused); 5.418 + android_app_write_cmd((struct android_app*)activity->instance, 5.419 + focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); 5.420 +} 5.421 + 5.422 +static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) { 5.423 + LOGV("NativeWindowCreated: %p -- %p\n", activity, window); 5.424 + android_app_set_window((struct android_app*)activity->instance, window); 5.425 +} 5.426 + 5.427 +static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) { 5.428 + LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window); 5.429 + android_app_set_window((struct android_app*)activity->instance, NULL); 5.430 +} 5.431 + 5.432 +static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { 5.433 + LOGV("InputQueueCreated: %p -- %p\n", activity, queue); 5.434 + android_app_set_input((struct android_app*)activity->instance, queue); 5.435 +} 5.436 + 5.437 +static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) { 5.438 + LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue); 5.439 + android_app_set_input((struct android_app*)activity->instance, NULL); 5.440 +} 5.441 + 5.442 +void ANativeActivity_onCreate(ANativeActivity* activity, 5.443 + void* savedState, size_t savedStateSize) { 5.444 + LOGV("Creating: %p\n", activity); 5.445 + activity->callbacks->onDestroy = onDestroy; 5.446 + activity->callbacks->onStart = onStart; 5.447 + activity->callbacks->onResume = onResume; 5.448 + activity->callbacks->onSaveInstanceState = onSaveInstanceState; 5.449 + activity->callbacks->onPause = onPause; 5.450 + activity->callbacks->onStop = onStop; 5.451 + activity->callbacks->onConfigurationChanged = onConfigurationChanged; 5.452 + activity->callbacks->onLowMemory = onLowMemory; 5.453 + activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; 5.454 + activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; 5.455 + activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; 5.456 + activity->callbacks->onInputQueueCreated = onInputQueueCreated; 5.457 + activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; 5.458 + 5.459 + activity->instance = android_app_create(activity, savedState, savedStateSize); 5.460 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/android/native_glue.h Thu May 14 23:46:56 2015 +0300 6.3 @@ -0,0 +1,352 @@ 6.4 +/* 6.5 + * Copyright (C) 2010 The Android Open Source Project 6.6 + * 6.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 6.8 + * you may not use this file except in compliance with the License. 6.9 + * You may obtain a copy of the License at 6.10 + * 6.11 + * http://www.apache.org/licenses/LICENSE-2.0 6.12 + * 6.13 + * Unless required by applicable law or agreed to in writing, software 6.14 + * distributed under the License is distributed on an "AS IS" BASIS, 6.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6.16 + * See the License for the specific language governing permissions and 6.17 + * limitations under the License. 6.18 + * 6.19 + */ 6.20 + 6.21 +#ifndef _ANDROID_NATIVE_APP_GLUE_H 6.22 +#define _ANDROID_NATIVE_APP_GLUE_H 6.23 + 6.24 +#include <poll.h> 6.25 +#include <pthread.h> 6.26 +#include <sched.h> 6.27 + 6.28 +#include <android/configuration.h> 6.29 +#include <android/looper.h> 6.30 +#include <android/native_activity.h> 6.31 + 6.32 +#ifdef __cplusplus 6.33 +extern "C" { 6.34 +#endif 6.35 + 6.36 +/** 6.37 + * The native activity interface provided by <android/native_activity.h> 6.38 + * is based on a set of application-provided callbacks that will be called 6.39 + * by the Activity's main thread when certain events occur. 6.40 + * 6.41 + * This means that each one of this callbacks _should_ _not_ block, or they 6.42 + * risk having the system force-close the application. This programming 6.43 + * model is direct, lightweight, but constraining. 6.44 + * 6.45 + * The 'android_native_app_glue' static library is used to provide a different 6.46 + * execution model where the application can implement its own main event 6.47 + * loop in a different thread instead. Here's how it works: 6.48 + * 6.49 + * 1/ The application must provide a function named "android_main()" that 6.50 + * will be called when the activity is created, in a new thread that is 6.51 + * distinct from the activity's main thread. 6.52 + * 6.53 + * 2/ android_main() receives a pointer to a valid "android_app" structure 6.54 + * that contains references to other important objects, e.g. the 6.55 + * ANativeActivity obejct instance the application is running in. 6.56 + * 6.57 + * 3/ the "android_app" object holds an ALooper instance that already 6.58 + * listens to two important things: 6.59 + * 6.60 + * - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX 6.61 + * declarations below. 6.62 + * 6.63 + * - input events coming from the AInputQueue attached to the activity. 6.64 + * 6.65 + * Each of these correspond to an ALooper identifier returned by 6.66 + * ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT, 6.67 + * respectively. 6.68 + * 6.69 + * Your application can use the same ALooper to listen to additional 6.70 + * file-descriptors. They can either be callback based, or with return 6.71 + * identifiers starting with LOOPER_ID_USER. 6.72 + * 6.73 + * 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event, 6.74 + * the returned data will point to an android_poll_source structure. You 6.75 + * can call the process() function on it, and fill in android_app->onAppCmd 6.76 + * and android_app->onInputEvent to be called for your own processing 6.77 + * of the event. 6.78 + * 6.79 + * Alternatively, you can call the low-level functions to read and process 6.80 + * the data directly... look at the process_cmd() and process_input() 6.81 + * implementations in the glue to see how to do this. 6.82 + * 6.83 + * See the sample named "native-activity" that comes with the NDK with a 6.84 + * full usage example. Also look at the JavaDoc of NativeActivity. 6.85 + */ 6.86 + 6.87 +struct android_app; 6.88 + 6.89 +/** 6.90 + * Data associated with an ALooper fd that will be returned as the "outData" 6.91 + * when that source has data ready. 6.92 + */ 6.93 +struct android_poll_source { 6.94 + // The identifier of this source. May be LOOPER_ID_MAIN or 6.95 + // LOOPER_ID_INPUT. 6.96 + int32_t id; 6.97 + 6.98 + // The android_app this ident is associated with. 6.99 + struct android_app* app; 6.100 + 6.101 + // Function to call to perform the standard processing of data from 6.102 + // this source. 6.103 + void (*process)(struct android_app* app, struct android_poll_source* source); 6.104 +}; 6.105 + 6.106 +/** 6.107 + * This is the interface for the standard glue code of a threaded 6.108 + * application. In this model, the application's code is running 6.109 + * in its own thread separate from the main thread of the process. 6.110 + * It is not required that this thread be associated with the Java 6.111 + * VM, although it will need to be in order to make JNI calls any 6.112 + * Java objects. 6.113 + */ 6.114 +struct android_app { 6.115 + // The application can place a pointer to its own state object 6.116 + // here if it likes. 6.117 + void* userData; 6.118 + 6.119 + // Fill this in with the function to process main app commands (APP_CMD_*) 6.120 + void (*onAppCmd)(struct android_app* app, int32_t cmd); 6.121 + 6.122 + // Fill this in with the function to process input events. At this point 6.123 + // the event has already been pre-dispatched, and it will be finished upon 6.124 + // return. Return 1 if you have handled the event, 0 for any default 6.125 + // dispatching. 6.126 + int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event); 6.127 + 6.128 + // The ANativeActivity object instance that this app is running in. 6.129 + ANativeActivity* activity; 6.130 + 6.131 + // The current configuration the app is running in. 6.132 + AConfiguration* config; 6.133 + 6.134 + // This is the last instance's saved state, as provided at creation time. 6.135 + // It is NULL if there was no state. You can use this as you need; the 6.136 + // memory will remain around until you call android_app_exec_cmd() for 6.137 + // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL. 6.138 + // These variables should only be changed when processing a APP_CMD_SAVE_STATE, 6.139 + // at which point they will be initialized to NULL and you can malloc your 6.140 + // state and place the information here. In that case the memory will be 6.141 + // freed for you later. 6.142 + void* savedState; 6.143 + size_t savedStateSize; 6.144 + 6.145 + // The ALooper associated with the app's thread. 6.146 + ALooper* looper; 6.147 + 6.148 + // When non-NULL, this is the input queue from which the app will 6.149 + // receive user input events. 6.150 + AInputQueue* inputQueue; 6.151 + 6.152 + // When non-NULL, this is the window surface that the app can draw in. 6.153 + ANativeWindow* window; 6.154 + 6.155 + // Current content rectangle of the window; this is the area where the 6.156 + // window's content should be placed to be seen by the user. 6.157 + ARect contentRect; 6.158 + 6.159 + // Current state of the app's activity. May be either APP_CMD_START, 6.160 + // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below. 6.161 + int activityState; 6.162 + 6.163 + // This is non-zero when the application's NativeActivity is being 6.164 + // destroyed and waiting for the app thread to complete. 6.165 + int destroyRequested; 6.166 + 6.167 + // ------------------------------------------------- 6.168 + // Below are "private" implementation of the glue code. 6.169 + 6.170 + pthread_mutex_t mutex; 6.171 + pthread_cond_t cond; 6.172 + 6.173 + int msgread; 6.174 + int msgwrite; 6.175 + 6.176 + pthread_t thread; 6.177 + 6.178 + struct android_poll_source cmdPollSource; 6.179 + struct android_poll_source inputPollSource; 6.180 + 6.181 + int running; 6.182 + int stateSaved; 6.183 + int destroyed; 6.184 + int redrawNeeded; 6.185 + AInputQueue* pendingInputQueue; 6.186 + ANativeWindow* pendingWindow; 6.187 + ARect pendingContentRect; 6.188 + 6.189 + // MainActivity class 6.190 + jclass activity_class; 6.191 +}; 6.192 + 6.193 +enum { 6.194 + /** 6.195 + * Looper data ID of commands coming from the app's main thread, which 6.196 + * is returned as an identifier from ALooper_pollOnce(). The data for this 6.197 + * identifier is a pointer to an android_poll_source structure. 6.198 + * These can be retrieved and processed with android_app_read_cmd() 6.199 + * and android_app_exec_cmd(). 6.200 + */ 6.201 + LOOPER_ID_MAIN = 1, 6.202 + 6.203 + /** 6.204 + * Looper data ID of events coming from the AInputQueue of the 6.205 + * application's window, which is returned as an identifier from 6.206 + * ALooper_pollOnce(). The data for this identifier is a pointer to an 6.207 + * android_poll_source structure. These can be read via the inputQueue 6.208 + * object of android_app. 6.209 + */ 6.210 + LOOPER_ID_INPUT = 2, 6.211 + 6.212 + /** 6.213 + * Start of user-defined ALooper identifiers. 6.214 + */ 6.215 + LOOPER_ID_USER = 3, 6.216 +}; 6.217 + 6.218 +enum { 6.219 + /** 6.220 + * Command from main thread: the AInputQueue has changed. Upon processing 6.221 + * this command, android_app->inputQueue will be updated to the new queue 6.222 + * (or NULL). 6.223 + */ 6.224 + APP_CMD_INPUT_CHANGED, 6.225 + 6.226 + /** 6.227 + * Command from main thread: a new ANativeWindow is ready for use. Upon 6.228 + * receiving this command, android_app->window will contain the new window 6.229 + * surface. 6.230 + */ 6.231 + APP_CMD_INIT_WINDOW, 6.232 + 6.233 + /** 6.234 + * Command from main thread: the existing ANativeWindow needs to be 6.235 + * terminated. Upon receiving this command, android_app->window still 6.236 + * contains the existing window; after calling android_app_exec_cmd 6.237 + * it will be set to NULL. 6.238 + */ 6.239 + APP_CMD_TERM_WINDOW, 6.240 + 6.241 + /** 6.242 + * Command from main thread: the current ANativeWindow has been resized. 6.243 + * Please redraw with its new size. 6.244 + */ 6.245 + APP_CMD_WINDOW_RESIZED, 6.246 + 6.247 + /** 6.248 + * Command from main thread: the system needs that the current ANativeWindow 6.249 + * be redrawn. You should redraw the window before handing this to 6.250 + * android_app_exec_cmd() in order to avoid transient drawing glitches. 6.251 + */ 6.252 + APP_CMD_WINDOW_REDRAW_NEEDED, 6.253 + 6.254 + /** 6.255 + * Command from main thread: the content area of the window has changed, 6.256 + * such as from the soft input window being shown or hidden. You can 6.257 + * find the new content rect in android_app::contentRect. 6.258 + */ 6.259 + APP_CMD_CONTENT_RECT_CHANGED, 6.260 + 6.261 + /** 6.262 + * Command from main thread: the app's activity window has gained 6.263 + * input focus. 6.264 + */ 6.265 + APP_CMD_GAINED_FOCUS, 6.266 + 6.267 + /** 6.268 + * Command from main thread: the app's activity window has lost 6.269 + * input focus. 6.270 + */ 6.271 + APP_CMD_LOST_FOCUS, 6.272 + 6.273 + /** 6.274 + * Command from main thread: the current device configuration has changed. 6.275 + */ 6.276 + APP_CMD_CONFIG_CHANGED, 6.277 + 6.278 + /** 6.279 + * Command from main thread: the system is running low on memory. 6.280 + * Try to reduce your memory use. 6.281 + */ 6.282 + APP_CMD_LOW_MEMORY, 6.283 + 6.284 + /** 6.285 + * Command from main thread: the app's activity has been started. 6.286 + */ 6.287 + APP_CMD_START, 6.288 + 6.289 + /** 6.290 + * Command from main thread: the app's activity has been resumed. 6.291 + */ 6.292 + APP_CMD_RESUME, 6.293 + 6.294 + /** 6.295 + * Command from main thread: the app should generate a new saved state 6.296 + * for itself, to restore from later if needed. If you have saved state, 6.297 + * allocate it with malloc and place it in android_app.savedState with 6.298 + * the size in android_app.savedStateSize. The will be freed for you 6.299 + * later. 6.300 + */ 6.301 + APP_CMD_SAVE_STATE, 6.302 + 6.303 + /** 6.304 + * Command from main thread: the app's activity has been paused. 6.305 + */ 6.306 + APP_CMD_PAUSE, 6.307 + 6.308 + /** 6.309 + * Command from main thread: the app's activity has been stopped. 6.310 + */ 6.311 + APP_CMD_STOP, 6.312 + 6.313 + /** 6.314 + * Command from main thread: the app's activity is being destroyed, 6.315 + * and waiting for the app thread to clean up and exit before proceeding. 6.316 + */ 6.317 + APP_CMD_DESTROY, 6.318 +}; 6.319 + 6.320 +/** 6.321 + * Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next 6.322 + * app command message. 6.323 + */ 6.324 +int8_t android_app_read_cmd(struct android_app* android_app); 6.325 + 6.326 +/** 6.327 + * Call with the command returned by android_app_read_cmd() to do the 6.328 + * initial pre-processing of the given command. You can perform your own 6.329 + * actions for the command after calling this function. 6.330 + */ 6.331 +void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd); 6.332 + 6.333 +/** 6.334 + * Call with the command returned by android_app_read_cmd() to do the 6.335 + * final post-processing of the given command. You must have done your own 6.336 + * actions for the command before calling this function. 6.337 + */ 6.338 +void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd); 6.339 + 6.340 +/** 6.341 + * Dummy function you can call to ensure glue code isn't stripped. 6.342 + */ 6.343 +void app_dummy(); 6.344 + 6.345 +/** 6.346 + * This is the function that application code must implement, representing 6.347 + * the main entry to the app. 6.348 + */ 6.349 +extern void android_main(struct android_app* app); 6.350 + 6.351 +#ifdef __cplusplus 6.352 +} 6.353 +#endif 6.354 + 6.355 +#endif /* _ANDROID_NATIVE_APP_GLUE_H */