diff options
Diffstat (limited to 'sal/android')
-rw-r--r-- | sal/android/android_native_app_glue.c | 2 | ||||
-rw-r--r-- | sal/android/lo-bootstrap.c | 299 | ||||
-rw-r--r-- | sal/android/makefile.mk | 59 |
3 files changed, 238 insertions, 122 deletions
diff --git a/sal/android/android_native_app_glue.c b/sal/android/android_native_app_glue.c index 8ff9f69d9946..440f3db7513e 100644 --- a/sal/android/android_native_app_glue.c +++ b/sal/android/android_native_app_glue.c @@ -414,7 +414,7 @@ static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) android_app_set_input((struct android_app*)activity->instance, NULL); } -void ANativeActivity_onCreate(ANativeActivity* activity, +__attribute__ ((visibility("default"))) void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize) { LOGI("Creating: %p\n", activity); activity->callbacks->onDestroy = onDestroy; diff --git a/sal/android/lo-bootstrap.c b/sal/android/lo-bootstrap.c index 6ac285d498d1..07c168701f69 100644 --- a/sal/android/lo-bootstrap.c +++ b/sal/android/lo-bootstrap.c @@ -48,8 +48,12 @@ #include "lo-bootstrap.h" +#pragma GCC diagnostic ignored "-Wdeclaration-after-statement" + #include "android_native_app_glue.c" +#pragma GCC diagnostic warning "-Wdeclaration-after-statement" + #undef LOGI #undef LOGW @@ -132,11 +136,64 @@ struct cdir_end { /* End of Zip data structures */ +static struct cdir_entry *cdir_start; +static uint16_t cdir_entries; + +struct lo_apk_dir { + char *folder_path; + struct cdir_entry *current_entry; + int remaining_entries; +}; + +static uint32_t cdir_entry_size (struct cdir_entry *entry) +{ + return sizeof(*entry) + + letoh16(entry->filename_size) + + letoh16(entry->extra_field_size) + + letoh16(entry->file_comment_size); +} + +static int +setup_cdir(void) +{ + struct cdir_end *dirend = (struct cdir_end *)((char *) apk_file + apk_file_size - sizeof(*dirend)); + uint32_t cdir_offset; + + while ((void *)dirend > apk_file && + letoh32(dirend->signature) != CDIR_END_SIG) + dirend = (struct cdir_end *)((char *)dirend - 1); + if (letoh32(dirend->signature) != CDIR_END_SIG) { + LOGE("setup_cdir: Could not find end of central directory record"); + return 0; + } + + cdir_offset = letoh32(dirend->cdir_offset); + + cdir_entries = letoh16(dirend->cdir_entries); + cdir_start = (struct cdir_entry *)((char *)apk_file + cdir_offset); + + return 1; +} + +static struct cdir_entry * +find_cdir_entry (struct cdir_entry *entry, int count, const char *name) +{ + size_t name_size = strlen(name); + while (count--) { + if (letoh16(entry->filename_size) == name_size && + !memcmp(entry->data, name, name_size)) + return entry; + entry = (struct cdir_entry *)((char *)entry + cdir_entry_size(entry)); + } + return NULL; +} + static void -engine_handle_cmd(struct android_app* app, +engine_handle_cmd(struct android_app* state, int32_t cmd) { - struct engine* engine = (struct engine*)app->userData; + (void) state; + switch (cmd) { case APP_CMD_SAVE_STATE: break; @@ -163,7 +220,7 @@ read_section(int fd, free(result); return NULL; } - if (read(fd, result, shdr->sh_size) < shdr->sh_size) { + if (read(fd, result, shdr->sh_size) < (int) shdr->sh_size) { close(fd); free(result); return NULL; @@ -183,6 +240,7 @@ free_ptrarray(void **pa) free(pa); } +__attribute__ ((visibility("default"))) jobjectArray Java_org_libreoffice_android_Bootstrap_dlneeds(JNIEnv* env, jobject clazz, @@ -190,10 +248,12 @@ Java_org_libreoffice_android_Bootstrap_dlneeds(JNIEnv* env, { char **needed; int n_needed; - const jbyte *libName; + const char *libName; jclass String; jobjectArray result; + (void) clazz; + libName = (*env)->GetStringUTFChars(env, library, NULL); needed = lo_dlneeds(libName); @@ -231,41 +291,55 @@ Java_org_libreoffice_android_Bootstrap_dlneeds(JNIEnv* env, return result; } +__attribute__ ((visibility("default"))) jint Java_org_libreoffice_android_Bootstrap_dlopen(JNIEnv* env, jobject clazz, jstring library) { - const jbyte *libName = (*env)->GetStringUTFChars(env, library, NULL); - void *p = lo_dlopen (libName); + const char *libName; + void *p; + + (void) clazz; + libName = (*env)->GetStringUTFChars(env, library, NULL); + p = lo_dlopen (libName); (*env)->ReleaseStringUTFChars(env, library, libName); return (jint) p; } +__attribute__ ((visibility("default"))) jint Java_org_libreoffice_android_Bootstrap_dlsym(JNIEnv* env, jobject clazz, jint handle, jstring symbol) { - const jbyte *symName = (*env)->GetStringUTFChars(env, symbol, NULL); - void *p = lo_dlsym ((void *) handle, symName); + const char *symName; + void *p; + + (void) clazz; + symName = (*env)->GetStringUTFChars(env, symbol, NULL); + p = lo_dlsym ((void *) handle, symName); (*env)->ReleaseStringUTFChars(env, symbol, symName); return (jint) p; } +__attribute__ ((visibility("default"))) jint Java_org_libreoffice_android_Bootstrap_dlcall(JNIEnv* env, jobject clazz, jint function, jobject argument) { - jclass StringArray = (*env)->FindClass(env, "[Ljava/lang/String;"); + jclass StringArray; + + (void) clazz; + StringArray = (*env)->FindClass(env, "[Ljava/lang/String;"); if (StringArray == NULL) { LOGE("Could not find String[] class"); return 0; @@ -297,6 +371,7 @@ Java_org_libreoffice_android_Bootstrap_dlcall(JNIEnv* env, // String apkFile, // String[] ld_library_path); +__attribute__ ((visibility("default"))) jboolean Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2Ljava_lang_String_2_3Ljava_lang_String_2 (JNIEnv* env, @@ -307,10 +382,12 @@ Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2Ljava_lang_Stri { struct stat st; int i, n, fd; - const jbyte *dataDirPath; - const jbyte *apkFilePath; + const char *dataDirPath; + const char *apkFilePath; char *lib_dir; + (void) clazz; + n = (*env)->GetArrayLength(env, ld_library_path); library_locations = malloc((n+2) * sizeof(char *)); @@ -326,7 +403,7 @@ Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2Ljava_lang_Stri library_locations[0] = lib_dir; for (i = 0; i < n; i++) { - const jbyte *s = (*env)->GetStringUTFChars(env, (*env)->GetObjectArrayElement(env, ld_library_path, i), NULL); + const char *s = (*env)->GetStringUTFChars(env, (*env)->GetObjectArrayElement(env, ld_library_path, i), NULL); library_locations[i+1] = strdup(s); (*env)->ReleaseStringUTFChars(env, (*env)->GetObjectArrayElement(env, ld_library_path, i), s); } @@ -362,6 +439,9 @@ Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2Ljava_lang_Stri (*env)->ReleaseStringUTFChars(env, apkFile, apkFilePath); + if (!setup_cdir()) + return JNI_FALSE; + return JNI_TRUE; } @@ -369,6 +449,7 @@ Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2Ljava_lang_Stri // Object lo_main_argument, // int lo_main_delay); +__attribute__ ((visibility("default"))) jboolean Java_org_libreoffice_android_Bootstrap_setup__ILjava_lang_Object_2I(JNIEnv* env, jobject clazz, @@ -379,6 +460,8 @@ Java_org_libreoffice_android_Bootstrap_setup__ILjava_lang_Object_2I(JNIEnv* env, jclass StringArray; int i; + (void) clazz; + lo_main = lo_main_ptr; StringArray = (*env)->FindClass(env, "[Ljava/lang/String;"); @@ -396,7 +479,7 @@ Java_org_libreoffice_android_Bootstrap_setup__ILjava_lang_Object_2I(JNIEnv* env, lo_main_argv = malloc(sizeof(char *) * (lo_main_argc+1)); for (i = 0; i < lo_main_argc; i++) { - const jbyte *s = (*env)->GetStringUTFChars(env, (*env)->GetObjectArrayElement(env, lo_main_argument, i), NULL); + const char *s = (*env)->GetStringUTFChars(env, (*env)->GetObjectArrayElement(env, lo_main_argument, i), NULL); lo_main_argv[i] = strdup(s); (*env)->ReleaseStringUTFChars(env, (*env)->GetObjectArrayElement(env, lo_main_argument, i), s); /* LOGI("argv[%d] = %s", i, lo_main_argv[i]); */ @@ -410,22 +493,31 @@ Java_org_libreoffice_android_Bootstrap_setup__ILjava_lang_Object_2I(JNIEnv* env, // public static native int getpid(); +__attribute__ ((visibility("default"))) jint Java_org_libreoffice_android_Bootstrap_getpid(JNIEnv* env, jobject clazz) { + (void) env; + (void) clazz; + return getpid(); } // public static native void system(String cmdline); -jint +__attribute__ ((visibility("default"))) +void Java_org_libreoffice_android_Bootstrap_system(JNIEnv* env, jobject clazz, jstring cmdline) { - const jbyte *s = (*env)->GetStringUTFChars(env, cmdline, NULL); + const char *s; + + (void) clazz; + + s = (*env)->GetStringUTFChars(env, cmdline, NULL); LOGI("system(%s)", s); @@ -436,12 +528,17 @@ Java_org_libreoffice_android_Bootstrap_system(JNIEnv* env, // public static native void putenv(String string); +__attribute__ ((visibility("default"))) void Java_org_libreoffice_android_Bootstrap_putenv(JNIEnv* env, jobject clazz, jstring string) { - const jbyte *s = (*env)->GetStringUTFChars(env, string, NULL); + const char *s; + + (void) clazz; + + s = (*env)->GetStringUTFChars(env, string, NULL); LOGI("putenv(%s)", s); @@ -450,6 +547,7 @@ Java_org_libreoffice_android_Bootstrap_putenv(JNIEnv* env, (*env)->ReleaseStringUTFChars(env, string, s); } +__attribute__ ((visibility("default"))) char ** lo_dlneeds(const char *library) { @@ -470,7 +568,7 @@ lo_dlneeds(const char *library) return NULL; } - if (read(fd, &hdr, sizeof(hdr)) < sizeof(hdr)) { + if (read(fd, &hdr, sizeof(hdr)) < (int) sizeof(hdr)) { LOGE("lo_dlneeds: Could not read ELF header of %s", library); close(fd); return NULL; @@ -483,7 +581,7 @@ lo_dlneeds(const char *library) close(fd); return NULL; } - if (read(fd, &shdr, sizeof(shdr)) < sizeof(shdr)) { + if (read(fd, &shdr, sizeof(shdr)) < (int) sizeof(shdr)) { LOGE("lo_dlneeds: Could not read section header of %s", library); close(fd); return NULL; @@ -501,7 +599,7 @@ lo_dlneeds(const char *library) return NULL; } for (i = 0; i < hdr.e_shnum; i++) { - if (read(fd, &shdr, sizeof(shdr)) < sizeof(shdr)) { + if (read(fd, &shdr, sizeof(shdr)) < (int) sizeof(shdr)) { LOGE("lo_dlneeds: Could not read section header of %s", library); close(fd); return NULL; @@ -531,14 +629,13 @@ lo_dlneeds(const char *library) return NULL; } for (i = 0; i < hdr.e_shnum; i++) { - if (read(fd, &shdr, sizeof(shdr)) < sizeof(shdr)) { + if (read(fd, &shdr, sizeof(shdr)) < (int) sizeof(shdr)) { LOGE("lo_dlneeds: Could not read section header of %s", library); close(fd); return NULL; } if (shdr.sh_type == SHT_DYNAMIC) { - int dynoff; - int *libnames; + size_t dynoff; /* Count number of DT_NEEDED entries */ n_needed = 0; @@ -548,7 +645,7 @@ lo_dlneeds(const char *library) return NULL; } for (dynoff = 0; dynoff < shdr.sh_size; dynoff += sizeof(dyn)) { - if (read(fd, &dyn, sizeof(dyn)) < sizeof(dyn)) { + if (read(fd, &dyn, sizeof(dyn)) < (int) sizeof(dyn)) { LOGE("lo_dlneeds: Could not read .dynamic entry of %s", library); close(fd); return NULL; @@ -569,7 +666,7 @@ lo_dlneeds(const char *library) return NULL; } for (dynoff = 0; dynoff < shdr.sh_size; dynoff += sizeof(dyn)) { - if (read(fd, &dyn, sizeof(dyn)) < sizeof(dyn)) { + if (read(fd, &dyn, sizeof(dyn)) < (int) sizeof(dyn)) { LOGE("lo_dlneeds: Could not read .dynamic entry in %s", library); close(fd); free(result); @@ -595,6 +692,7 @@ lo_dlneeds(const char *library) return NULL; } +__attribute__ ((visibility("default"))) void * lo_dlopen(const char *library) { @@ -698,6 +796,7 @@ lo_dlopen(const char *library) return p; } +__attribute__ ((visibility("default"))) void * lo_dlsym(void *handle, const char *symbol) @@ -709,6 +808,7 @@ lo_dlsym(void *handle, return p; } +__attribute__ ((visibility("default"))) int lo_dladdr(void *addr, Dl_info *info) @@ -736,7 +836,7 @@ lo_dladdr(void *addr, void *lo, *hi; char file[sizeof(line)]; file[0] = '\0'; - if (sscanf(line, "%x-%x %*s %*x %*x:%*x %*d %[^\n]", &lo, &hi, file) == 3) { + if (sscanf(line, "%x-%x %*s %*x %*x:%*x %*d %[^\n]", (unsigned *) &lo, (unsigned *) &hi, file) == 3) { /* LOGI("got %p-%p: %s", lo, hi, file); */ if (addr >= lo && addr < hi) { if (info->dli_fbase != lo) { @@ -762,51 +862,15 @@ lo_dladdr(void *addr, return result; } -static uint32_t cdir_entry_size (struct cdir_entry *entry) -{ - return sizeof(*entry) + - letoh16(entry->filename_size) + - letoh16(entry->extra_field_size) + - letoh16(entry->file_comment_size); -} - -static struct cdir_entry * -find_cdir_entry (struct cdir_entry *entry, int count, const char *name) -{ - size_t name_size = strlen(name); - while (count--) { - if (letoh16(entry->filename_size) == name_size && - !memcmp(entry->data, name, name_size)) - return entry; - entry = (struct cdir_entry *)((char *)entry + cdir_entry_size(entry)); - } - return NULL; -} - +__attribute__ ((visibility("default"))) void * lo_apkentry(const char *filename, size_t *size) { - struct cdir_end *dirend = (struct cdir_end *)((char *) apk_file + apk_file_size - sizeof(*dirend)); - uint32_t cdir_offset; - uint16_t cdir_entries; - struct cdir_entry *cdir_start; struct cdir_entry *entry; struct local_file_header *file; void *data; - while ((void *)dirend > apk_file && - letoh32(dirend->signature) != CDIR_END_SIG) - dirend = (struct cdir_end *)((char *)dirend - 1); - if (letoh32(dirend->signature) != CDIR_END_SIG) { - LOGE("lo_apkentry: Could not find end of central directory record"); - return; - } - - cdir_offset = letoh32(dirend->cdir_offset); - cdir_entries = letoh16(dirend->cdir_entries); - cdir_start = (struct cdir_entry *)((char *)apk_file + cdir_offset); - if (*filename == '/') filename++; @@ -831,6 +895,111 @@ lo_apkentry(const char *filename, return data; } +static lo_apk_dir * +new_dir(const char *folder_path, + struct cdir_entry *start_entry, + int remaining_entries) +{ + lo_apk_dir *result; + + result = malloc(sizeof(*result)); + if (result == NULL) + return NULL; + + result->folder_path = strdup(folder_path); + result->current_entry = start_entry; + result->remaining_entries = remaining_entries; + + return result; +} + + +__attribute__ ((visibility("default"))) +lo_apk_dir * +lo_apk_opendir(const char *dirname) +{ + int count = cdir_entries; + struct cdir_entry *entry = cdir_start; + size_t name_size = strlen(dirname); + + if (*dirname == '/') { + dirname++; + if (!dirname[0]) + return new_dir("", cdir_start, count); + } + + while (count--) { + if (letoh16(entry->filename_size) >= name_size && + !memcmp(entry->data, dirname, name_size) && + entry->data[name_size] == '/') + break; + entry = (struct cdir_entry *)((char *)entry + cdir_entry_size(entry)); + } + if (count >= 0) + return new_dir(dirname, entry, count+1); + + return NULL; +} + +static int +path_component_length(const char *path) +{ + const char *slash = strchr(path, '/'); + + if (slash) + return slash - path; + + return strlen(path); +} + +__attribute__ ((visibility("default"))) +struct dirent * +lo_apk_readdir(lo_apk_dir *dirp) +{ + static struct dirent result; + size_t folder_size = strlen(dirp->folder_path); + + while (dirp->remaining_entries > 0) { + const char *folder_end = dirp->current_entry->data + folder_size; + int entry_len; + + if (letoh16(dirp->current_entry->filename_size) > folder_size && + !memcmp(dirp->current_entry->data, dirp->folder_path, folder_size) && + *folder_end == '/' && + (entry_len = path_component_length(folder_end + 1)) < 256) { + + /* Fake an unique inode number; might be used? */ + result.d_ino = cdir_entries - dirp->remaining_entries + 2; + + result.d_off = 0; + result.d_reclen = 0; + + if (folder_end[entry_len] == '/') + result.d_type = DT_DIR; + else + result.d_type = DT_REG; + + memcpy(result.d_name, folder_end + 1, entry_len); + result.d_name[entry_len] = '\0'; + return &result; + } + dirp->remaining_entries--; + } + + return NULL; +} + +__attribute__ ((visibility("default"))) +int +lo_apk_closedir(lo_apk_dir *dirp) +{ + free(dirp->folder_path); + free(dirp); + + return 0; +} + +__attribute__ ((visibility("default"))) int lo_dlcall_argc_argv(void *function, int argc, @@ -1015,19 +1184,25 @@ patch_libgnustl_shared(void) &replacement_method_before_arm); } +__attribute__ ((visibility("default"))) void Java_org_libreoffice_android_Bootstrap_patch_libgnustl_shared(JNIEnv* env, jobject clazz) { + (void) env; + (void) clazz; + patch_libgnustl_shared(); } +__attribute__ ((visibility("default"))) JavaVM * lo_get_javavm(void) { return app->activity->vm; } +__attribute__ ((visibility("default"))) void android_main(struct android_app* state) { diff --git a/sal/android/makefile.mk b/sal/android/makefile.mk deleted file mode 100644 index c5e630bed4af..000000000000 --- a/sal/android/makefile.mk +++ /dev/null @@ -1,59 +0,0 @@ -# Version: MPL 1.1 / GPLv3+ / LGPLv3+ -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License or as specified alternatively below. You may obtain a copy of -# the License at http:#www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# Major Contributor(s): -# Copyright (C) 2011 Tor Lillqvist <tml@iki.fi> (initial developer) -# Copyright (C) 2011 SUSE Linux http://suse.com (initial developer's employer) -# -# Zip parsing code lifted from Mozilla's other-licenses/android/APKOpen.cpp, -# by Michael Wu <mwu@mozilla.com>. -# -# All Rights Reserved. -# -# For minor contributions see the git repository. -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 3 or later (the "GPLv3+"), or -# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), -# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable -# instead of those above. - -PRJ = .. -PRJNAME = sal -TARGET = lo-bootstrap - -# Too many warnings from android_native_app_glue.[ch] -EXTERNAL_WARNINGS_NOT_ERRORS = TRUE - -.INCLUDE : settings.mk - -.IF "$(OS)" != "ANDROID" -ALL: -# do nothing -.ENDIF - -SHL1TARGET = $(TARGET) - -SHL1OBJS = \ - $(SLO)$/lo-bootstrap.obj - -# We don't want to link liblo-bootstrap.so against -# libgnustl_shared.so. The Android dynamic linker won't find it -# anyway. One very point of liblo-bootstrap is its wrapper for -# dlopen() that searches also in the app's lib folder for needed -# shared libraries. So just re-define STDSHLCUIMT. - -STDSHLCUIMT := -llog -landroid - -# Also don't pointless - -.INCLUDE : target.mk |