summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--android/Bootstrap/src/org/libreoffice/android/LibreOfficeKit.java135
-rw-r--r--include/osl/detail/android-bootstrap.h7
-rw-r--r--sal/Library_lo-bootstrap.mk1
-rw-r--r--sal/android/libreofficekit-jni.c130
-rw-r--r--sal/android/lo-bootstrap.c11
5 files changed, 277 insertions, 7 deletions
diff --git a/android/Bootstrap/src/org/libreoffice/android/LibreOfficeKit.java b/android/Bootstrap/src/org/libreoffice/android/LibreOfficeKit.java
new file mode 100644
index 000000000000..82b889e2548f
--- /dev/null
+++ b/android/Bootstrap/src/org/libreoffice/android/LibreOfficeKit.java
@@ -0,0 +1,135 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+package org.libreoffice.android;
+
+import android.app.Activity;
+import android.content.pm.ApplicationInfo;
+import android.util.Log;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+// final because subclassing would be meaningless.
+public final class LibreOfficeKit
+{
+ // private constructor because instantiating would be meaningless
+ private LibreOfficeKit()
+ {
+ }
+
+ private static String TAG = "lo-bootstrap";
+
+ // Native methods in this class are all implemented in
+ // sal/android/lo-bootstrap.c as the lo-bootstrap library is loaded with
+ // System.loadLibrary() and Android's JNI works only to such libraries, it
+ // seems.
+
+ private static native boolean init(String dataDir,
+ String cacheDir,
+ String apkFile);
+
+ // Extracts files in the .apk that need to be extraced into the app's tree
+ static native void extract_files();
+
+/*
+ // Wrapper for getpid()
+ public static native int getpid();
+
+ // Wrapper for system()
+ public static native void system(String cmdline);
+*/
+ // Wrapper for putenv()
+ public static native void putenv(String string);
+/*
+ // A wrapper for InitVCL() in libvcl (svmain.cxx), called indirectly
+ // through the lo-bootstrap library
+ public static native void initVCL();
+
+ // A wrapper for osl_setCommandArgs(). Before calling
+ // osl_setCommandArgs(), argv[0] is prefixed with the parent directory of
+ // where the lo-bootstrap library is.
+ public static native void setCommandArgs(String[] argv);
+*/
+ // A method that starts a thread to redirect stdout and stderr writes to
+ // the Android logging mechanism, or stops the redirection.
+ public static native boolean redirect_stdio(boolean state);
+/*
+ // The DIB returned by css.awt.XBitmap.getDIB is in BGR_888 form, at least
+ // for Writer documents. We need it in Android's Bitmap.Config.ARGB_888
+ // format, which actually is RGBA_888, whee... At least in Android 4.0.3,
+ // at least on my device. No idea if it is always like that or not, the
+ // documentation sucks.
+ public static native void twiddle_BGR_to_RGBA(byte[] source, int offset, int width, int height, ByteBuffer destination);
+
+ public static native void force_full_alpha_array(byte[] array, int offset, int length);
+
+ public static native void force_full_alpha_bb(ByteBuffer buffer, int offset, int length);
+
+ public static native long new_byte_buffer_wrapper(ByteBuffer bbuffer);
+
+ public static native void delete_byte_buffer_wrapper(long bbw);
+*/
+
+ static boolean init_done = false;
+
+ // This init() method should be called from the upper Java level of
+ // LO-based apps.
+ public static synchronized void init(Activity activity)
+ {
+ if (init_done)
+ return;
+
+ String dataDir = null;
+
+ ApplicationInfo ai = activity.getApplicationInfo();
+ dataDir = ai.dataDir;
+ Log.i(TAG, String.format("dataDir=%s\n", dataDir));
+
+ redirect_stdio(true);
+
+ if (!init(dataDir,
+ activity.getApplication().getCacheDir().getAbsolutePath(),
+ activity.getApplication().getPackageResourcePath()))
+ return;
+
+ // Extract files from the .apk that can't be used mmapped directly from it
+ extract_files();
+
+ // If we notice that a fonts.conf file was extracted, automatically
+ // set the FONTCONFIG_FILE env var.
+ InputStream i;
+ try {
+ i = activity.getAssets().open("unpack/etc/fonts/fonts.conf");
+ }
+ catch (java.io.IOException e) {
+ i = null;
+ }
+ putenv("OOO_DISABLE_RECOVERY=1");
+ if (i != null)
+ putenv("FONTCONFIG_FILE=" + dataDir + "/etc/fonts/fonts.conf");
+
+ // TMPDIR is used by osl_getTempDirURL()
+ putenv("TMPDIR=" + activity.getCacheDir().getAbsolutePath());
+
+ init_done = true;
+ }
+
+ // Now with static loading we always have all native code in one native
+ // library which we always call liblo-native-code.so, regardless of the
+ // app. The library has already been unpacked into /data/data/<app
+ // name>/lib at installation time by the package manager.
+ static {
+ System.loadLibrary("lo-native-code");
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/osl/detail/android-bootstrap.h b/include/osl/detail/android-bootstrap.h
index 002027a5d8a0..b18531bb65e2 100644
--- a/include/osl/detail/android-bootstrap.h
+++ b/include/osl/detail/android-bootstrap.h
@@ -38,6 +38,13 @@ JavaVM *lo_get_javavm(void);
const char *lo_get_app_data_dir(void);
+#define UNPACK_TREE "/assets/unpack"
+#define UNPACK_TREE_GZ "/assets/gz.unpack"
+
+int setup_cdir(void);
+int setup_assets_tree(void);
+void extract_files(const char *root, const char *prefix, int gzipped);
+
#ifdef __cplusplus
}
#endif
diff --git a/sal/Library_lo-bootstrap.mk b/sal/Library_lo-bootstrap.mk
index 14380915162f..3dc4bf9dfeaa 100644
--- a/sal/Library_lo-bootstrap.mk
+++ b/sal/Library_lo-bootstrap.mk
@@ -19,6 +19,7 @@ $(eval $(call gb_Library_add_libs,lo-bootstrap,\
))
$(eval $(call gb_Library_add_cobjects,lo-bootstrap,\
+ sal/android/libreofficekit-jni \
sal/android/lo-bootstrap \
))
diff --git a/sal/android/libreofficekit-jni.c b/sal/android/libreofficekit-jni.c
new file mode 100644
index 000000000000..3563d5b7891e
--- /dev/null
+++ b/sal/android/libreofficekit-jni.c
@@ -0,0 +1,130 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include <jni.h>
+
+#include <android/log.h>
+
+#include <osl/detail/android-bootstrap.h>
+
+//#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "LibreOfficeKit", __VA_ARGS__))
+#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "LibreOfficeKit", __VA_ARGS__))
+
+/* These are valid / used in all apps. */
+extern const char *data_dir;
+extern const char *cache_dir;
+extern void *apk_file;
+extern int apk_file_size;
+
+extern void Java_org_libreoffice_android_Bootstrap_putenv(JNIEnv* env, jobject clazz, jstring string);
+extern jboolean Java_org_libreoffice_android_Bootstrap_redirect_1stdio(JNIEnv* env, jobject clazz, jboolean state);
+extern void Java_org_libreoffice_android_Bootstrap_extract_1files(JNIEnv* env, jobject clazz);
+
+/// Call the same method from Bootstrap.
+__attribute__ ((visibility("default")))
+void
+Java_org_libreoffice_android_LibreOfficeKit_putenv(JNIEnv* env,
+ jobject clazz,
+ jstring string)
+{
+ Java_org_libreoffice_android_Bootstrap_putenv(env, clazz, string);
+}
+
+/// Call the same method from Bootstrap.
+__attribute__ ((visibility("default")))
+jboolean
+Java_org_libreoffice_android_LibreOfficeKit_redirect_1stdio(JNIEnv* env,
+ jobject clazz,
+ jboolean state)
+{
+ return Java_org_libreoffice_android_Bootstrap_redirect_1stdio(env, clazz, state);
+}
+
+/// Call the same method from Bootstrap.
+__attribute__ ((visibility("default")))
+void
+Java_org_libreoffice_android_LibreOfficeKit_extract_1files(JNIEnv* env,
+ jobject clazz)
+{
+ Java_org_libreoffice_android_Bootstrap_extract_1files(env, clazz);
+}
+
+/// Initialize the LibreOfficeKit.
+__attribute__ ((visibility("default")))
+jboolean
+Java_org_libreoffice_android_LibreOfficeKit_init__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2
+ (JNIEnv* env,
+ jobject clazz,
+ jstring dataDir,
+ jstring cacheDir,
+ jstring apkFile)
+{
+ struct stat st;
+ int fd;
+ const char *dataDirPath;
+ const char *cacheDirPath;
+ const char *apkFilePath;
+
+ (void) clazz;
+
+ dataDirPath = (*env)->GetStringUTFChars(env, dataDir, NULL);
+ data_dir = strdup(dataDirPath);
+ (*env)->ReleaseStringUTFChars(env, dataDir, dataDirPath);
+
+ cacheDirPath = (*env)->GetStringUTFChars(env, cacheDir, NULL);
+ cache_dir = strdup(cacheDirPath);
+ (*env)->ReleaseStringUTFChars(env, cacheDir, cacheDirPath);
+
+ apkFilePath = (*env)->GetStringUTFChars(env, apkFile, NULL);
+
+ fd = open(apkFilePath, O_RDONLY);
+ if (fd == -1) {
+ LOGE("Could not open %s", apkFilePath);
+ (*env)->ReleaseStringUTFChars(env, apkFile, apkFilePath);
+ return JNI_FALSE;
+ }
+ if (fstat(fd, &st) == -1) {
+ LOGE("Could not fstat %s", apkFilePath);
+ close(fd);
+ (*env)->ReleaseStringUTFChars(env, apkFile, apkFilePath);
+ return JNI_FALSE;
+ }
+ apk_file = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ close(fd);
+
+ if (apk_file == MAP_FAILED) {
+ LOGE("Could not mmap %s", apkFilePath);
+ (*env)->ReleaseStringUTFChars(env, apkFile, apkFilePath);
+ return JNI_FALSE;
+ }
+ apk_file_size = st.st_size;
+
+ (*env)->ReleaseStringUTFChars(env, apkFile, apkFilePath);
+
+ if (!setup_cdir())
+ return JNI_FALSE;
+
+ if (!setup_assets_tree())
+ return JNI_FALSE;
+
+ return JNI_TRUE;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/android/lo-bootstrap.c b/sal/android/lo-bootstrap.c
index 49f9b3aa627c..973c1b25116a 100644
--- a/sal/android/lo-bootstrap.c
+++ b/sal/android/lo-bootstrap.c
@@ -28,7 +28,7 @@
#include "uthash.h"
-#include "osl/detail/android-bootstrap.h"
+#include <osl/detail/android-bootstrap.h>
#undef LOGI
@@ -142,7 +142,7 @@ cdir_entry_size(struct cdir_entry *entry)
letoh16(entry->file_comment_size);
}
-static int
+int
setup_cdir(void)
{
struct cdir_end *dirend = (struct cdir_end *)((char *) apk_file + apk_file_size - sizeof(*dirend));
@@ -221,7 +221,7 @@ handle_one_asset(struct cdir_entry *entry)
}
}
-static int
+int
setup_assets_tree(void)
{
int count = cdir_entries;
@@ -629,9 +629,6 @@ lo_apk_lstat(const char *path,
return -1;
}
-#define UNPACK_TREE "/assets/unpack"
-#define UNPACK_TREE_GZ "/assets/gz.unpack"
-
static int
mkdir_p(const char *dirname)
{
@@ -718,7 +715,7 @@ extract_gzipped(const char *filename,
return total;
}
-static void
+void
extract_files(const char *root,
const char *prefix,
int gzipped)