[Libreoffice-commits] .: 3 commits - sal/osl unotest/prj unotest/source

Tor Lillqvist tml at kemper.freedesktop.org
Fri Nov 18 16:58:37 PST 2011


 sal/osl/android/Makefile                                   |   73 ++-
 sal/osl/android/build.xml                                  |   29 +
 sal/osl/android/jni/lo-bootstrap.c                         |  240 ++++++++++++-
 sal/osl/android/jni/lo-bootstrap.h                         |    3 
 sal/osl/android/src/org/libreoffice/android/Bootstrap.java |   38 +-
 sal/osl/unx/file.cxx                                       |   99 ++++-
 unotest/prj/d.lst                                          |    1 
 unotest/source/cpp/unoexceptionprotector/makefile.mk       |    7 
 8 files changed, 426 insertions(+), 64 deletions(-)

New commits:
commit 552f521070bf5ff4e031206968463cd99061edc5
Author: Tor Lillqvist <tlillqvist at suse.com>
Date:   Sat Nov 19 02:47:22 2011 +0200

    Add read-only pseudo-files representing a memory block
    
    For Android only for now. To be used to read raw asset files from the
    application package (.apk file, a zip archive).

diff --git a/sal/osl/unx/file.cxx b/sal/osl/unx/file.cxx
index d57820b..7a36e69 100644
--- a/sal/osl/unx/file.cxx
+++ b/sal/osl/unx/file.cxx
@@ -79,6 +79,12 @@ struct FileHandle_Impl
     rtl_String *    m_strFilePath; /* holds native file path */
     int             m_fd;
 
+    enum Kind
+    {
+        KIND_FD = 1,
+        KIND_MEM = 2
+    };
+    int          m_kind;
     /** State
      */
     enum StateBits
@@ -242,6 +248,7 @@ FileHandle_Impl::Guard::~Guard()
 FileHandle_Impl::FileHandle_Impl (int fd, char const * path)
     : m_strFilePath (0),
       m_fd      (fd),
+      m_kind    (KIND_FD),
       m_state   (STATE_SEEKABLE | STATE_READABLE),
       m_size    (0),
       m_offset  (0),
@@ -356,6 +363,24 @@ oslFileError FileHandle_Impl::readAt (
     if (!(m_state & STATE_READABLE))
         return osl_File_E_BADF;
 
+    if (m_kind == KIND_MEM)
+    {
+        ssize_t nBytes;
+
+        m_offset = nOffset;
+
+        if ((sal_uInt64) m_offset >= m_size)
+            nBytes = 0;
+        else
+        {
+            nBytes = std::min(nBytesRequested, (size_t) (m_size - m_offset));
+            memmove(pBuffer, m_buffer + m_offset, nBytes);
+            m_offset += nBytes;
+        }
+        *pBytesRead = nBytes;
+        return osl_File_E_None;
+    }
+
 #if defined(LINUX) || defined(SOLARIS)
 
     ssize_t nBytes = ::pread (m_fd, pBuffer, nBytesRequested, nOffset);
@@ -449,7 +474,7 @@ oslFileError FileHandle_Impl::readFileAt (
         *pBytesRead = nBytes;
         return osl_File_E_None;
     }
-    else if (0 == m_buffer)
+    else if (m_kind == KIND_MEM || 0 == m_buffer)
     {
         // not buffered
         return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
@@ -825,6 +850,34 @@ static int osl_file_queryLocking (sal_uInt32 uFlags)
     return 0;
 }
 
+#ifdef ANDROID
+
+static oslFileError
+SAL_CALL osl_openMemoryAsFile( void *address, size_t size, oslFileHandle *pHandle )
+{
+    oslFileError eRet;
+    FileHandle_Impl * pImpl = new FileHandle_Impl (-1, "");
+    if (!pImpl)
+    {
+        eRet = oslTranslateFileError (OSL_FET_ERROR, ENOMEM);
+        return eRet;
+    }
+    pImpl->m_kind = FileHandle_Impl::KIND_MEM;
+    pImpl->m_size = sal::static_int_cast< sal_uInt64 >(size);
+
+    *pHandle = (oslFileHandle)(pImpl);
+
+    pImpl->m_bufptr = 0;
+    pImpl->m_buflen = size;
+
+    pImpl->m_bufsiz = size;
+    pImpl->m_buffer = (sal_uInt8*) address;
+
+    return osl_File_E_None;
+}
+
+#endif
+
 /****************************************************************************
  *  osl_openFile
  ***************************************************************************/
@@ -854,6 +907,21 @@ SAL_CALL osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uIn
         return oslTranslateFileError (OSL_FET_ERROR, errno);
 #endif /* MACOSX */
 
+#ifdef ANDROID
+    /* Opening a file from /assets read-only means
+     * we should mmap it from the .apk file
+     */
+    if (!(uFlags & osl_File_OpenFlag_Write) &&
+        strncmp (buffer, "/assets/", strlen ("/assets/")) == 0)
+    {
+        void *address;
+        size_t size;
+        void *(*lo_apkentry)(const char *, size_t *) = (void *(*)(const char *, size_t *)) dlsym(RTLD_DEFAULT, "lo_apkentry");
+        address = (*lo_apkentry)(buffer, &size);
+        return osl_openMemoryAsFile(address, size, pHandle);
+    }
+#endif
+
     /* set mode and flags */
     int mode  = S_IRUSR | S_IRGRP | S_IROTH;
     int flags = O_RDONLY;
@@ -976,6 +1044,12 @@ SAL_CALL osl_closeFile( oslFileHandle Handle )
 {
     FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
 
+    if (pImpl->m_kind == FileHandle_Impl::KIND_MEM)
+    {
+        delete pImpl;
+        return osl_File_E_None;
+    }
+
     if ((pImpl == 0) || (pImpl->m_fd < 0))
         return osl_File_E_INVAL;
 
@@ -1008,6 +1082,9 @@ SAL_CALL osl_syncFile(oslFileHandle Handle)
 {
     FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
 
+    if (pImpl->m_kind == FileHandle_Impl::KIND_MEM)
+        return osl_File_E_None;
+
     if ((0 == pImpl) || (-1 == pImpl->m_fd))
         return osl_File_E_INVAL;
 
@@ -1037,6 +1114,12 @@ SAL_CALL osl_mapFile (
 {
     FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
 
+    if (pImpl->m_kind == FileHandle_Impl::KIND_MEM)
+    {
+        *ppAddr = pImpl->m_buffer;
+        return osl_File_E_None;
+    }
+
     if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppAddr))
         return osl_File_E_INVAL;
     *ppAddr = 0;
@@ -1140,7 +1223,7 @@ SAL_CALL osl_readLine (
 {
     FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
 
-    if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppSequence))
+    if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == ppSequence))
         return osl_File_E_INVAL;
     sal_uInt64 uBytesRead = 0;
 
@@ -1165,7 +1248,7 @@ SAL_CALL osl_readFile (
 {
     FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
 
-    if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesRead))
+    if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pBuffer) || (0 == pBytesRead))
         return osl_File_E_INVAL;
 
     static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
@@ -1226,7 +1309,7 @@ SAL_CALL osl_readFileAt (
 {
     FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
 
-    if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesRead))
+    if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pBuffer) || (0 == pBytesRead))
         return osl_File_E_INVAL;
     if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
         return osl_File_E_SPIPE;
@@ -1289,7 +1372,7 @@ SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF )
 {
     FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
 
-    if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pIsEOF))
+    if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pIsEOF))
         return osl_File_E_INVAL;
 
     FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
@@ -1305,7 +1388,7 @@ SAL_CALL osl_getFilePos( oslFileHandle Handle, sal_uInt64* pPos )
 {
     FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
 
-    if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pPos))
+    if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pPos))
         return osl_File_E_INVAL;
 
     FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
@@ -1321,7 +1404,7 @@ SAL_CALL osl_setFilePos (oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffse
 {
     FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
 
-    if ((0 == pImpl) || (-1 == pImpl->m_fd))
+    if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)))
         return osl_File_E_INVAL;
 
     static sal_Int64 const g_limit_off_t = std::numeric_limits< off_t >::max();
@@ -1368,7 +1451,7 @@ SAL_CALL osl_getFileSize( oslFileHandle Handle, sal_uInt64* pSize )
 {
     FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
 
-    if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pSize))
+    if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pSize))
         return osl_File_E_INVAL;
 
     FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
commit 2ad14b0e0380c390f09256b3f4f70f733e310df2
Author: Tor Lillqvist <tlillqvist at suse.com>
Date:   Sat Nov 19 02:28:06 2011 +0200

    More misc Android work
    
    Add possibility to start strace tracing the process. Unfortunately it
    this doesn't seem to work as nicely as one might have hoped. If the
    process crashes, the last strace output does not show up. Some
    buffering that gets abruptly discarded when the straced process dies?
    
    Add a function to the native code to look up an archive member in the
    .apk and return a pointer to it. To be used for non-compressed
    resources only. We mmap the whole .apk. The Zip format parsing code is
    borrrowed from Mozilla's APKOpen.cpp.
    
    Correspondingly, add to the local build.xml a re-definition of the
    "-package-resources" target from Ant's build.xml modified to not
    compress resources.
    
    Improved the Makefile a lot. New target "install" to build the apk and
    install it without constructing the apk twice.
    
    Other minor changes here and there.

diff --git a/sal/osl/android/Makefile b/sal/osl/android/Makefile
index d60618a..a607d93 100644
--- a/sal/osl/android/Makefile
+++ b/sal/osl/android/Makefile
@@ -2,34 +2,60 @@ NDK_HOME:=$(shell type -p ndk-build)
 NDK_HOME:=$(shell dirname $(NDK_HOME))
 
 SODEST=libs/armeabi-v7a
+OBJLOCAL=obj/local/armeabi-v7a
 
-all:
+define COPY
+cp $(1) $(SODEST)$(if $(2),/$(2)) && \
+arm-linux-androideabi-strip --strip-debug $(SODEST)$(if $(2),/$(2),/$(notdir $(1))) && \
+cp $(1) $(OBJLOCAL)$(if $(2),/$(2))
+endef
+
+define CONDCOPY
+test -f $(1) && $(call COPY,$(1),$(2))
+endef
+
+# The default target just builds
+all: ndk-build
+	unset JAVA_HOME && ant debug
+	@echo 'Install it on the device with ant debug install'
+	@echo 'Then run it with something like what "make run" does (see Makefile)'
+
+ndk-build:
 	ndk-build V=1
 #
 # Copy shared libraries we need to libs/armeabi-v7a so that ant will
 # include them in the .apk.
-# First ones from here, sal
-	cp ../../$(INPATH)/bin/cppunittester $(SODEST)/libcppunittester.so
 #
-# Then the cppunit library
-	cp $(OUTDIR)/lib/libcppunit-1.12.so $(SODEST)
+# Copy them to obj/local/armeabi-v7a, too, where gdb will look for
+# them.
+#
+# First the cppunittester "program" from here, which as all "program"
+# files we build for Android actually is a shared object.
+	$(call COPY,../../$(INPATH)/bin/cppunittester,libcppunittester.so)
 #
-# Then cppunit "plug-ins", first ones from sal
+# The cppunit library
+	$(call COPY,$(OUTDIR)/lib/libcppunit-1.12.so)
 #
-	cp ../../$(INPATH)/lib/*.so $(SODEST)
+# cppunit "plug-ins", first ones from sal
 #
-# Then ones from other modules. Note that depending on when you try
+	$(call COPY,../../$(INPATH)/lib/*.so)
+#
+# and ones from other modules. Note that depending on when you try
 # this, these might not have been built yet.
 #
 	-for F in $(SRC_ROOT)/cppu/$(INPATH)/lib/qa_*.so; do \
-	    test -f $${F} && cp $${F} $(SODEST); \
+	    $(call CONDCOPY,$${F},`basename $${F}`); \
 	done
 #
 	-for F in i18npool_test_breakiterator; do \
-	    test -f $(WORKDIR)/LinkTarget/CppunitTest/libtest_$${F}.so && cp $(WORKDIR)/LinkTarget/CppunitTest/libtest_$${F}.so $(SODEST); \
+	    $(call CONDCOPY,$(WORKDIR)/LinkTarget/CppunitTest/libtest_$${F}.so); \
 	done
+
 #
-# Then libs and UNO components that the tests from other modules need.
+# Other "programs"
+	$(call COPY,$(OUTDIR)/bin/uno,libunoexe.so)
+#
+# Libs and UNO components that the tests from other modules need.
 #
 	-for F in gcc3_uno \
 		  reg \
@@ -37,31 +63,22 @@ all:
 		  uno_cppu \
 		  uno_salhelpergcc3 \
 	          uno_cppuhelpergcc3 \
+		  unoexceptionprotector \
+		  xml2 \
 		  xmlreader \
 		  bootstrap.uno; do \
-	    test -f $(OUTDIR)/lib/lib$${F}.so && cp $(OUTDIR)/lib/lib$${F}.so $(SODEST); \
+	    $(call CONDCOPY,$(OUTDIR)/lib/lib$${F}.so); \
 	done
 #
 # Then the shared GNU C++ library
-	cp $(NDK_HOME)/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/libgnustl_shared.so $(SODEST)
-#
-# Copy them to obj/local/armeabi-v7a, too, where gdb will look for
-# them. Not sure if this is useful or not; I have great problems with
-# ndk-gdb. Actually, commenting out this part for now...
-#
-#	cp ../../$(INPATH)/bin/cppunittester obj/local/armeabi-v7a/libcppunittester.so
-#	cp $(OUTPATH)/lib/libcppunit-1.12.so obj/local/armeabi-v7a
-#	cp ../../$(INPATH)/lib/*.so obj/local/armeabi-v7a
-#	cp $(NDK_HOME)/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/libgnustl_shared.so obj/local/armeabi-v7a
-	unset JAVA_HOME && ant debug
-	@echo 'Install it on the device with ant debug install'
-	@echo 'Then run it with something like what "make run" does (see Makefile)'
+	$(call COPY,$(NDK_HOME)/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/libgnustl_shared.so)
 
-run: all
+install: ndk-build
 	unset JAVA_HOME && ant debug install
-#
+
+run: install
 # Note: this is of course just an example. The full path the the test
 # .so needs to be supplied, unfortunately, I guess cppunittester
 # checks its existance using the pathname instead of just
 # osl_loadModule'ing it.
-	adb shell am start -n org.libreoffice.android/.Bootstrap -e lo-main-library libcppunittester -e lo-main-cmdline "cppunittester /data/data/org.libreoffice.android/lib/libqa_sal_types.so"
+	adb shell am start -n org.libreoffice.android/.Bootstrap -e lo-main-library libcppunittester -e lo-main-cmdline "/data/data/org.libreoffice.android/lib/libqa_sal_types.so"
diff --git a/sal/osl/android/build.xml b/sal/osl/android/build.xml
index a186d8d..6b091c4 100644
--- a/sal/osl/android/build.xml
+++ b/sal/osl/android/build.xml
@@ -82,4 +82,33 @@
     <!-- version-tag: 1 -->
     <import file="${sdk.dir}/tools/ant/build.xml" />
 
+    <!-- Re-define the "-package-resources" target to not compress resources -->
+
+    <target name="-package-resources" depends="-crunch">
+        <!-- only package resources if *not* a library project -->
+        <do-only-if-not-library elseText="Library project: do not package resources..." >
+            <aapt executable="${aapt}"
+                    command="package"
+                    versioncode="${version.code}"
+                    versionname="${version.name}"
+                    debug="${build.is.packaging.debug}"
+                    manifest="AndroidManifest.xml"
+                    assets="${asset.absolute.dir}"
+                    androidjar="${android.jar}"
+                    apkfolder="${out.absolute.dir}"
+                    nocrunch="${build.packaging.nocrunch}"
+                    resourcefilename="${resource.package.file.name}"
+                    resourcefilter="${aapt.resource.filter}"
+                    projectLibrariesResName="project.libraries.res"
+                    projectLibrariesPackageName="project.libraries.package"
+                    previousBuildType="${build.last.target}"
+                    buildType="${build.target}">
+                <res path="${out.res.absolute.dir}" />
+                <res path="${resource.absolute.dir}" />
+                <nocompress /> <!-- forces no compression on any files in assets or res/raw -->
+                <!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->
+            </aapt>
+        </do-only-if-not-library>
+    </target>
+
 </project>
diff --git a/sal/osl/android/jni/lo-bootstrap.c b/sal/osl/android/jni/lo-bootstrap.c
index 04540a9..0ddbe3f 100644
--- a/sal/osl/android/jni/lo-bootstrap.c
+++ b/sal/osl/android/jni/lo-bootstrap.c
@@ -16,6 +16,9 @@
  * Copyright (C) 2011 Tor Lillqvist <tml at 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 at mozilla.com>.
+ *
  * All Rights Reserved.
  *
  * For minor contributions see the git repository.
@@ -35,6 +38,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <dlfcn.h>
+#include <sys/mman.h>
 
 #include <jni.h>
 
@@ -57,11 +61,68 @@ struct engine {
 };
 
 static struct android_app *app;
-static JNIEnv *jni_env;
 static const char **library_locations;
+static void *apk_file;
+static int apk_file_size;
 static int (*lo_main)(int, const char **);
 static int lo_main_argc;
 static const char **lo_main_argv;
+static int sleep_time = 0;
+
+/* compression methods */
+#define STORE    0
+#define DEFLATE  8
+#define LZMA    14
+
+struct local_file_header {
+    uint32_t signature;
+    uint16_t min_version;
+    uint16_t general_flag;
+    uint16_t compression;
+    uint16_t lastmod_time;
+    uint16_t lastmod_date;
+    uint32_t crc32;
+    uint32_t compressed_size;
+    uint32_t uncompressed_size;
+    uint16_t filename_size;
+    uint16_t extra_field_size;
+    char     data[0];
+} __attribute__((__packed__));
+
+struct cdir_entry {
+    uint32_t signature;
+    uint16_t creator_version;
+    uint16_t min_version;
+    uint16_t general_flag;
+    uint16_t compression;
+    uint16_t lastmod_time;
+    uint16_t lastmod_date;
+    uint32_t crc32;
+    uint32_t compressed_size;
+    uint32_t uncompressed_size;
+    uint16_t filename_size;
+    uint16_t extra_field_size;
+    uint16_t file_comment_size;
+    uint16_t disk_num;
+    uint16_t internal_attr;
+    uint32_t external_attr;
+    uint32_t offset;
+    char     data[0];
+} __attribute__((__packed__));
+
+#define CDIR_END_SIG 0x06054b50
+
+struct cdir_end {
+    uint32_t signature;
+    uint16_t disk_num;
+    uint16_t cdir_disk;
+    uint16_t disk_entries;
+    uint16_t cdir_entries;
+    uint32_t cdir_size;
+    uint32_t cdir_offset;
+    uint16_t comment_size;
+    char     comment[0];
+} __attribute__((__packed__));
 
 static void
 engine_handle_cmd(struct android_app* app,
@@ -225,16 +286,21 @@ Java_org_libreoffice_android_Bootstrap_dlcall(JNIEnv* env,
 }
 
 // public native boolean setup(String dataDir,
+//                             String apkFile,
 //                             String[] ld_library_path);
 
 jboolean
-Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2_3Ljava_lang_String_2(JNIEnv* env,
-                                                                                       jobject this,
-                                                                                       jstring dataDir,
-                                                                                       jobjectArray ld_library_path)
+Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2Ljava_lang_String_2_3Ljava_lang_String_2
+    (JNIEnv* env,
+     jobject this,
+     jstring dataDir,
+     jstring apkFile,
+     jobjectArray ld_library_path)
 {
-    int i, n;
+    struct stat st;
+    int i, n, fd;
     const jbyte *dataDirPath;
+    const jbyte *apkFilePath;
     char *lib_dir;
 
     n = (*env)->GetArrayLength(env, ld_library_path);
@@ -262,17 +328,45 @@ Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2_3Ljava_lang_St
     for (n = 0; library_locations[n] != NULL; n++)
         LOGI("library_locations[%d] = %s", n, library_locations[n]);
 
+    apkFilePath =  (*env)->GetStringUTFChars(env, apkFile, NULL);
+
+    fd = open(apkFilePath, O_RDONLY);
+    if (fd == -1) {
+        LOGI("Could not open %s", apkFilePath);
+        (*env)->ReleaseStringUTFChars(env, apkFile, apkFilePath);
+        return JNI_FALSE;
+    }
+    if (fstat(fd, &st) == -1) {
+        LOGI("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) {
+        LOGI("Could not mmap %s", apkFilePath);
+        (*env)->ReleaseStringUTFChars(env, apkFile, apkFilePath);
+        return JNI_FALSE;
+    }
+    apk_file_size = st.st_size;
+
+    (*env)->ReleaseStringUTFChars(env, apkFile, apkFilePath);
+
     return JNI_TRUE;
 }
 
 // public native boolean setup(int lo_main_ptr,
-//                             Object lo_main_argument);
+//                             Object lo_main_argument,
+//                             int lo_main_delay);
 
 jboolean
-Java_org_libreoffice_android_Bootstrap_setup__ILjava_lang_Object_2(JNIEnv* env,
-                                                                   jobject this,
-                                                                   void *lo_main_ptr,
-                                                                   jobject lo_main_argument)
+Java_org_libreoffice_android_Bootstrap_setup__ILjava_lang_Object_2I(JNIEnv* env,
+                                                                    jobject this,
+                                                                    void *lo_main_ptr,
+                                                                    jobject lo_main_argument,
+                                                                    jint lo_main_delay)
 {
     jclass StringArray;
     int i;
@@ -301,9 +395,37 @@ Java_org_libreoffice_android_Bootstrap_setup__ILjava_lang_Object_2(JNIEnv* env,
     }
     lo_main_argv[lo_main_argc] = NULL;
 
+    sleep_time = lo_main_delay;
+
     return JNI_TRUE;
 }
 
+// public static native int getpid();
+
+jint
+Java_org_libreoffice_android_Bootstrap_getpid(JNIEnv* env,
+                                              jobject clazz)
+{
+    return getpid();
+}
+
+
+// public static native void system(String cmdline);
+
+jint
+Java_org_libreoffice_android_Bootstrap_system(JNIEnv* env,
+                                              jobject clazz,
+                                              jstring cmdline)
+{
+    const jbyte *s = (*env)->GetStringUTFChars(env, cmdline, NULL);
+
+    LOGI("system(%s)", s);
+
+    system(s);
+
+    (*env)->ReleaseStringUTFChars(env, cmdline, s);
+}
+
 char **
 lo_dlneeds(const char *library)
 {
@@ -534,6 +656,7 @@ lo_dlopen(const char *library)
             return NULL;
         }
     }
+    free_ptrarray((void **) needed);
 
     p = dlopen(full_name, RTLD_LOCAL);
     LOGI("dlopen(%s) = %p", full_name, p);
@@ -569,14 +692,10 @@ lo_dladdr(void *addr,
     FILE *maps;
     char line[200];
     int result;
+    int found;
 
     result = dladdr(addr, info);
-    if (result != 0)
-        LOGI("dladdr(%p) = { %s:%p, %s:%p ]",
-             addr,
-             info->dli_fname, info->dli_fbase,
-             info->dli_sname ? info->dli_sname : "(none)", info->dli_saddr);
-    else {
+    if (result == 0) {
         LOGI("dladdr(%p) = 0", addr);
         return 0;
     }
@@ -586,6 +705,8 @@ lo_dladdr(void *addr,
         LOGI("lo_dladdr: Could not open /proc/self/maps: %s", strerror(errno));
         return 0;
     }
+
+    found = 0;
     while (fgets(line, sizeof(line), maps) != NULL &&
            line[strlen(line)-1] == '\n') {
         void *lo, *hi;
@@ -599,16 +720,93 @@ lo_dladdr(void *addr,
                     fclose(maps);
                     return 0;
                 }
+                LOGI("dladdr(%p) = { %s:%p, %s:%p }: %s",
+                     addr,
+                     info->dli_fname, info->dli_fbase,
+                     info->dli_sname ? info->dli_sname : "(none)", info->dli_saddr,
+                     file);
                 info->dli_fname = strdup(file);
+                found = 1;
                 break;
             }
         }
     }
+    if (!found)
+        LOGI("lo_dladdr: Did not find %p in /proc/self/maps", addr);
     fclose(maps);
 
     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;
+}
+
+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) {
+        LOGI("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++;
+
+    entry = find_cdir_entry(cdir_start, cdir_entries, filename);
+
+    if (entry == NULL) {
+        LOGI("lo_apkentry: Could not find %s", filename);
+        return NULL;
+    }
+    file = (struct local_file_header *)((char *)apk_file + letoh32(entry->offset));
+
+    if (letoh16(file->compression) != STORE) {
+        LOGI("lo_apkentry: File %s is compressed", filename);
+        return NULL;
+    }
+
+    data = ((char *)&file->data) + letoh16(file->filename_size) + letoh16(file->extra_field_size);
+    *size = file->uncompressed_size;
+
+    LOGI("lo_apkentry(%s): %p, %d", filename, data, *size);
+
+    return data;
+}
+
 int
 lo_dlcall_argc_argv(void *function,
                     int argc,
@@ -623,6 +821,7 @@ lo_dlcall_argc_argv(void *function,
 void android_main(struct android_app* state)
 {
     struct engine engine;
+    Dl_info lo_main_info;
 
     app = state;
 
@@ -630,6 +829,13 @@ void android_main(struct android_app* state)
     state->userData = &engine;
     state->onAppCmd = engine_handle_cmd;
 
+    if (lo_dladdr(lo_main, &lo_main_info) != 0) {
+        lo_main_argv[0] = lo_main_info.dli_fname;
+    }
+
+    if (sleep_time != 0)
+        sleep(sleep_time);
+
     lo_main(lo_main_argc, lo_main_argv);
 
     exit(0);
diff --git a/sal/osl/android/jni/lo-bootstrap.h b/sal/osl/android/jni/lo-bootstrap.h
index 523ba99..c01ae3c 100644
--- a/sal/osl/android/jni/lo-bootstrap.h
+++ b/sal/osl/android/jni/lo-bootstrap.h
@@ -42,6 +42,9 @@ void *lo_dlsym(void *handle,
 int lo_dladdr(void *addr,
               Dl_info *info);
 
+void *lo_apkentry(const char *filename,
+                  size_t *size);
+
 int lo_dlcall_argc_argv(void *function,
                         int argc,
                         const char **argv);
diff --git a/sal/osl/android/src/org/libreoffice/android/Bootstrap.java b/sal/osl/android/src/org/libreoffice/android/Bootstrap.java
index 5e70543..505b72e 100644
--- a/sal/osl/android/src/org/libreoffice/android/Bootstrap.java
+++ b/sal/osl/android/src/org/libreoffice/android/Bootstrap.java
@@ -45,10 +45,12 @@ public class Bootstrap extends NativeActivity
     private static String TAG = "lo-bootstrap";
 
     public native boolean setup(String dataDir,
+                                String apkFile,
                                 String[] ld_library_path);
 
     public native boolean setup(int lo_main_ptr,
-                                Object lo_main_argument);
+                                Object lo_main_argument,
+                                int lo_main_delay);
 
     // This is not just a wrapper for the C library dlopen(), but also
     // loads recursively dependent libraries.
@@ -57,6 +59,12 @@ public class Bootstrap extends NativeActivity
     // This is just a wrapper for the C library dlsym().
     public static native int dlsym(int handle, String symbol);
 
+    // Wrapper for getpid()
+    public static native int getpid();
+
+    // Wrapper for system()
+    public static native void system(String cmdline);
+
     @Override
     protected void onCreate(Bundle savedInstanceState)
     {
@@ -79,7 +87,7 @@ public class Bootstrap extends NativeActivity
 
         String[] llpa = llp.split(":");
 
-        if (!setup(dataDir, llpa))
+        if (!setup(dataDir, getApplication().getPackageResourcePath(), llpa))
             return;
 
         String mainLibrary = getIntent().getStringExtra("lo-main-library");
@@ -95,12 +103,22 @@ public class Bootstrap extends NativeActivity
         String cmdLine = getIntent().getStringExtra("lo-main-cmdline");
 
         if (cmdLine == null)
-            cmdLine = "cppunittester /data/data/org.libreoffice.android/lib/libqa_sal_types.so";
+            cmdLine = "/data/data/org.libreoffice.android/lib/libqa_sal_types.so";
+
+        // argv[0] will be replaced by android_main() in lo-bootstrap.c by the
+        // pathname of the mainLibrary.
+        cmdLine = "dummy-program-name " + cmdLine;
 
         Log.i(TAG, String.format("cmdLine=%s", cmdLine));
 
         String[] argv = cmdLine.split(" ");
 
+        // As we don't do any shell style quote handling, to enable
+        // having spaces in argv elements, they need to be entered as
+        // '~' characters which we here change into spaces...
+        for (int i = 0; i < argv.length; i++)
+            argv[i] = argv[i].replace('~', ' ');
+
         // Load the LO "program" here and look up lo_main
         int loLib = dlopen(mainLibrary);
 
@@ -115,8 +133,18 @@ public class Bootstrap extends NativeActivity
             return;
         }
 
-        // This saves lo_main and argv
-        if (!setup(lo_main, argv))
+        // Tell lo-bootstrap to Start a strace on itself if requested
+        String strace_args = getIntent().getStringExtra("lo-strace");
+        if (strace_args != null)
+            system("/system/xbin/strace -p " + getpid() + " " + (strace_args != "yes" ? strace_args : "" ) + " &");
+
+        int delay = 0;
+        String sdelay = getIntent().getStringExtra("lo-main-delay");
+        if (sdelay != null)
+            delay = Integer.parseInt(sdelay);
+
+        // Tell lo-bootstrap.c the stuff it needs to know
+        if (!setup(lo_main, argv, delay))
             return;
 
         // Finally, call our super-class, NativeActivity's onCreate(),
commit 79d0853239b7b8bd4fa2de5d8e1917343b27f8d1
Author: Tor Lillqvist <tlillqvist at suse.com>
Date:   Sat Nov 19 01:23:23 2011 +0200

    Do build the unoexceptionprotector also when cross-compiling

diff --git a/unotest/prj/d.lst b/unotest/prj/d.lst
index a173c2f..7b84924 100644
--- a/unotest/prj/d.lst
+++ b/unotest/prj/d.lst
@@ -8,6 +8,7 @@ mkdir: %_DEST%\inc\unotest\detail
 ..\%__SRC%\lib\libunotest.dll.a %_DEST%\lib\libunotest.dll.a
 ..\%__SRC%\lib\unoexceptionprotector.dylib %_DEST%\lib\unoexceptionprotector.dylib
 ..\%__SRC%\lib\unoexceptionprotector.so %_DEST%\lib\unoexceptionprotector.so
+..\%__SRC%\lib\libunoexceptionprotector.so %_DEST%\lib\libunoexceptionprotector.so
 ..\inc\unotest\detail\unotestdllapi.hxx %_DEST%\inc\unotest\detail\unotestdllapi.hxx
 ..\inc\unotest\bootstrapfixturebase.hxx %_DEST%\inc\unotest\bootstrapfixturebase.hxx
 ..\inc\unotest\filters-test.hxx %_DEST%\inc\unotest\filters-test.hxx
diff --git a/unotest/source/cpp/unoexceptionprotector/makefile.mk b/unotest/source/cpp/unoexceptionprotector/makefile.mk
index d3d13e6..e20438e 100644
--- a/unotest/source/cpp/unoexceptionprotector/makefile.mk
+++ b/unotest/source/cpp/unoexceptionprotector/makefile.mk
@@ -32,11 +32,6 @@ VISIBILITY_HIDDEN = TRUE
 
 .INCLUDE: settings.mk
 
-.IF "$(CROSS_COMPILING)"=="YES"
-all:
-    @echo Nothing done when cross-compiling
-.ENDIF
-
 # --- Files --------------------------------------------------------
 DLLPRE =
 
@@ -52,7 +47,7 @@ SHL1STDLIBS = \
     $(CPPULIB) \
     $(CPPUNITLIB) \
     $(SALLIB)
-SHL1TARGET = unoexceptionprotector
+SHL1TARGET = $(ENFORCEDSHLPREFIX)unoexceptionprotector
 SHL1USE_EXPORTS = name
 DEF1NAME = $(SHL1TARGET)
 


More information about the Libreoffice-commits mailing list