summaryrefslogtreecommitdiff
path: root/sal
diff options
context:
space:
mode:
authorChristian Lohmaier <lohmaier+LibreOffice@googlemail.com>2015-10-11 01:52:39 +0200
committerTomaž Vajngerl <tomaz.vajngerl@collabora.com>2015-10-15 10:28:28 +0200
commit7f87188e9a35cb8ab06a94ede5504c5d49993766 (patch)
tree9ab65ed9995eb379c94cb23a518ec70cb330e13a /sal
parent9b35f433a63e6c6f45705e252fe7ae622b5e2742 (diff)
move extracting assets to Java & use AssetManager to access assets
using AssetsManager in both java as well as native parts allows to handle files both with and without compression transparently Change-Id: If02f1159c498be7ea965fd9c217410722f2dca1f (cherry picked from commit 143fb0a4b5d4ab69d4928299d8112ab95d99870a)
Diffstat (limited to 'sal')
-rw-r--r--sal/android/libreofficekit-jni.c19
-rw-r--r--sal/android/lo-bootstrap.c182
-rw-r--r--sal/osl/unx/file.cxx29
3 files changed, 35 insertions, 195 deletions
diff --git a/sal/android/libreofficekit-jni.c b/sal/android/libreofficekit-jni.c
index 41fa97e8273d..c5f53c92bcd5 100644
--- a/sal/android/libreofficekit-jni.c
+++ b/sal/android/libreofficekit-jni.c
@@ -21,6 +21,8 @@
#include <jni.h>
#include <android/log.h>
+#include <android/asset_manager.h>
+#include <android/asset_manager_jni.h>
#include <osl/detail/android-bootstrap.h>
@@ -34,6 +36,7 @@ extern const char* data_dir;
extern const char* cache_dir;
extern void* apk_file;
extern int apk_file_size;
+AAssetManager* native_asset_manager;
extern void Java_org_libreoffice_android_Bootstrap_putenv(JNIEnv* env, jobject clazz, jstring string);
extern void Java_org_libreoffice_android_Bootstrap_redirect_1stdio(JNIEnv* env, jobject clazz, jboolean state);
@@ -63,7 +66,7 @@ void Java_org_libreoffice_kit_LibreOfficeKit_redirectStdio
__attribute__ ((visibility("default")))
jboolean Java_org_libreoffice_kit_LibreOfficeKit_initializeNative
(JNIEnv* env, jobject clazz,
- jstring dataDir, jstring cacheDir, jstring apkFile)
+ jstring dataDir, jstring cacheDir, jstring apkFile, jobject assetManager)
{
struct stat st;
int fd;
@@ -76,6 +79,8 @@ jboolean Java_org_libreoffice_kit_LibreOfficeKit_initializeNative
(void) clazz;
+ native_asset_manager = AAssetManager_fromJava(env, assetManager);
+
dataDirPath = (*env)->GetStringUTFChars(env, dataDir, NULL);
data_dir = strdup(dataDirPath);
(*env)->ReleaseStringUTFChars(env, dataDir, dataDirPath);
@@ -122,10 +127,6 @@ jboolean Java_org_libreoffice_kit_LibreOfficeKit_initializeNative
return JNI_FALSE;
}
- // Extract files from the .apk that can't be used mmapped directly from it
- extract_files(UNPACK_TREE, UNPACK_TREE, 0);
- extract_files(UNPACK_TREE_GZ, UNPACK_TREE_GZ, 1);
-
// LibreOfficeKit expects a path to the program/ directory
free(full_program_dir);
data_dir_len = strlen(data_dir);
@@ -160,4 +161,12 @@ jobject Java_org_libreoffice_kit_LibreOfficeKit_getLibreOfficeKitHandle
return (*env)->NewDirectByteBuffer(env, (void*) aOffice, sizeof(LibreOfficeKit));
}
+__attribute__ ((visibility("default")))
+AAssetManager *
+lo_get_native_assetmgr(void)
+{
+ return native_asset_manager;
+}
+
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/android/lo-bootstrap.c b/sal/android/lo-bootstrap.c
index 5c47b8f6bd2f..7a2da48eb93b 100644
--- a/sal/android/lo-bootstrap.c
+++ b/sal/android/lo-bootstrap.c
@@ -311,10 +311,6 @@ Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2Ljava_lang_Stri
if (!setup_assets_tree())
return JNI_FALSE;
- // Extract files from the .apk that can't be used mmapped directly from it
- extract_files(UNPACK_TREE, UNPACK_TREE, 0);
- extract_files(UNPACK_TREE_GZ, UNPACK_TREE_GZ, 1);
-
return JNI_TRUE;
}
@@ -635,184 +631,6 @@ lo_apk_lstat(const char *path,
return -1;
}
-static int
-mkdir_p(const char *dirname)
-{
- char *p = malloc(strlen(dirname) + 1);
- const char *q = dirname + 1;
- const char *slash;
-
- do {
- slash = strchr(q, '/');
- if (slash == NULL)
- slash = q + strlen(q);
- memcpy(p, dirname, slash-dirname);
- p[slash-dirname] = '\0';
- if (mkdir(p, 0700) == -1 && errno != EEXIST) {
- LOGE("mkdir_p: Could not create %s: %s", p, strerror(errno));
- free(p);
- return 0;
- }
- if (*slash)
- q = slash + 1;
- } while (*slash);
-
- free(p);
- return 1;
-}
-
-static int
-extract_gzipped(const char *filename,
- const char *apkentry,
- int size,
- FILE *f)
-{
- gzFile gzfd;
- int gzerrno;
- int nbytes;
- char buf[5000];
- int total = 0;
- char *tmpname;
- FILE *tmp;
-
- tmpname = malloc(strlen(cache_dir) + strlen("/tmp.gz") + 1);
- strcpy(tmpname, cache_dir);
- strcat(tmpname, "/tmp.gz");
-
- tmp = fopen(tmpname, "w+");
- unlink(tmpname);
-
- if (tmp == NULL) {
- LOGE("extract_gzipped: could not create %s: %s", tmpname, strerror(errno));
- free(tmpname);
- return 0;
- }
-
- if (fwrite(apkentry, size, 1, tmp) != 1) {
- LOGE("extract_gzipped: could not write gzipped entry to %s: %s", tmpname, strerror(errno));
- fclose(tmp);
- free(tmpname);
- return 0;
- }
-
- free(tmpname);
- rewind(tmp);
-
- gzfd = gzdopen(fileno(tmp), "rb");
- if (gzfd == NULL) {
- LOGE("extract_gzipped: gzdopen failed");
- fclose(tmp);
- return 0;
- }
-
- while ((nbytes = gzread(gzfd, buf, sizeof(buf))) > 0) {
- fwrite(buf, nbytes, 1, f);
- total += nbytes;
- }
- if (nbytes == -1) {
- LOGE("extract_gzipped: Could not gzread from %s: %s", filename, gzerror(gzfd, &gzerrno));
- return total;
- }
- if (gzclose(gzfd) == -1) {
- LOGE("extract_gzipped: gzclose failed");
- return total;
- }
-
- return total;
-}
-
-void
-extract_files(const char *root,
- const char *prefix,
- int gzipped)
-{
- lo_apk_dir *tree = lo_apk_opendir(prefix);
- struct dirent *dent;
-
- if (tree == NULL)
- return;
-
- while ((dent = lo_apk_readdir(tree)) != NULL) {
- if (strcmp(dent->d_name, ".") == 0 ||
- strcmp(dent->d_name, "..") == 0)
- continue;
-
- if (dent->d_type == DT_DIR) {
- char *subdir = malloc(strlen(prefix) + 1 + strlen(dent->d_name) + 1);
- strcpy(subdir, prefix);
- strcat(subdir, "/");
- strcat(subdir, dent->d_name);
- extract_files(root, subdir, gzipped);
- free(subdir);
- } else {
- char *filename;
- char *newfilename;
- const char *apkentry;
- size_t size;
- struct stat st;
- FILE *f;
-
- filename = malloc(strlen(prefix) + 1 + strlen(dent->d_name) + 1);
- strcpy(filename, prefix);
- strcat(filename, "/");
- strcat(filename, dent->d_name);
-
- apkentry = lo_apkentry(filename, &size);
- if (apkentry == NULL) {
- LOGE("extract_files: Could not find %s in .apk", filename);
- free(filename);
- continue;
- }
-
- newfilename = malloc(strlen(data_dir) + 1 + strlen(prefix) - strlen(root) + strlen(dent->d_name) + 1);
- strcpy(newfilename, data_dir);
- strcat(newfilename, "/");
- strcat(newfilename, prefix + strlen(root) + 1);
-
- if (!mkdir_p(newfilename)) {
- free(filename);
- free(newfilename);
- continue;
- }
-
- strcat(newfilename, "/");
- strcat(newfilename, dent->d_name);
-
- if (stat(newfilename, &st) == 0 &&
- (gzipped || st.st_size == (long long) size)) {
- free(filename);
- free(newfilename);
- continue;
- }
-
- f = fopen(newfilename, "w");
- if (f == NULL) {
- LOGE("extract_files: Could not open %s for writing: %s", newfilename, strerror(errno));
- free(filename);
- free(newfilename);
- continue;
- }
-
- if (!gzipped) {
- if (fwrite(apkentry, size, 1, f) != 1) {
- LOGE("extract_files: Could not write %lld bytes to %s: %s", (long long) size, newfilename, strerror(errno));
- } else {
- LOGI("extract_files: Copied %s to %s: %lld bytes", filename, newfilename, (long long) size);
- }
- } else {
- size = extract_gzipped(filename, apkentry, size, f);
- LOGI("extract_files: Decompressed %s to %s: %lld bytes", filename, newfilename, (long long) size);
- }
-
- fclose(f);
-
- free(filename);
- free(newfilename);
- }
- }
- lo_apk_closedir(tree);
-}
-
/* Android's JNI works only to libraries loaded through Java's
* System.loadLibrary(), it seems. But now with just one big app-specific .so
* on Android, that would not be a problem, but for historical reasons, we
diff --git a/sal/osl/unx/file.cxx b/sal/osl/unx/file.cxx
index 73612a32d273..a4664c924a22 100644
--- a/sal/osl/unx/file.cxx
+++ b/sal/osl/unx/file.cxx
@@ -56,6 +56,8 @@
#ifdef ANDROID
#include <osl/detail/android-bootstrap.h>
+#include <android/log.h>
+#include <android/asset_manager.h>
#endif
/*******************************************************************
@@ -829,6 +831,21 @@ openFilePath( const char *cpFilePath, oslFileHandle* pHandle, sal_uInt32 uFlags,
*/
if (strncmp (cpFilePath, "/assets/", sizeof ("/assets/") - 1) == 0)
{
+ void* address;
+ size_t size;
+ AAssetManager* mgr = lo_get_native_assetmgr();
+ AAsset* asset = AAssetManager_open(mgr, cpFilePath + sizeof("/assets/")-1, AASSET_MODE_BUFFER);
+ if (NULL == asset) {
+ address = NULL;
+ errno = ENOENT;
+ __android_log_print(ANDROID_LOG_ERROR,"libo:sal/osl/unx/file", "failed to open %s", cpFilePath);
+ return osl_File_E_NOENT;
+ } else {
+ size = AAsset_getLength(asset);
+ address = malloc (sizeof(char)*size);
+ AAsset_read (asset,address,size);
+ AAsset_close(asset);
+ }
if (uFlags & osl_File_OpenFlag_Write)
{
// It seems to work better to silently "open" it read-only
@@ -836,15 +853,7 @@ openFilePath( const char *cpFilePath, oslFileHandle* pHandle, sal_uInt32 uFlags,
// loading a document from /assets fails with that idiotic
// "General Error" dialog...
}
- void *address;
- size_t size;
- address = lo_apkentry(cpFilePath, &size);
SAL_INFO("sal.file", "osl_openFile(" << cpFilePath << ") => " << address);
- if (address == NULL)
- {
- errno = ENOENT;
- return osl_File_E_NOENT;
- }
return openMemoryAsFile(address, size, pHandle, cpFilePath);
}
#endif
@@ -1042,6 +1051,10 @@ SAL_CALL osl_closeFile( oslFileHandle Handle )
if (pImpl->m_kind == FileHandle_Impl::KIND_MEM)
{
+#ifdef ANDROID
+ free(pImpl->m_buffer);
+ pImpl->m_buffer = NULL;
+#endif
delete pImpl;
return osl_File_E_None;
}