Permalink
Browse files

moved platform dependent code into separate functions

support multiple native libraries within a single apk (required for unity)
  • Loading branch information...
1 parent 955950b commit ce2b496785349f2e50f5de5d95bbd35ed588388a @crowriot crowriot committed Jan 13, 2013
Showing with 227 additions and 85 deletions.
  1. +147 −67 apkenv.c
  2. +11 −2 apkenv.h
  3. +17 −8 apklib/apklib.c
  4. +6 −1 apklib/apklib.h
  5. +4 −0 jni/jnienv.c
  6. +2 −0 jni/jnienv.h
  7. +37 −7 jni/shlib.c
  8. +3 −0 jni/shlib.h
View
214 apkenv.c
@@ -60,6 +60,12 @@ lookup_symbol_impl(const char *method)
return jni_shlib_resolve(&global, method);
}
+void *
+lookup_lib_symbol_impl(const char *lib, const char *method)
+{
+ return jni_shlib_lib_resolve(&global, lib, method);
+}
+
void
foreach_file_impl(const char *prefix, apk_for_each_file_callback callback)
{
@@ -295,50 +301,10 @@ operation(const char *operation, const char *filename)
#define MEEGOTOUCH_BORDER 16
-//#define NOSDL
-
+void* platform_data = 0;
-int main(int argc, char **argv)
+SDL_Surface* platform_init()
{
- char **tmp;
-
- recursive_mkdir(DATA_DIRECTORY_BASE);
- global.apkenv_executable = argv[0];
- global.apkenv_headline = APKENV_HEADLINE;
- global.apkenv_copyright = APKENV_COPYRIGHT;
-
- printf("%s\n%s\n\n", global.apkenv_headline, global.apkenv_copyright);
-
- switch (argc) {
- case 2:
- /* One argument - the .apk (continue below) */
- break;
- case 3:
- /* Two arguments - operation + the apk */
- operation(argv[1], argv[2]);
- break;
- default:
- /* Wrong number of arguments */
- usage();
- }
-
- global.lookup_symbol = lookup_symbol_impl;
- global.foreach_file = foreach_file_impl;
- global.read_file = read_file_impl;
-
- jnienv_init(&global);
- javavm_init(&global);
- global.apk_filename = strdup(argv[argc-1]);
- global.apklib_handle = apk_open(global.apk_filename);
- global.support_modules = NULL;
-
-
- const char *shlib = apk_get_shared_library(global.apklib_handle);
- if (shlib == NULL) {
- printf("Not a native APK.\n");
- return 0;
- }
-
SDL_Surface* screen;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) {
printf("SDL Init failed.\n");
@@ -355,8 +321,12 @@ int main(int argc, char **argv)
**/
#ifdef PANDORA
screen = SDL_SetVideoMode(SCREEN_WIDTH,SCREEN_HEIGHT,0,SDL_FULLSCREEN);
- void* gles = GLES_Init(1);
- if (!gles) {
+#if defined(APKENV_GLES2)
+ platform_data = GLES_Init(2);
+#else
+ platform_data = GLES_Init(1);
+#endif
+ if (!platform_data) {
fprintf(stderr,"ERROR: GLES_Init failed.\n");
return 0;
}
@@ -397,15 +367,115 @@ int main(int argc, char **argv)
XChangeProperty(dpy, wm.info.x11.wmwindow, atom, XA_CARDINAL, 32,
PropModeReplace, (unsigned char*)region, 4);
#endif
+ return screen;
+}
+
+void platform_swap()
+{
+#ifdef PANDORA
+ GLES_SwapBuffers(platform_data);
+#elif defined(FREMANTLE)
+ SDL_GLES_SwapBuffers();
+#else
+ SDL_GL_SwapBuffers();
+#endif
+}
+
+void platform_exit()
+{
+#ifdef PANDORA
+ GLES_Exit(platform_data);
+#endif
+}
+
+int main(int argc, char **argv)
+{
+ char **tmp;
- global.method_table = jni_shlib_find_methods(shlib);
- global.jni_library = android_dlopen(shlib, RTLD_LAZY);
- unlink(shlib);
- if (!(global.jni_library)) {
- printf("Missing library dependencies.\n");
+ recursive_mkdir(DATA_DIRECTORY_BASE);
+
+ global.apkenv_executable = argv[0];
+ global.apkenv_headline = APKENV_HEADLINE;
+ global.apkenv_copyright = APKENV_COPYRIGHT;
+
+ printf("%s\n%s\n\n", global.apkenv_headline, global.apkenv_copyright);
+
+ switch (argc) {
+ case 2:
+ /* One argument - the .apk (continue below) */
+ break;
+ case 3:
+ /* Two arguments - operation + the apk */
+ operation(argv[1], argv[2]);
+ break;
+ default:
+ /* Wrong number of arguments */
+ usage();
+ }
+
+ global.lookup_symbol = lookup_symbol_impl;
+ global.lookup_lib_symbol = lookup_lib_symbol_impl;
+ global.foreach_file = foreach_file_impl;
+ global.read_file = read_file_impl;
+
+ jnienv_init(&global);
+ javavm_init(&global);
+ global.apk_filename = strdup(argv[argc-1]);
+ global.apklib_handle = apk_open(global.apk_filename);
+ global.support_modules = NULL;
+
+
+ /*
+ const char *shlib = apk_get_shared_library(global.apklib_handle,"");
+ if (shlib == NULL) {
+ printf("Not a native APK.\n");
+ return 0;
+ }
+ */
+ const char* libdir[] = {
+ "assets/libs/armeabi-v7a",
+ "assets/libs/armeabi",
+ "lib/armeabi-v7a",
+ "lib/armeabi",
+ 0
+ };
+ int ilib = 0;
+ struct SharedLibrary *shlibs = 0;
+ while (libdir[ilib]!=0) {
+ shlibs = apk_get_shared_libraries(global.apklib_handle,libdir[ilib]);
+ if (shlibs!=0)
+ break;
+ ilib ++;
+ }
+ if (shlibs==0) {
+ printf("Not a native APK.\n");
return 0;
}
+ struct JniLibrary *lib = malloc(sizeof(struct JniLibrary));
+ struct JniLibrary *head = lib;
+ lib->next = 0;
+
+ struct SharedLibrary *shlib = shlibs;
+ while (shlib!=0) {
+ lib->lib = android_dlopen(shlib->filename,RTLD_LAZY);
+ if (!(lib->lib)) {
+ printf("Missing library dependencies.\n");
+ return 0;
+ }
+ lib->method_table = jni_shlib_find_methods(shlib->filename);
+ lib->name = strdup(shlib->filename);
+ // unlink(shlib->filename);
+ shlib = shlib->next;
+ if (shlib!=0) {
+ lib->next = malloc(sizeof(struct JniLibrary));
+ lib = lib->next;
+ lib->next = 0;
+ }
+ }
+
+ global.libraries = head;
+
load_modules(".");
load_modules(MODULE_DIRECTORY_BASE);
@@ -424,14 +494,24 @@ int main(int argc, char **argv)
if (module == NULL) {
printf("Not supported yet, but found JNI methods:\n");
- tmp = global.method_table;
- while (*tmp) {
- printf(" %s\n", *tmp);
- tmp++;
+
+ struct JniLibrary *lib = global.libraries;
+ while (lib!=0) {
+ tmp = lib->method_table;
+ while (*tmp) {
+ printf(" %s\n", *tmp);
+ tmp++;
+ }
+ lib = lib->next;
}
goto finish;
}
+ SDL_Surface* screen = platform_init();
+ if (screen==0) {
+ return 0;
+ }
+
global.active_module = module;
printf("Using module: %s\n", module->filename);
install_overrides(module);
@@ -482,26 +562,26 @@ int main(int argc, char **argv)
}
}
module->update(module);
-#ifdef PANDORA
- GLES_SwapBuffers(gles);
-#elif defined(FREMANTLE)
- SDL_GLES_SwapBuffers();
-#else
- SDL_GL_SwapBuffers();
-#endif
+
+ platform_swap();
}
finish:
- tmp = global.method_table;
- while (*tmp) {
- free(*tmp++);
+
+ lib = global.libraries;
+ while (lib!=0) {
+ tmp = lib->method_table;
+ while (*tmp) {
+ free(*tmp++);
+ }
+ free(lib->method_table);
+ struct JniLibrary *next = lib->next;
+ free(lib);
+ lib = next;
}
- free(global.method_table);
+
apk_close(global.apklib_handle);
-#ifdef PANDORA
- GLES_Exit(gles);
-#endif
return 0;
}
View
13 apkenv.h
@@ -63,9 +63,18 @@ struct SupportModule {
};
typedef void *(*lookup_symbol_t)(const char *method);
+typedef void *(*lookup_lib_symbol_t)(const char *lib, const char *method);
typedef void (*foreach_file_t)(const char *prefix, apk_for_each_file_callback callback);
typedef int (*read_file_t)(const char *filename, char **buffer, size_t *size);
+struct JniLibrary {
+ struct JniLibrary *next;
+ char *name;
+ void *lib;
+ char **method_table;
+};
+
+
struct GlobalState {
const char *apkenv_executable;
const char *apkenv_headline;
@@ -79,13 +88,13 @@ struct GlobalState {
const char *apk_filename;
AndroidApk *apklib_handle;
- void *jni_library;
- char **method_table;
+ struct JniLibrary *libraries;
struct SupportModule *support_modules;
struct SupportModule *active_module;
lookup_symbol_t lookup_symbol;
+ lookup_lib_symbol_t lookup_lib_symbol;
foreach_file_t foreach_file;
read_file_t read_file;
};
View
25 apklib/apklib.c
@@ -49,27 +49,28 @@ apk_open(const char *filename)
return apk;
}
-char *
-apk_get_shared_library(AndroidApk *apk)
+struct SharedLibrary*
+apk_get_shared_libraries(AndroidApk *apk, const char* libdir)
{
assert(apk != NULL);
char filename[PATH_MAX], tmpname[PATH_MAX];
FILE *result = NULL;
char buf[64*1024];
int read;
+ struct SharedLibrary *libs = 0;
+ struct SharedLibrary *head = 0;
+ int libdirlen = strlen(libdir);
if (unzGoToFirstFile(apk->zip) != UNZ_OK) {
return NULL;
}
do {
if (unzGetCurrentFileInfo(apk->zip, NULL, filename, sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
- if (memcmp(filename, "lib/armeabi", 11) == 0) {
+ if (memcmp(filename, libdir, libdirlen) == 0) {
if (unzOpenCurrentFile(apk->zip) == UNZ_OK) {
-
-
#if !defined(PANDORA)
strcpy(filename, "/home/user/.apkenv-XXXXXX");
int fd = mkstemp(filename);
@@ -90,14 +91,22 @@ apk_get_shared_library(AndroidApk *apk)
#if defined(PANDORA)
sync();
#endif
- return strdup(filename);
+ if (libs==0) {
+ libs = malloc(sizeof(struct SharedLibrary));
+ head = libs;
+ libs->next = 0;
+ } else {
+ libs->next = malloc(sizeof(struct SharedLibrary));
+ libs->next->next = 0;
+ libs = libs->next;
+ }
+ libs->filename = strdup(filename);
}
- break;
}
}
} while (unzGoToNextFile(apk->zip) == UNZ_OK);
- return NULL;
+ return head;
}
enum ApkResult
View
7 apklib/apklib.h
@@ -42,11 +42,16 @@ enum ApkResult {
APK_ERROR,
};
+struct SharedLibrary {
+ struct SharedLibrary *next;
+ char* filename;
+};
+
typedef void (*apk_for_each_file_callback)(const char *filename, char *buffer, size_t size);
/* apklib.c */
AndroidApk *apk_open(const char *filename);
-char *apk_get_shared_library(AndroidApk *apk);
+struct SharedLibrary* apk_get_shared_libraries(AndroidApk *apk, const char *libdir);
enum ApkResult apk_read_file(AndroidApk *apk, const char *filename, char **buffer, size_t *size);
void apk_for_each_file(AndroidApk *apk, const char *prefix, apk_for_each_file_callback callback);
void apk_close(AndroidApk *apk);
View
4 jni/jnienv.c
@@ -1581,12 +1581,16 @@ JNIEnv_GetBooleanArrayRegion(JNIEnv* p0, jbooleanArray p1, jsize p2, jsize p3, j
}
+//#include <sys/mman.h>
+
+
void
JNIEnv_GetByteArrayRegion(JNIEnv *env, jbyteArray arrayobj, jsize start, jsize len, jbyte* buf)
{
JNIENV_DEBUG_PRINTF("JNIEnv_GetByteArrayRegion(%x, %d, %d, %x)\n", arrayobj, start, len, buf);
if (arrayobj != GLOBAL_J(env)) {
struct dummy_byte_array *array = arrayobj;
+ //mprotect(buf, len, PROT_WRITE);
memcpy(buf, array->data+start, len);
}
}
View
2 jni/jnienv.h
@@ -55,6 +55,8 @@ struct _jmethodID {
char *sig;
};
+#define _jfieldID _jmethodID
+
jint JNIEnv_GetVersion(JNIEnv *p0) SOFTFP;
jclass JNIEnv_DefineClass(JNIEnv *p0, const char *p1, jobject p2, const jbyte *p3, jsize p4) SOFTFP;
jclass JNIEnv_FindClass(JNIEnv *p0, const char *p1) SOFTFP;
View
44 jni/shlib.c
@@ -74,6 +74,8 @@ jni_shlib_find_methods(const char *filename)
tmp[i] = fgetc(fp);
remaining_bytes--;
if (tmp[i] == '\0') {
+ JNISHLIB_DEBUG_PRINTF("[SHLIB] %s\n",tmp);
+
if ((memcmp(tmp, "Java_", 5) == 0) ||
(memcmp(tmp, "JNI_", 4) == 0)) {
method_table[method_table_offset++] = strdup(tmp);
@@ -100,17 +102,45 @@ jni_shlib_find_methods(const char *filename)
void *
jni_shlib_resolve(struct GlobalState *global, const char *method)
{
- char **method_table = global->method_table;
+ struct JniLibrary *lib = global->libraries;
+ while (lib!=0) {
+ char **method_table = lib->method_table;
- while (*method_table) {
- if (strstr(*method_table, method) != NULL) {
- JNISHLIB_DEBUG_PRINTF("[shlib] Found symbol: %s\n",
- *method_table);
- return android_dlsym(global->jni_library, *method_table);
+ while (*method_table) {
+ JNISHLIB_DEBUG_PRINTF("[shlib] Available symbol: %s\n",*method_table);
+ if (strstr(*method_table, method) != NULL) {
+ JNISHLIB_DEBUG_PRINTF("[shlib] Found symbol: %s\n",
+ *method_table);
+ return android_dlsym(lib->lib, *method_table);
+ }
+ method_table++;
}
- method_table++;
+ lib = lib->next;
}
return NULL;
}
+
+void *
+jni_shlib_lib_resolve(struct GlobalState *global, const char* libname, const char *method)
+{
+ struct JniLibrary *lib = global->libraries;
+ while (lib!=0) {
+ char **method_table = lib->method_table;
+ if (strstr(lib->name,libname)!=0) {
+ while (*method_table) {
+ JNISHLIB_DEBUG_PRINTF("[shlib] Available symbol: %s in %s\n",*method_table,lib->name);
+ if (strstr(*method_table, method) != NULL) {
+ JNISHLIB_DEBUG_PRINTF("[shlib] Found symbol: %s in %s\n",
+ *method_table,lib->name);
+ return android_dlsym(lib->lib, *method_table);
+ }
+ method_table++;
+ }
+ }
+ lib = lib->next;
+ }
+
+ return NULL;
+}
View
3 jni/shlib.h
@@ -38,4 +38,7 @@ jni_shlib_find_methods(const char *filename);
void *
jni_shlib_resolve(struct GlobalState *global, const char *method);
+void *
+jni_shlib_lib_resolve(struct GlobalState *global, const char* lib, const char *method);
+
#endif /* JNI_SHLIB_H */

0 comments on commit ce2b496

Please sign in to comment.