libreofficekit-jni.c 6.13 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/* -*- 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>
20
#include <unistd.h>
21 22 23 24

#include <jni.h>

#include <android/log.h>
25 26
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
27 28 29

#include <osl/detail/android-bootstrap.h>

30 31 32
#include <LibreOfficeKit/LibreOfficeKit.h>

#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "LibreOfficeKit", __VA_ARGS__))
33 34 35
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "LibreOfficeKit", __VA_ARGS__))

/* These are valid / used in all apps. */
36 37 38
extern const char* data_dir;
extern const char* cache_dir;
extern void* apk_file;
39
extern int apk_file_size;
40
extern bool android_lok_from_jni; ///< for the distinction if the LOK is used for the 'old' (JNI-based) or the 'new' (loolwsd-based) app
41
AAssetManager* native_asset_manager;
42 43

extern void Java_org_libreoffice_android_Bootstrap_putenv(JNIEnv* env, jobject clazz, jstring string);
44
extern void Java_org_libreoffice_android_Bootstrap_redirect_1stdio(JNIEnv* env, jobject clazz, jboolean state);
45

46
extern LibreOfficeKit* libreofficekit_hook(const char* install_path);
47

48
static char *full_program_dir = NULL;
49

50 51 52
/// Call the same method from Bootstrap.
__attribute__ ((visibility("default")))
void
53 54
Java_org_libreoffice_kit_LibreOfficeKit_putenv
    (JNIEnv* env, jobject clazz, jstring string)
55 56 57 58 59 60
{
    Java_org_libreoffice_android_Bootstrap_putenv(env, clazz, string);
}

/// Call the same method from Bootstrap.
__attribute__ ((visibility("default")))
61 62
void Java_org_libreoffice_kit_LibreOfficeKit_redirectStdio
    (JNIEnv* env, jobject clazz, jboolean state)
63
{
64
    Java_org_libreoffice_android_Bootstrap_redirect_1stdio(env, clazz, state);
65 66 67 68
}

/// Initialize the LibreOfficeKit.
__attribute__ ((visibility("default")))
69
jboolean libreofficekit_initialize(JNIEnv* env,
70
     jstring dataDir, jstring cacheDir, jstring apkFile, jobject assetManager)
71 72 73 74 75 76 77
{
    struct stat st;
    int fd;
    const char *dataDirPath;
    const char *cacheDirPath;
    const char *apkFilePath;

78 79 80
    const char *fontsConf = "/etc/fonts/fonts.conf";
    char *fontsConfPath;

81
    setenv("OOO_DISABLE_RECOVERY", "1", 1);
82

83 84
    native_asset_manager = AAssetManager_fromJava(env, assetManager);

85 86 87 88 89 90 91 92
    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);

93 94 95
    // TMPDIR is used by osl_getTempDirURL()
    setenv("TMPDIR", cache_dir, 1);

96 97 98 99 100 101 102 103 104 105 106 107
    fontsConfPath = malloc(strlen(data_dir) + sizeof(fontsConf));
    strcpy(fontsConfPath, data_dir);
    strcat(fontsConfPath, fontsConf);

    fd = open(fontsConfPath, O_RDONLY);
    if (fd != -1) {
        close(fd);
        LOGI("Setting FONTCONFIG_FILE to %s", fontsConfPath);
        setenv("FONTCONFIG_FILE", fontsConfPath, 1);
    }
    free(fontsConfPath);

108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
    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())
135 136
    {
        LOGE("setup_cdir failed");
137
        return JNI_FALSE;
138
    }
139 140

    if (!setup_assets_tree())
141 142
    {
        LOGE("setup_assets_tree failed");
143
        return JNI_FALSE;
144 145
    }

146
    LOGI("LibreOfficeKit: libreofficekit_initialize finished");
147 148

    return JNI_TRUE;
149 150 151 152 153 154 155 156 157 158 159 160
}

/// Initialize the LibreOfficeKit.
__attribute__ ((visibility("default")))
jboolean Java_org_libreoffice_kit_LibreOfficeKit_initializeNative
    (JNIEnv* env, jobject clazz,
     jstring dataDir, jstring cacheDir, jstring apkFile, jobject assetManager)
{
    const char program_dir[] = "/program";
    size_t data_dir_len;

    (void) clazz;
161 162 163 164 165

    // the 'old' app needs to avoid setting the virtual device to transparent
    // in paintTile(), so indicate we are using the 'old' app
    android_lok_from_jni = true;

166 167
    libreofficekit_initialize(env, dataDir, cacheDir, apkFile, assetManager);

168
    // LibreOfficeKit expects a path to the program/ directory
169
    free(full_program_dir);
170 171 172 173 174 175
    data_dir_len = strlen(data_dir);
    full_program_dir = malloc(data_dir_len + sizeof(program_dir));

    strncpy(full_program_dir, data_dir, data_dir_len);
    strncpy(full_program_dir + data_dir_len, program_dir, sizeof(program_dir));

176
    // Initialize LibreOfficeKit
177
    if (!libreofficekit_hook(full_program_dir))
178 179 180 181 182 183
    {
        LOGE("libreofficekit_hook returned null");
        return JNI_FALSE;
    }

    LOGI("LibreOfficeKit successfully initialized");
184 185 186 187

    return JNI_TRUE;
}

188
__attribute__ ((visibility("default")))
189
jobject Java_org_libreoffice_kit_LibreOfficeKit_getLibreOfficeKitHandle
190 191
    (JNIEnv* env, jobject clazz)
{
192 193
    LibreOfficeKit* aOffice;

194 195 196
    (void) env;
    (void) clazz;

197 198 199
    aOffice = libreofficekit_hook(full_program_dir);

    return (*env)->NewDirectByteBuffer(env, (void*) aOffice, sizeof(LibreOfficeKit));
200 201
}

202 203 204 205
__attribute__ ((visibility("default")))
AAssetManager *
lo_get_native_assetmgr(void)
{
206
    return native_asset_manager;
207 208
}

209
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */