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 */