istereo2
changeset 23:7d795dade0bc
first pass at android port... compiles!
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 03 Oct 2015 06:10:30 +0300 |
parents | c6971ff4795e |
children | 9d53a4938ce8 |
files | .hgignore android/Makefile android/manifest.xml.in libs/Makefile src/android/amain.c src/android/android_native_app_glue.c src/android/android_native_app_glue.h src/android/assman.c src/android/logger.c src/android/logger.h src/opengl.h |
diffstat | 11 files changed, 1290 insertions(+), 12 deletions(-) [+] |
line diff
1.1 --- a/.hgignore Fri Oct 02 07:10:19 2015 +0300 1.2 +++ b/.hgignore Sat Oct 03 06:10:30 2015 +0300 1.3 @@ -11,3 +11,11 @@ 1.4 ^data/ 1.5 \.DS_Store 1.6 ^test$ 1.7 +^android/bin/ 1.8 +^android/libs/ 1.9 +^android/res/ 1.10 +^android/src/ 1.11 +^android/assets/ 1.12 +\.xml$ 1.13 +\.properties$ 1.14 +proguard-project\.txt$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/android/Makefile Sat Oct 03 06:10:30 2015 +0300 2.3 @@ -0,0 +1,106 @@ 2.4 +bin = stereotunnel 2.5 +root = .. 2.6 +src = $(wildcard $(root)/src/*.c) 2.7 +ccsrc = $(wildcard $(root)/src/*.cc) 2.8 + 2.9 +include $(root)/libs/Makefile 2.10 + 2.11 +# --- android settings --- 2.12 +android_platform = android-19 2.13 +name = $(bin) 2.14 +pkgprefix = com.mutantstargoat 2.15 +# ------------------------ 2.16 + 2.17 +src += $(wildcard $(root)/src/android/*.c) 2.18 + 2.19 +obj = $(src:.c=.o) $(ccsrc:.cc=.o) 2.20 +lib = libs/armeabi/lib$(name).so 2.21 +apk-release = bin/$(name).apk 2.22 +apk-debug = bin/$(name)-debug.apk 2.23 + 2.24 +pkg = $(pkgprefix).$(name) 2.25 +act = android.app.NativeActivity 2.26 + 2.27 +CC = arm-linux-androideabi-gcc 2.28 +CXX = arm-linux-androideabi-g++ 2.29 + 2.30 +android_libs = -lstdc++ -llog -landroid -lEGL -lGLESv2 2.31 + 2.32 +defs += -DANDROID -DAPP_NAME=\"$(name)\" -DNO_FREETYPE -DHAVE_OPENGL_H 2.33 +CXXFLAGS = -Wall -g $(defs) -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 \ 2.34 + $(android_inc) -I$(root)/src -I$(root)/src/android $(incdir) 2.35 +CFLAGS = -std=c99 $(CXXFLAGS) 2.36 +LDFLAGS = -Wl,--fix-cortex-a8 -Wl,-z,defs $(android_libs) $(libpaths) -lm 2.37 + 2.38 +.PHONY: debug 2.39 +debug: $(apk-debug) 2.40 + 2.41 +.PHONY: release 2.42 +release: $(apk-release) 2.43 + 2.44 +$(apk-debug): $(lib) $(jsrc) AndroidManifest.xml assets/data assets/sdr 2.45 + ant debug 2.46 + 2.47 +$(apk-release): $(lib) $(jsrc) AndroidManifest.xml assets/data assets/sdr 2.48 + ant release 2.49 + 2.50 +assets/data: 2.51 + mkdir -p assets 2.52 + cd assets && rm -f data && ln -s ../../data . 2.53 + 2.54 +assets/sdr: 2.55 + mkdir -p assets 2.56 + cd assets && rm -f sdr && ln -s ../../sdr . 2.57 + 2.58 +.PHONY: lib 2.59 +lib: $(lib) 2.60 + 2.61 +$(lib): $(obj) 2.62 + @mkdir -p libs/armeabi 2.63 + $(CXX) -o $@ -shared $(obj) $(LDFLAGS) 2.64 + 2.65 +ant_files = *.xml *.properties proguard-project.txt 2.66 +ant_dirs = bin libs res obj src gen 2.67 + 2.68 +.PHONY: clean 2.69 +clean: 2.70 + rm -f $(obj) $(lib) $(apk-release) $(apk-debug) $(ant_files) 2.71 + rm -rf $(ant_dirs) 2.72 + rm -f assets/data assets/sdr 2.73 + [ -d assets ] && rmdir assets || true 2.74 + 2.75 +.PHONY: install 2.76 +install: install-debug 2.77 + 2.78 +.PHONY: install-debug 2.79 +install-debug: 2.80 + adb install -r $(apk-debug) 2.81 + 2.82 +.PHONY: install-release 2.83 +install-release: 2.84 + adb install -r $(apk-release) 2.85 + 2.86 +.PHONY: uninstall 2.87 +uninstall: 2.88 + adb uninstall $(pkg) 2.89 + 2.90 +.PHONY: run 2.91 +run: 2.92 + adb shell am start -n $(pkg)/$(act) 2.93 + 2.94 +.PHONY: stop 2.95 +stop: 2.96 + adb shell am force-stop $(pkg) 2.97 + 2.98 +AndroidManifest.xml: manifest.xml.in 2.99 + android create project -p . -t $(android_platform) -k $(pkg) -a NativeActivity -n $(name) 2.100 + cat manifest.xml.in | sed 's/$$APPNAME/$(name)/g' | sed 's/$$APPTITLE/$(title)/g' >$@ 2.101 +# cd src && rm -f *.java && ln -s ../../src/android/*.java . 2.102 + 2.103 +.PHONY: update-project 2.104 +update-project: build.xml 2.105 + android update project -p . -t $(android_platform) 2.106 + 2.107 +.PHONY: logcat 2.108 +logcat: 2.109 + adb logcat $(name):V AndroidRuntime:V DEBUG:V '*:S'
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/android/manifest.xml.in Sat Oct 03 06:10:30 2015 +0300 3.3 @@ -0,0 +1,25 @@ 3.4 +<?xml version="1.0" encoding="utf-8"?> 3.5 +<manifest xmlns:android="http://schemas.android.com/apk/res/android" 3.6 + package="com.mutantstargoat.$APPNAME" 3.7 + android:versionCode="1" 3.8 + android:versionName="1.0"> 3.9 + 3.10 + <uses-sdk android:minSdkVersion="9"/> 3.11 + 3.12 + <application android:label="$APPNAME" 3.13 + android:hasCode="false" 3.14 + android:debuggable="true"> 3.15 + <!-- android:icon="@drawable/ic_launcher" --> 3.16 + 3.17 + <activity android:name="android.app.NativeActivity" 3.18 + android:label="$APPTITLE"> 3.19 + 3.20 + <meta-data android:name="android.app.lib_name" android:value="$APPNAME"/> 3.21 + 3.22 + <intent-filter> 3.23 + <action android:name="android.intent.action.MAIN" /> 3.24 + <category android:name="android.intent.category.LAUNCHER" /> 3.25 + </intent-filter> 3.26 + </activity> 3.27 + </application> 3.28 +</manifest>
4.1 --- a/libs/Makefile Fri Oct 02 07:10:19 2015 +0300 4.2 +++ b/libs/Makefile Sat Oct 03 06:10:30 2015 +0300 4.3 @@ -1,11 +1,12 @@ 4.4 -src += $(wildcard libs/zlib/*.c) \ 4.5 - $(wildcard libs/libpng/*.c) \ 4.6 - $(wildcard libs/libjpeg/*.c) \ 4.7 - $(wildcard libs/imago2/*.c) \ 4.8 - $(wildcard libs/vmath/*.c) \ 4.9 - $(wildcard libs/drawtext/*.c) 4.10 +src += $(wildcard $(root)/libs/zlib/*.c) \ 4.11 + $(wildcard $(root)/libs/libpng/*.c) \ 4.12 + $(wildcard $(root)/libs/libjpeg/*.c) \ 4.13 + $(wildcard $(root)/libs/imago2/*.c) \ 4.14 + $(wildcard $(root)/libs/vmath/*.c) \ 4.15 + $(wildcard $(root)/libs/drawtext/*.c) 4.16 4.17 -ccsrc += $(wildcard libs/goatkit/*.cc) 4.18 +ccsrc += $(wildcard $(root)/libs/goatkit/*.cc) 4.19 4.20 -incdir += -Ilibs -Ilibs/imago2 -Ilibs/zlib -Ilibs/libpng -Ilibs/libjpeg \ 4.21 - -Ilibs/vmath -Ilibs/drawtext 4.22 +incdir += -I$(root)/libs -I$(root)/libs/imago2 -I$(root)/libs/zlib \ 4.23 + -I$(root)/libs/libpng -I$(root)/libs/libjpeg \ 4.24 + -I$(root)/libs/vmath -I$(root)/libs/drawtext
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/android/amain.c Sat Oct 03 06:10:30 2015 +0300 5.3 @@ -0,0 +1,275 @@ 5.4 +#include <stdio.h> 5.5 +#include <stdlib.h> 5.6 +#include <assert.h> 5.7 +#include <EGL/egl.h> 5.8 +#include <jni.h> 5.9 +#include "android_native_app_glue.h" 5.10 +#include <android/sensor.h> 5.11 +#include "logger.h" 5.12 +#include "istereo.h" 5.13 + 5.14 +struct android_app *app; 5.15 + 5.16 +static void handle_command(struct android_app *app, int32_t cmd); 5.17 +static int handle_input(struct android_app *app, AInputEvent *ev); 5.18 +static int handle_touch_input(struct android_app *app, AInputEvent *ev); 5.19 +static int init_gl(void); 5.20 +static void destroy_gl(void); 5.21 + 5.22 +static EGLDisplay dpy; 5.23 +static EGLSurface surf; 5.24 +static EGLContext ctx; 5.25 + 5.26 +static int redisp_pending = 1; /* TODO stop busy-looping */ 5.27 + 5.28 +static int width, height; 5.29 +static int init_done; 5.30 + 5.31 +void android_main(struct android_app *app_ptr) 5.32 +{ 5.33 + app_dummy(); 5.34 + app = app_ptr; 5.35 + 5.36 + app->onAppCmd = handle_command; 5.37 + app->onInputEvent = handle_input; 5.38 + 5.39 + start_logger(); 5.40 + 5.41 + for(;;) { 5.42 + int num_events; 5.43 + struct android_poll_source *pollsrc; 5.44 + 5.45 + while(ALooper_pollAll(0, 0, &num_events, (void**)&pollsrc) >= 0) { 5.46 + if(pollsrc) { 5.47 + pollsrc->process(app, pollsrc); 5.48 + } 5.49 + } 5.50 + 5.51 + if(app->destroyRequested) { 5.52 + return; 5.53 + } 5.54 + 5.55 + if(init_done && redisp_pending) { 5.56 + redraw(); 5.57 + eglSwapBuffers(dpy, surf); 5.58 + } 5.59 + } 5.60 +} 5.61 + 5.62 +void set_mouse_pos(int x, int y) 5.63 +{ 5.64 +} 5.65 + 5.66 +void set_mouse_cursor(int enable) 5.67 +{ 5.68 +} 5.69 + 5.70 +/* TODO */ 5.71 +void ad_banner_show(void) 5.72 +{ 5.73 +} 5.74 + 5.75 +void ad_banner_hide(void) 5.76 +{ 5.77 +} 5.78 + 5.79 +static void handle_command(struct android_app *app, int32_t cmd) 5.80 +{ 5.81 + switch(cmd) { 5.82 + case APP_CMD_SAVE_STATE: 5.83 + /* save the application state to be reloaded on restart if needed */ 5.84 + break; 5.85 + 5.86 + case APP_CMD_INIT_WINDOW: 5.87 + if(init_gl() == -1) { 5.88 + exit(1); 5.89 + } 5.90 + /* initialize the application */ 5.91 + if(init() == -1) { 5.92 + exit(1); /* initialization failed, quit */ 5.93 + } 5.94 + init_done = 1; 5.95 + break; 5.96 + 5.97 + case APP_CMD_TERM_WINDOW: 5.98 + /* cleanup */ 5.99 + init_done = 0; 5.100 + cleanup(); 5.101 + destroy_gl(); 5.102 + break; 5.103 + 5.104 + case APP_CMD_GAINED_FOCUS: 5.105 + /* app focused */ 5.106 + break; 5.107 + 5.108 + case APP_CMD_LOST_FOCUS: 5.109 + /* app lost focus */ 5.110 + break; 5.111 + 5.112 + case APP_CMD_WINDOW_RESIZED: 5.113 + case APP_CMD_CONFIG_CHANGED: 5.114 + { 5.115 + int nx = ANativeWindow_getWidth(app->window); 5.116 + int ny = ANativeWindow_getHeight(app->window); 5.117 + if(nx != width || ny != height) { 5.118 + reshape(nx, ny); 5.119 + width = nx; 5.120 + height = ny; 5.121 + } 5.122 + } 5.123 + break; 5.124 + 5.125 + default: 5.126 + break; 5.127 + } 5.128 +} 5.129 + 5.130 +static int handle_input(struct android_app *app, AInputEvent *ev) 5.131 +{ 5.132 + int evtype = AInputEvent_getType(ev); 5.133 + 5.134 + switch(evtype) { 5.135 + case AINPUT_EVENT_TYPE_MOTION: 5.136 + return handle_touch_input(app, ev); 5.137 + 5.138 + default: 5.139 + break; 5.140 + } 5.141 + return 0; 5.142 +} 5.143 + 5.144 +#define MAX_TOUCH_IDS 32 5.145 + 5.146 +static int handle_touch_input(struct android_app *app, AInputEvent *ev) 5.147 +{ 5.148 + int x, y, idx, touch_id; 5.149 + unsigned int action; 5.150 + static int prev_pos[MAX_TOUCH_IDS][2]; 5.151 + 5.152 + action = AMotionEvent_getAction(ev); 5.153 + 5.154 + idx = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> 5.155 + AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; 5.156 + touch_id = AMotionEvent_getPointerId(ev, idx); 5.157 + 5.158 + x = AMotionEvent_getX(ev, idx); 5.159 + y = AMotionEvent_getY(ev, idx); 5.160 + 5.161 + switch(action & AMOTION_EVENT_ACTION_MASK) { 5.162 + case AMOTION_EVENT_ACTION_DOWN: 5.163 + case AMOTION_EVENT_ACTION_POINTER_DOWN: 5.164 + if(touch_id == 0) { 5.165 + mouse_button(0, 1, x, y); 5.166 + } 5.167 + if(touch_id < MAX_TOUCH_IDS) { 5.168 + prev_pos[touch_id][0] = x; 5.169 + prev_pos[touch_id][1] = y; 5.170 + } 5.171 + break; 5.172 + 5.173 + case AMOTION_EVENT_ACTION_UP: 5.174 + case AMOTION_EVENT_ACTION_POINTER_UP: 5.175 + if(touch_id == 0) { 5.176 + mouse_button(0, 0, x, y); 5.177 + } 5.178 + if(touch_id < MAX_TOUCH_IDS) { 5.179 + prev_pos[touch_id][0] = x; 5.180 + prev_pos[touch_id][1] = y; 5.181 + } 5.182 + break; 5.183 + 5.184 + case AMOTION_EVENT_ACTION_MOVE: 5.185 + { 5.186 + int i, pcount = AMotionEvent_getPointerCount(ev); 5.187 + for(i=0; i<pcount; i++) { 5.188 + int id = AMotionEvent_getPointerId(ev, i); 5.189 + if(id < MAX_TOUCH_IDS && x != prev_pos[id][0] && y != prev_pos[id][1]) { 5.190 + if(id == 0) { 5.191 + mouse_motion(x, y); 5.192 + } 5.193 + prev_pos[id][0] = x; 5.194 + prev_pos[id][1] = y; 5.195 + } 5.196 + } 5.197 + } 5.198 + break; 5.199 + 5.200 + default: 5.201 + break; 5.202 + } 5.203 + 5.204 + return 1; 5.205 +} 5.206 + 5.207 + 5.208 +static int init_gl(void) 5.209 +{ 5.210 + static const int eglattr[] = { 5.211 + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 5.212 + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 5.213 + EGL_RED_SIZE, 5, 5.214 + EGL_GREEN_SIZE, 5, 5.215 + EGL_BLUE_SIZE, 5, 5.216 + EGL_DEPTH_SIZE, 16, 5.217 + EGL_NONE 5.218 + }; 5.219 + static const int ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 5.220 + 5.221 + EGLConfig eglcfg; 5.222 + int count, vis; 5.223 + 5.224 + dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 5.225 + if(!dpy || !eglInitialize(dpy, 0, 0)) { 5.226 + fprintf(stderr, "failed to initialize EGL\n"); 5.227 + destroy_gl(); 5.228 + return -1; 5.229 + } 5.230 + 5.231 + if(!eglChooseConfig(dpy, eglattr, &eglcfg, 1, &count)) { 5.232 + fprintf(stderr, "no matching EGL config found\n"); 5.233 + destroy_gl(); 5.234 + return -1; 5.235 + } 5.236 + 5.237 + /* configure the native window visual according to the chosen EGL config */ 5.238 + eglGetConfigAttrib(dpy, &eglcfg, EGL_NATIVE_VISUAL_ID, &vis); 5.239 + ANativeWindow_setBuffersGeometry(app->window, 0, 0, vis); 5.240 + 5.241 + if(!(surf = eglCreateWindowSurface(dpy, eglcfg, app->window, 0))) { 5.242 + fprintf(stderr, "failed to create window\n"); 5.243 + destroy_gl(); 5.244 + return -1; 5.245 + } 5.246 + 5.247 + if(!(ctx = eglCreateContext(dpy, eglcfg, EGL_NO_CONTEXT, ctxattr))) { 5.248 + fprintf(stderr, "failed to create OpenGL ES context\n"); 5.249 + destroy_gl(); 5.250 + return -1; 5.251 + } 5.252 + eglMakeCurrent(dpy, surf, surf, ctx); 5.253 + 5.254 + eglQuerySurface(dpy, surf, EGL_WIDTH, &width); 5.255 + eglQuerySurface(dpy, surf, EGL_HEIGHT, &height); 5.256 + reshape(width, height); 5.257 + 5.258 + return 0; 5.259 +} 5.260 + 5.261 +static void destroy_gl(void) 5.262 +{ 5.263 + if(!dpy) return; 5.264 + 5.265 + eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 5.266 + 5.267 + if(ctx) { 5.268 + eglDestroyContext(dpy, ctx); 5.269 + ctx = 0; 5.270 + } 5.271 + if(surf) { 5.272 + eglDestroySurface(dpy, surf); 5.273 + surf = 0; 5.274 + } 5.275 + 5.276 + eglTerminate(dpy); 5.277 + dpy = 0; 5.278 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/android/android_native_app_glue.c Sat Oct 03 06:10:30 2015 +0300 6.3 @@ -0,0 +1,440 @@ 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 +#include <jni.h> 6.22 + 6.23 +#include <errno.h> 6.24 +#include <string.h> 6.25 +#include <unistd.h> 6.26 +#include <sys/resource.h> 6.27 + 6.28 +#include "android_native_app_glue.h" 6.29 +#include <android/log.h> 6.30 + 6.31 +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__)) 6.32 +#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__)) 6.33 + 6.34 +/* For debug builds, always enable the debug traces in this library */ 6.35 +#ifndef NDEBUG 6.36 +# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__)) 6.37 +#else 6.38 +# define LOGV(...) ((void)0) 6.39 +#endif 6.40 + 6.41 +static void free_saved_state(struct android_app* android_app) { 6.42 + pthread_mutex_lock(&android_app->mutex); 6.43 + if (android_app->savedState != NULL) { 6.44 + free(android_app->savedState); 6.45 + android_app->savedState = NULL; 6.46 + android_app->savedStateSize = 0; 6.47 + } 6.48 + pthread_mutex_unlock(&android_app->mutex); 6.49 +} 6.50 + 6.51 +int8_t android_app_read_cmd(struct android_app* android_app) { 6.52 + int8_t cmd; 6.53 + if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) { 6.54 + switch (cmd) { 6.55 + case APP_CMD_SAVE_STATE: 6.56 + free_saved_state(android_app); 6.57 + break; 6.58 + } 6.59 + return cmd; 6.60 + } else { 6.61 + LOGE("No data on command pipe!"); 6.62 + } 6.63 + return -1; 6.64 +} 6.65 + 6.66 +static void print_cur_config(struct android_app* android_app) { 6.67 + char lang[2], country[2]; 6.68 + AConfiguration_getLanguage(android_app->config, lang); 6.69 + AConfiguration_getCountry(android_app->config, country); 6.70 + 6.71 + LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d " 6.72 + "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d " 6.73 + "modetype=%d modenight=%d", 6.74 + AConfiguration_getMcc(android_app->config), 6.75 + AConfiguration_getMnc(android_app->config), 6.76 + lang[0], lang[1], country[0], country[1], 6.77 + AConfiguration_getOrientation(android_app->config), 6.78 + AConfiguration_getTouchscreen(android_app->config), 6.79 + AConfiguration_getDensity(android_app->config), 6.80 + AConfiguration_getKeyboard(android_app->config), 6.81 + AConfiguration_getNavigation(android_app->config), 6.82 + AConfiguration_getKeysHidden(android_app->config), 6.83 + AConfiguration_getNavHidden(android_app->config), 6.84 + AConfiguration_getSdkVersion(android_app->config), 6.85 + AConfiguration_getScreenSize(android_app->config), 6.86 + AConfiguration_getScreenLong(android_app->config), 6.87 + AConfiguration_getUiModeType(android_app->config), 6.88 + AConfiguration_getUiModeNight(android_app->config)); 6.89 +} 6.90 + 6.91 +void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { 6.92 + switch (cmd) { 6.93 + case APP_CMD_INPUT_CHANGED: 6.94 + LOGV("APP_CMD_INPUT_CHANGED\n"); 6.95 + pthread_mutex_lock(&android_app->mutex); 6.96 + if (android_app->inputQueue != NULL) { 6.97 + AInputQueue_detachLooper(android_app->inputQueue); 6.98 + } 6.99 + android_app->inputQueue = android_app->pendingInputQueue; 6.100 + if (android_app->inputQueue != NULL) { 6.101 + LOGV("Attaching input queue to looper"); 6.102 + AInputQueue_attachLooper(android_app->inputQueue, 6.103 + android_app->looper, LOOPER_ID_INPUT, NULL, 6.104 + &android_app->inputPollSource); 6.105 + } 6.106 + pthread_cond_broadcast(&android_app->cond); 6.107 + pthread_mutex_unlock(&android_app->mutex); 6.108 + break; 6.109 + 6.110 + case APP_CMD_INIT_WINDOW: 6.111 + LOGV("APP_CMD_INIT_WINDOW\n"); 6.112 + pthread_mutex_lock(&android_app->mutex); 6.113 + android_app->window = android_app->pendingWindow; 6.114 + pthread_cond_broadcast(&android_app->cond); 6.115 + pthread_mutex_unlock(&android_app->mutex); 6.116 + break; 6.117 + 6.118 + case APP_CMD_TERM_WINDOW: 6.119 + LOGV("APP_CMD_TERM_WINDOW\n"); 6.120 + pthread_cond_broadcast(&android_app->cond); 6.121 + break; 6.122 + 6.123 + case APP_CMD_RESUME: 6.124 + case APP_CMD_START: 6.125 + case APP_CMD_PAUSE: 6.126 + case APP_CMD_STOP: 6.127 + LOGV("activityState=%d\n", cmd); 6.128 + pthread_mutex_lock(&android_app->mutex); 6.129 + android_app->activityState = cmd; 6.130 + pthread_cond_broadcast(&android_app->cond); 6.131 + pthread_mutex_unlock(&android_app->mutex); 6.132 + break; 6.133 + 6.134 + case APP_CMD_CONFIG_CHANGED: 6.135 + LOGV("APP_CMD_CONFIG_CHANGED\n"); 6.136 + AConfiguration_fromAssetManager(android_app->config, 6.137 + android_app->activity->assetManager); 6.138 + print_cur_config(android_app); 6.139 + break; 6.140 + 6.141 + case APP_CMD_DESTROY: 6.142 + LOGV("APP_CMD_DESTROY\n"); 6.143 + android_app->destroyRequested = 1; 6.144 + break; 6.145 + } 6.146 +} 6.147 + 6.148 +void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) { 6.149 + switch (cmd) { 6.150 + case APP_CMD_TERM_WINDOW: 6.151 + LOGV("APP_CMD_TERM_WINDOW\n"); 6.152 + pthread_mutex_lock(&android_app->mutex); 6.153 + android_app->window = NULL; 6.154 + pthread_cond_broadcast(&android_app->cond); 6.155 + pthread_mutex_unlock(&android_app->mutex); 6.156 + break; 6.157 + 6.158 + case APP_CMD_SAVE_STATE: 6.159 + LOGV("APP_CMD_SAVE_STATE\n"); 6.160 + pthread_mutex_lock(&android_app->mutex); 6.161 + android_app->stateSaved = 1; 6.162 + pthread_cond_broadcast(&android_app->cond); 6.163 + pthread_mutex_unlock(&android_app->mutex); 6.164 + break; 6.165 + 6.166 + case APP_CMD_RESUME: 6.167 + free_saved_state(android_app); 6.168 + break; 6.169 + } 6.170 +} 6.171 + 6.172 +void app_dummy() { 6.173 + 6.174 +} 6.175 + 6.176 +static void android_app_destroy(struct android_app* android_app) { 6.177 + LOGV("android_app_destroy!"); 6.178 + free_saved_state(android_app); 6.179 + pthread_mutex_lock(&android_app->mutex); 6.180 + if (android_app->inputQueue != NULL) { 6.181 + AInputQueue_detachLooper(android_app->inputQueue); 6.182 + } 6.183 + AConfiguration_delete(android_app->config); 6.184 + android_app->destroyed = 1; 6.185 + pthread_cond_broadcast(&android_app->cond); 6.186 + pthread_mutex_unlock(&android_app->mutex); 6.187 + // Can't touch android_app object after this. 6.188 +} 6.189 + 6.190 +static void process_input(struct android_app* app, struct android_poll_source* source) { 6.191 + AInputEvent* event = NULL; 6.192 + while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { 6.193 + LOGV("New input event: type=%d\n", AInputEvent_getType(event)); 6.194 + if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { 6.195 + continue; 6.196 + } 6.197 + int32_t handled = 0; 6.198 + if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); 6.199 + AInputQueue_finishEvent(app->inputQueue, event, handled); 6.200 + } 6.201 +} 6.202 + 6.203 +static void process_cmd(struct android_app* app, struct android_poll_source* source) { 6.204 + int8_t cmd = android_app_read_cmd(app); 6.205 + android_app_pre_exec_cmd(app, cmd); 6.206 + if (app->onAppCmd != NULL) app->onAppCmd(app, cmd); 6.207 + android_app_post_exec_cmd(app, cmd); 6.208 +} 6.209 + 6.210 +static void* android_app_entry(void* param) { 6.211 + struct android_app* android_app = (struct android_app*)param; 6.212 + 6.213 + android_app->config = AConfiguration_new(); 6.214 + AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); 6.215 + 6.216 + print_cur_config(android_app); 6.217 + 6.218 + android_app->cmdPollSource.id = LOOPER_ID_MAIN; 6.219 + android_app->cmdPollSource.app = android_app; 6.220 + android_app->cmdPollSource.process = process_cmd; 6.221 + android_app->inputPollSource.id = LOOPER_ID_INPUT; 6.222 + android_app->inputPollSource.app = android_app; 6.223 + android_app->inputPollSource.process = process_input; 6.224 + 6.225 + ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); 6.226 + ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, 6.227 + &android_app->cmdPollSource); 6.228 + android_app->looper = looper; 6.229 + 6.230 + pthread_mutex_lock(&android_app->mutex); 6.231 + android_app->running = 1; 6.232 + pthread_cond_broadcast(&android_app->cond); 6.233 + pthread_mutex_unlock(&android_app->mutex); 6.234 + 6.235 + android_main(android_app); 6.236 + 6.237 + android_app_destroy(android_app); 6.238 + return NULL; 6.239 +} 6.240 + 6.241 +// -------------------------------------------------------------------- 6.242 +// Native activity interaction (called from main thread) 6.243 +// -------------------------------------------------------------------- 6.244 + 6.245 +static struct android_app* android_app_create(ANativeActivity* activity, 6.246 + void* savedState, size_t savedStateSize) { 6.247 + struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app)); 6.248 + memset(android_app, 0, sizeof(struct android_app)); 6.249 + android_app->activity = activity; 6.250 + 6.251 + pthread_mutex_init(&android_app->mutex, NULL); 6.252 + pthread_cond_init(&android_app->cond, NULL); 6.253 + 6.254 + if (savedState != NULL) { 6.255 + android_app->savedState = malloc(savedStateSize); 6.256 + android_app->savedStateSize = savedStateSize; 6.257 + memcpy(android_app->savedState, savedState, savedStateSize); 6.258 + } 6.259 + 6.260 + int msgpipe[2]; 6.261 + if (pipe(msgpipe)) { 6.262 + LOGE("could not create pipe: %s", strerror(errno)); 6.263 + return NULL; 6.264 + } 6.265 + android_app->msgread = msgpipe[0]; 6.266 + android_app->msgwrite = msgpipe[1]; 6.267 + 6.268 + pthread_attr_t attr; 6.269 + pthread_attr_init(&attr); 6.270 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 6.271 + pthread_create(&android_app->thread, &attr, android_app_entry, android_app); 6.272 + 6.273 + // Wait for thread to start. 6.274 + pthread_mutex_lock(&android_app->mutex); 6.275 + while (!android_app->running) { 6.276 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 6.277 + } 6.278 + pthread_mutex_unlock(&android_app->mutex); 6.279 + 6.280 + return android_app; 6.281 +} 6.282 + 6.283 +static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) { 6.284 + if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) { 6.285 + LOGE("Failure writing android_app cmd: %s\n", strerror(errno)); 6.286 + } 6.287 +} 6.288 + 6.289 +static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) { 6.290 + pthread_mutex_lock(&android_app->mutex); 6.291 + android_app->pendingInputQueue = inputQueue; 6.292 + android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); 6.293 + while (android_app->inputQueue != android_app->pendingInputQueue) { 6.294 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 6.295 + } 6.296 + pthread_mutex_unlock(&android_app->mutex); 6.297 +} 6.298 + 6.299 +static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) { 6.300 + pthread_mutex_lock(&android_app->mutex); 6.301 + if (android_app->pendingWindow != NULL) { 6.302 + android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW); 6.303 + } 6.304 + android_app->pendingWindow = window; 6.305 + if (window != NULL) { 6.306 + android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW); 6.307 + } 6.308 + while (android_app->window != android_app->pendingWindow) { 6.309 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 6.310 + } 6.311 + pthread_mutex_unlock(&android_app->mutex); 6.312 +} 6.313 + 6.314 +static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) { 6.315 + pthread_mutex_lock(&android_app->mutex); 6.316 + android_app_write_cmd(android_app, cmd); 6.317 + while (android_app->activityState != cmd) { 6.318 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 6.319 + } 6.320 + pthread_mutex_unlock(&android_app->mutex); 6.321 +} 6.322 + 6.323 +static void android_app_free(struct android_app* android_app) { 6.324 + pthread_mutex_lock(&android_app->mutex); 6.325 + android_app_write_cmd(android_app, APP_CMD_DESTROY); 6.326 + while (!android_app->destroyed) { 6.327 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 6.328 + } 6.329 + pthread_mutex_unlock(&android_app->mutex); 6.330 + 6.331 + close(android_app->msgread); 6.332 + close(android_app->msgwrite); 6.333 + pthread_cond_destroy(&android_app->cond); 6.334 + pthread_mutex_destroy(&android_app->mutex); 6.335 + free(android_app); 6.336 +} 6.337 + 6.338 +static void onDestroy(ANativeActivity* activity) { 6.339 + LOGV("Destroy: %p\n", activity); 6.340 + android_app_free((struct android_app*)activity->instance); 6.341 +} 6.342 + 6.343 +static void onStart(ANativeActivity* activity) { 6.344 + LOGV("Start: %p\n", activity); 6.345 + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START); 6.346 +} 6.347 + 6.348 +static void onResume(ANativeActivity* activity) { 6.349 + LOGV("Resume: %p\n", activity); 6.350 + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME); 6.351 +} 6.352 + 6.353 +static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { 6.354 + struct android_app* android_app = (struct android_app*)activity->instance; 6.355 + void* savedState = NULL; 6.356 + 6.357 + LOGV("SaveInstanceState: %p\n", activity); 6.358 + pthread_mutex_lock(&android_app->mutex); 6.359 + android_app->stateSaved = 0; 6.360 + android_app_write_cmd(android_app, APP_CMD_SAVE_STATE); 6.361 + while (!android_app->stateSaved) { 6.362 + pthread_cond_wait(&android_app->cond, &android_app->mutex); 6.363 + } 6.364 + 6.365 + if (android_app->savedState != NULL) { 6.366 + savedState = android_app->savedState; 6.367 + *outLen = android_app->savedStateSize; 6.368 + android_app->savedState = NULL; 6.369 + android_app->savedStateSize = 0; 6.370 + } 6.371 + 6.372 + pthread_mutex_unlock(&android_app->mutex); 6.373 + 6.374 + return savedState; 6.375 +} 6.376 + 6.377 +static void onPause(ANativeActivity* activity) { 6.378 + LOGV("Pause: %p\n", activity); 6.379 + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE); 6.380 +} 6.381 + 6.382 +static void onStop(ANativeActivity* activity) { 6.383 + LOGV("Stop: %p\n", activity); 6.384 + android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP); 6.385 +} 6.386 + 6.387 +static void onConfigurationChanged(ANativeActivity* activity) { 6.388 + struct android_app* android_app = (struct android_app*)activity->instance; 6.389 + LOGV("ConfigurationChanged: %p\n", activity); 6.390 + android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED); 6.391 +} 6.392 + 6.393 +static void onLowMemory(ANativeActivity* activity) { 6.394 + struct android_app* android_app = (struct android_app*)activity->instance; 6.395 + LOGV("LowMemory: %p\n", activity); 6.396 + android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY); 6.397 +} 6.398 + 6.399 +static void onWindowFocusChanged(ANativeActivity* activity, int focused) { 6.400 + LOGV("WindowFocusChanged: %p -- %d\n", activity, focused); 6.401 + android_app_write_cmd((struct android_app*)activity->instance, 6.402 + focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); 6.403 +} 6.404 + 6.405 +static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) { 6.406 + LOGV("NativeWindowCreated: %p -- %p\n", activity, window); 6.407 + android_app_set_window((struct android_app*)activity->instance, window); 6.408 +} 6.409 + 6.410 +static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) { 6.411 + LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window); 6.412 + android_app_set_window((struct android_app*)activity->instance, NULL); 6.413 +} 6.414 + 6.415 +static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { 6.416 + LOGV("InputQueueCreated: %p -- %p\n", activity, queue); 6.417 + android_app_set_input((struct android_app*)activity->instance, queue); 6.418 +} 6.419 + 6.420 +static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) { 6.421 + LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue); 6.422 + android_app_set_input((struct android_app*)activity->instance, NULL); 6.423 +} 6.424 + 6.425 +void ANativeActivity_onCreate(ANativeActivity* activity, 6.426 + void* savedState, size_t savedStateSize) { 6.427 + LOGV("Creating: %p\n", activity); 6.428 + activity->callbacks->onDestroy = onDestroy; 6.429 + activity->callbacks->onStart = onStart; 6.430 + activity->callbacks->onResume = onResume; 6.431 + activity->callbacks->onSaveInstanceState = onSaveInstanceState; 6.432 + activity->callbacks->onPause = onPause; 6.433 + activity->callbacks->onStop = onStop; 6.434 + activity->callbacks->onConfigurationChanged = onConfigurationChanged; 6.435 + activity->callbacks->onLowMemory = onLowMemory; 6.436 + activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; 6.437 + activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; 6.438 + activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; 6.439 + activity->callbacks->onInputQueueCreated = onInputQueueCreated; 6.440 + activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; 6.441 + 6.442 + activity->instance = android_app_create(activity, savedState, savedStateSize); 6.443 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/android/android_native_app_glue.h Sat Oct 03 06:10:30 2015 +0300 7.3 @@ -0,0 +1,349 @@ 7.4 +/* 7.5 + * Copyright (C) 2010 The Android Open Source Project 7.6 + * 7.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 7.8 + * you may not use this file except in compliance with the License. 7.9 + * You may obtain a copy of the License at 7.10 + * 7.11 + * http://www.apache.org/licenses/LICENSE-2.0 7.12 + * 7.13 + * Unless required by applicable law or agreed to in writing, software 7.14 + * distributed under the License is distributed on an "AS IS" BASIS, 7.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7.16 + * See the License for the specific language governing permissions and 7.17 + * limitations under the License. 7.18 + * 7.19 + */ 7.20 + 7.21 +#ifndef _ANDROID_NATIVE_APP_GLUE_H 7.22 +#define _ANDROID_NATIVE_APP_GLUE_H 7.23 + 7.24 +#include <poll.h> 7.25 +#include <pthread.h> 7.26 +#include <sched.h> 7.27 + 7.28 +#include <android/configuration.h> 7.29 +#include <android/looper.h> 7.30 +#include <android/native_activity.h> 7.31 + 7.32 +#ifdef __cplusplus 7.33 +extern "C" { 7.34 +#endif 7.35 + 7.36 +/** 7.37 + * The native activity interface provided by <android/native_activity.h> 7.38 + * is based on a set of application-provided callbacks that will be called 7.39 + * by the Activity's main thread when certain events occur. 7.40 + * 7.41 + * This means that each one of this callbacks _should_ _not_ block, or they 7.42 + * risk having the system force-close the application. This programming 7.43 + * model is direct, lightweight, but constraining. 7.44 + * 7.45 + * The 'android_native_app_glue' static library is used to provide a different 7.46 + * execution model where the application can implement its own main event 7.47 + * loop in a different thread instead. Here's how it works: 7.48 + * 7.49 + * 1/ The application must provide a function named "android_main()" that 7.50 + * will be called when the activity is created, in a new thread that is 7.51 + * distinct from the activity's main thread. 7.52 + * 7.53 + * 2/ android_main() receives a pointer to a valid "android_app" structure 7.54 + * that contains references to other important objects, e.g. the 7.55 + * ANativeActivity obejct instance the application is running in. 7.56 + * 7.57 + * 3/ the "android_app" object holds an ALooper instance that already 7.58 + * listens to two important things: 7.59 + * 7.60 + * - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX 7.61 + * declarations below. 7.62 + * 7.63 + * - input events coming from the AInputQueue attached to the activity. 7.64 + * 7.65 + * Each of these correspond to an ALooper identifier returned by 7.66 + * ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT, 7.67 + * respectively. 7.68 + * 7.69 + * Your application can use the same ALooper to listen to additional 7.70 + * file-descriptors. They can either be callback based, or with return 7.71 + * identifiers starting with LOOPER_ID_USER. 7.72 + * 7.73 + * 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event, 7.74 + * the returned data will point to an android_poll_source structure. You 7.75 + * can call the process() function on it, and fill in android_app->onAppCmd 7.76 + * and android_app->onInputEvent to be called for your own processing 7.77 + * of the event. 7.78 + * 7.79 + * Alternatively, you can call the low-level functions to read and process 7.80 + * the data directly... look at the process_cmd() and process_input() 7.81 + * implementations in the glue to see how to do this. 7.82 + * 7.83 + * See the sample named "native-activity" that comes with the NDK with a 7.84 + * full usage example. Also look at the JavaDoc of NativeActivity. 7.85 + */ 7.86 + 7.87 +struct android_app; 7.88 + 7.89 +/** 7.90 + * Data associated with an ALooper fd that will be returned as the "outData" 7.91 + * when that source has data ready. 7.92 + */ 7.93 +struct android_poll_source { 7.94 + // The identifier of this source. May be LOOPER_ID_MAIN or 7.95 + // LOOPER_ID_INPUT. 7.96 + int32_t id; 7.97 + 7.98 + // The android_app this ident is associated with. 7.99 + struct android_app* app; 7.100 + 7.101 + // Function to call to perform the standard processing of data from 7.102 + // this source. 7.103 + void (*process)(struct android_app* app, struct android_poll_source* source); 7.104 +}; 7.105 + 7.106 +/** 7.107 + * This is the interface for the standard glue code of a threaded 7.108 + * application. In this model, the application's code is running 7.109 + * in its own thread separate from the main thread of the process. 7.110 + * It is not required that this thread be associated with the Java 7.111 + * VM, although it will need to be in order to make JNI calls any 7.112 + * Java objects. 7.113 + */ 7.114 +struct android_app { 7.115 + // The application can place a pointer to its own state object 7.116 + // here if it likes. 7.117 + void* userData; 7.118 + 7.119 + // Fill this in with the function to process main app commands (APP_CMD_*) 7.120 + void (*onAppCmd)(struct android_app* app, int32_t cmd); 7.121 + 7.122 + // Fill this in with the function to process input events. At this point 7.123 + // the event has already been pre-dispatched, and it will be finished upon 7.124 + // return. Return 1 if you have handled the event, 0 for any default 7.125 + // dispatching. 7.126 + int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event); 7.127 + 7.128 + // The ANativeActivity object instance that this app is running in. 7.129 + ANativeActivity* activity; 7.130 + 7.131 + // The current configuration the app is running in. 7.132 + AConfiguration* config; 7.133 + 7.134 + // This is the last instance's saved state, as provided at creation time. 7.135 + // It is NULL if there was no state. You can use this as you need; the 7.136 + // memory will remain around until you call android_app_exec_cmd() for 7.137 + // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL. 7.138 + // These variables should only be changed when processing a APP_CMD_SAVE_STATE, 7.139 + // at which point they will be initialized to NULL and you can malloc your 7.140 + // state and place the information here. In that case the memory will be 7.141 + // freed for you later. 7.142 + void* savedState; 7.143 + size_t savedStateSize; 7.144 + 7.145 + // The ALooper associated with the app's thread. 7.146 + ALooper* looper; 7.147 + 7.148 + // When non-NULL, this is the input queue from which the app will 7.149 + // receive user input events. 7.150 + AInputQueue* inputQueue; 7.151 + 7.152 + // When non-NULL, this is the window surface that the app can draw in. 7.153 + ANativeWindow* window; 7.154 + 7.155 + // Current content rectangle of the window; this is the area where the 7.156 + // window's content should be placed to be seen by the user. 7.157 + ARect contentRect; 7.158 + 7.159 + // Current state of the app's activity. May be either APP_CMD_START, 7.160 + // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below. 7.161 + int activityState; 7.162 + 7.163 + // This is non-zero when the application's NativeActivity is being 7.164 + // destroyed and waiting for the app thread to complete. 7.165 + int destroyRequested; 7.166 + 7.167 + // ------------------------------------------------- 7.168 + // Below are "private" implementation of the glue code. 7.169 + 7.170 + pthread_mutex_t mutex; 7.171 + pthread_cond_t cond; 7.172 + 7.173 + int msgread; 7.174 + int msgwrite; 7.175 + 7.176 + pthread_t thread; 7.177 + 7.178 + struct android_poll_source cmdPollSource; 7.179 + struct android_poll_source inputPollSource; 7.180 + 7.181 + int running; 7.182 + int stateSaved; 7.183 + int destroyed; 7.184 + int redrawNeeded; 7.185 + AInputQueue* pendingInputQueue; 7.186 + ANativeWindow* pendingWindow; 7.187 + ARect pendingContentRect; 7.188 +}; 7.189 + 7.190 +enum { 7.191 + /** 7.192 + * Looper data ID of commands coming from the app's main thread, which 7.193 + * is returned as an identifier from ALooper_pollOnce(). The data for this 7.194 + * identifier is a pointer to an android_poll_source structure. 7.195 + * These can be retrieved and processed with android_app_read_cmd() 7.196 + * and android_app_exec_cmd(). 7.197 + */ 7.198 + LOOPER_ID_MAIN = 1, 7.199 + 7.200 + /** 7.201 + * Looper data ID of events coming from the AInputQueue of the 7.202 + * application's window, which is returned as an identifier from 7.203 + * ALooper_pollOnce(). The data for this identifier is a pointer to an 7.204 + * android_poll_source structure. These can be read via the inputQueue 7.205 + * object of android_app. 7.206 + */ 7.207 + LOOPER_ID_INPUT = 2, 7.208 + 7.209 + /** 7.210 + * Start of user-defined ALooper identifiers. 7.211 + */ 7.212 + LOOPER_ID_USER = 3, 7.213 +}; 7.214 + 7.215 +enum { 7.216 + /** 7.217 + * Command from main thread: the AInputQueue has changed. Upon processing 7.218 + * this command, android_app->inputQueue will be updated to the new queue 7.219 + * (or NULL). 7.220 + */ 7.221 + APP_CMD_INPUT_CHANGED, 7.222 + 7.223 + /** 7.224 + * Command from main thread: a new ANativeWindow is ready for use. Upon 7.225 + * receiving this command, android_app->window will contain the new window 7.226 + * surface. 7.227 + */ 7.228 + APP_CMD_INIT_WINDOW, 7.229 + 7.230 + /** 7.231 + * Command from main thread: the existing ANativeWindow needs to be 7.232 + * terminated. Upon receiving this command, android_app->window still 7.233 + * contains the existing window; after calling android_app_exec_cmd 7.234 + * it will be set to NULL. 7.235 + */ 7.236 + APP_CMD_TERM_WINDOW, 7.237 + 7.238 + /** 7.239 + * Command from main thread: the current ANativeWindow has been resized. 7.240 + * Please redraw with its new size. 7.241 + */ 7.242 + APP_CMD_WINDOW_RESIZED, 7.243 + 7.244 + /** 7.245 + * Command from main thread: the system needs that the current ANativeWindow 7.246 + * be redrawn. You should redraw the window before handing this to 7.247 + * android_app_exec_cmd() in order to avoid transient drawing glitches. 7.248 + */ 7.249 + APP_CMD_WINDOW_REDRAW_NEEDED, 7.250 + 7.251 + /** 7.252 + * Command from main thread: the content area of the window has changed, 7.253 + * such as from the soft input window being shown or hidden. You can 7.254 + * find the new content rect in android_app::contentRect. 7.255 + */ 7.256 + APP_CMD_CONTENT_RECT_CHANGED, 7.257 + 7.258 + /** 7.259 + * Command from main thread: the app's activity window has gained 7.260 + * input focus. 7.261 + */ 7.262 + APP_CMD_GAINED_FOCUS, 7.263 + 7.264 + /** 7.265 + * Command from main thread: the app's activity window has lost 7.266 + * input focus. 7.267 + */ 7.268 + APP_CMD_LOST_FOCUS, 7.269 + 7.270 + /** 7.271 + * Command from main thread: the current device configuration has changed. 7.272 + */ 7.273 + APP_CMD_CONFIG_CHANGED, 7.274 + 7.275 + /** 7.276 + * Command from main thread: the system is running low on memory. 7.277 + * Try to reduce your memory use. 7.278 + */ 7.279 + APP_CMD_LOW_MEMORY, 7.280 + 7.281 + /** 7.282 + * Command from main thread: the app's activity has been started. 7.283 + */ 7.284 + APP_CMD_START, 7.285 + 7.286 + /** 7.287 + * Command from main thread: the app's activity has been resumed. 7.288 + */ 7.289 + APP_CMD_RESUME, 7.290 + 7.291 + /** 7.292 + * Command from main thread: the app should generate a new saved state 7.293 + * for itself, to restore from later if needed. If you have saved state, 7.294 + * allocate it with malloc and place it in android_app.savedState with 7.295 + * the size in android_app.savedStateSize. The will be freed for you 7.296 + * later. 7.297 + */ 7.298 + APP_CMD_SAVE_STATE, 7.299 + 7.300 + /** 7.301 + * Command from main thread: the app's activity has been paused. 7.302 + */ 7.303 + APP_CMD_PAUSE, 7.304 + 7.305 + /** 7.306 + * Command from main thread: the app's activity has been stopped. 7.307 + */ 7.308 + APP_CMD_STOP, 7.309 + 7.310 + /** 7.311 + * Command from main thread: the app's activity is being destroyed, 7.312 + * and waiting for the app thread to clean up and exit before proceeding. 7.313 + */ 7.314 + APP_CMD_DESTROY, 7.315 +}; 7.316 + 7.317 +/** 7.318 + * Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next 7.319 + * app command message. 7.320 + */ 7.321 +int8_t android_app_read_cmd(struct android_app* android_app); 7.322 + 7.323 +/** 7.324 + * Call with the command returned by android_app_read_cmd() to do the 7.325 + * initial pre-processing of the given command. You can perform your own 7.326 + * actions for the command after calling this function. 7.327 + */ 7.328 +void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd); 7.329 + 7.330 +/** 7.331 + * Call with the command returned by android_app_read_cmd() to do the 7.332 + * final post-processing of the given command. You must have done your own 7.333 + * actions for the command before calling this function. 7.334 + */ 7.335 +void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd); 7.336 + 7.337 +/** 7.338 + * Dummy function you can call to ensure glue code isn't stripped. 7.339 + */ 7.340 +void app_dummy(); 7.341 + 7.342 +/** 7.343 + * This is the function that application code must implement, representing 7.344 + * the main entry to the app. 7.345 + */ 7.346 +extern void android_main(struct android_app* app); 7.347 + 7.348 +#ifdef __cplusplus 7.349 +} 7.350 +#endif 7.351 + 7.352 +#endif /* _ANDROID_NATIVE_APP_GLUE_H */
8.1 --- a/src/android/assman.c Fri Oct 02 07:10:19 2015 +0300 8.2 +++ b/src/android/assman.c Sat Oct 03 06:10:30 2015 +0300 8.3 @@ -1,8 +1,9 @@ 8.4 #include <fcntl.h> 8.5 #include <android/asset_manager.h> 8.6 #include "assman.h" 8.7 -#include "native_glue.h" 8.8 -#include "amain.h" 8.9 +#include "android_native_app_glue.h" 8.10 + 8.11 +struct android_app *app; /* defined in android/amain.c */ 8.12 8.13 ass_file *ass_fopen(const char *fname, const char *mode) 8.14 {
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/android/logger.c Sat Oct 03 06:10:30 2015 +0300 9.3 @@ -0,0 +1,60 @@ 9.4 +#include <stdio.h> 9.5 +#include <assert.h> 9.6 +#include <unistd.h> 9.7 +#include <pthread.h> 9.8 +#include <android/log.h> 9.9 +#include "logger.h" 9.10 + 9.11 +static void *thread_func(void *arg); 9.12 + 9.13 +static int pfd[2]; 9.14 +static pthread_t thr; 9.15 +static int initialized; 9.16 + 9.17 +int start_logger(void) 9.18 +{ 9.19 + if(initialized) { 9.20 + return 1; 9.21 + } 9.22 + 9.23 + /* set stdout to line-buffered, and stderr to unbuffered */ 9.24 + setvbuf(stdout, 0, _IOLBF, 0); 9.25 + setvbuf(stderr, 0, _IONBF, 0); 9.26 + 9.27 + if(pipe(pfd) == -1) { 9.28 + perror("failed to create logging pipe"); 9.29 + return -1; 9.30 + } 9.31 + assert(pfd[0] > 2 && pfd[1] > 2); 9.32 + 9.33 + /* redirect stdout & stderr to the write-end of the pipe */ 9.34 + dup2(pfd[1], 1); 9.35 + dup2(pfd[1], 2); 9.36 + 9.37 + /* start the logging thread */ 9.38 + if(pthread_create(&thr, 0, thread_func, 0) == -1) { 9.39 + perror("failed to spawn logging thread"); 9.40 + return -1; 9.41 + } 9.42 + pthread_detach(thr); 9.43 + return 0; 9.44 +} 9.45 + 9.46 +static void *thread_func(void *arg) 9.47 +{ 9.48 + ssize_t rdsz; 9.49 + char buf[257]; 9.50 + 9.51 + __android_log_print(ANDROID_LOG_DEBUG, APP_NAME, "logger starting up..."); 9.52 + 9.53 + while((rdsz = read(pfd[0], buf, sizeof buf - 1)) > 0) { 9.54 + if(buf[rdsz - 1] == '\n') { 9.55 + --rdsz; 9.56 + } 9.57 + buf[rdsz] = 0; 9.58 + __android_log_write(ANDROID_LOG_DEBUG, APP_NAME, buf); 9.59 + } 9.60 + 9.61 + __android_log_print(ANDROID_LOG_DEBUG, APP_NAME, "logger shutting down..."); 9.62 + return 0; 9.63 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/android/logger.h Sat Oct 03 06:10:30 2015 +0300 10.3 @@ -0,0 +1,6 @@ 10.4 +#ifndef LOGGER_H_ 10.5 +#define LOGGER_H_ 10.6 + 10.7 +int start_logger(void); 10.8 + 10.9 +#endif /* LOGGER_H_ */
11.1 --- a/src/opengl.h Fri Oct 02 07:10:19 2015 +0300 11.2 +++ b/src/opengl.h Sat Oct 03 06:10:30 2015 +0300 11.3 @@ -1,6 +1,6 @@ 11.4 /* 11.5 Stereoscopic tunnel for iOS. 11.6 -Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org> 11.7 +Copyright (C) 2011-2015 John Tsiombikas <nuclear@member.fsf.org> 11.8 11.9 This program is free software: you can redistribute it and/or modify 11.10 it under the terms of the GNU General Public License as published by 11.11 @@ -28,6 +28,13 @@ 11.12 #define glClearDepth glClearDepthf 11.13 #define GLDEF 11.14 #include "sanegl.h" 11.15 + 11.16 +#elif defined(ANDROID) 11.17 +#include <GLES2/gl2.h> 11.18 +#include <GLES2/gl2ext.h> 11.19 +#define GLDEF 11.20 +#include "sanegl.h" 11.21 + 11.22 #else 11.23 11.24 #include <GL/glew.h>