diff --git a/app/src/main/cpp/archive.c b/app/src/main/cpp/archive.c index 6e4e12b7d..714738554 100644 --- a/app/src/main/cpp/archive.c +++ b/app/src/main/cpp/archive.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -104,7 +103,6 @@ JNIEXPORT jint JNICALL Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *_, jobject thiz, jint fd, jlong size) { archiveAddr = mmap64(0, size, PROT_READ, MAP_PRIVATE, fd, 0); if (archiveAddr == MAP_FAILED) { - archiveAddr = NULL; LOGE("%s%d", "mmap64 failed with errno ", errno); return 0; } @@ -145,27 +143,35 @@ Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *_, jobject thiz, jint fd, return r; } -JNIEXPORT jint JNICALL -Java_com_hippo_UriArchiveAccessor_extractToMemfd(JNIEnv *_, jobject thiz, jint index) { +typedef struct Memarea { + void *buffer; + long size; +} Memarea; + +JNIEXPORT jlong JNICALL +Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *_, jobject thiz, jint index) { struct archive_entry *entry; int ret; if (!arc || index < cur_index) { archive_alloc(); cur_index = 0; } - int memfd = syscall(SYS_memfd_create, "ArchiveMemFD", 0); + Memarea *memarea = malloc(sizeof(Memarea)); while (archive_read_next_header(arc, &entry) == ARCHIVE_OK) { if (!filename_is_playable_file(archive_entry_pathname(entry))) continue; if (cur_index++ == index) { - ret = archive_read_data_into_fd(arc, memfd); + memarea->size = (long) archive_entry_size(entry); + memarea->buffer = malloc(memarea->size); + ret = archive_read_data(arc, memarea->buffer, memarea->size); + if (ret != memarea->size) + LOGE("%s", "No enough data read, WTF?"); if (ret < 0) LOGE("%s%s", "Archive read failed:", archive_error_string(arc)); break; } } - lseek64(memfd, 0, SEEK_SET); - return memfd; + return (jlong) memarea; } JNIEXPORT void JNICALL diff --git a/app/src/main/cpp/image.c b/app/src/main/cpp/image.c index 50174cbe6..71a6aae72 100644 --- a/app/src/main/cpp/image.c +++ b/app/src/main/cpp/image.c @@ -19,10 +19,8 @@ #include #include -#include #include -#include #include #include @@ -54,6 +52,7 @@ void image_onUnload() { typedef struct { AImageDecoder *decoder; + void *srcBuffer; size_t stride; int fd; } SOURCE; @@ -73,8 +72,7 @@ static void recycleSource(SOURCE *src) { if (!src) return; AImageDecoder_delete(src->decoder); - if (!android_fdsan_get_owner_tag(src->fd)) - close(src->fd); + free(src->srcBuffer); free(src); } @@ -86,6 +84,11 @@ static void recycle(IMAGE *image) { free(image); } +typedef struct Memarea { + void *buffer; + long size; +} Memarea; + bool copy_pixels(const void *src, int src_w, int src_h, int src_x, int src_y, void *dst, int dst_w, int dst_h, int dst_x, int dst_y, int width, int height) { @@ -213,6 +216,17 @@ IMAGE *createFromFd(int fd) { return image; } +IMAGE *createFromAddr(void *addr, long size) { + AImageDecoder *decoder; + AImageDecoder_createFromBuffer((const void *) addr, size, &decoder); + IMAGE *image = calloc(1, sizeof(IMAGE)); + SOURCE *src = calloc(1, sizeof(SOURCE)); + src->decoder = decoder; + src->srcBuffer = addr; + decodeCommon(image, src); + return image; +} + IMAGE *create(int32_t width, int32_t height, const void *data) { IMAGE *plain = calloc(1, sizeof(IMAGE)); void *buffer = NULL; @@ -342,6 +356,14 @@ Java_com_hippo_image_Image_nativeRecycle(JNIEnv *env, jclass clazz, jlong ptr) { recycle((IMAGE *) ptr); } +JNIEXPORT jlong JNICALL +Java_com_hippo_image_Image_nativeDecodeAddr(JNIEnv *env, jclass clazz, jlong addr) { + Memarea *memarea = (Memarea *) addr; + IMAGE *image = createFromAddr(memarea->buffer, memarea->size); + free(memarea); + return (jlong) image; +} + JNIEXPORT jint JNICALL Java_com_hippo_image_Image_nativeGetFormat(JNIEnv *env, jclass clazz, jlong native_ptr) { return ((IMAGE *) native_ptr)->isAnimated; diff --git a/app/src/main/cpp/main.c b/app/src/main/cpp/main.c index 220219958..cc540335a 100644 --- a/app/src/main/cpp/main.c +++ b/app/src/main/cpp/main.c @@ -23,8 +23,6 @@ #include #include -#include - #include "image.h" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { @@ -38,8 +36,6 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_ERR; } - android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE); - return JNI_VERSION_1_6; } diff --git a/app/src/main/java/com/hippo/UriArchiveAccessor.java b/app/src/main/java/com/hippo/UriArchiveAccessor.java index e6ebeac97..d913922e4 100644 --- a/app/src/main/java/com/hippo/UriArchiveAccessor.java +++ b/app/src/main/java/com/hippo/UriArchiveAccessor.java @@ -21,6 +21,10 @@ package com.hippo; import android.content.Context; import android.net.Uri; import android.os.ParcelFileDescriptor; +import android.system.Os; +import android.system.OsConstants; + +import java.io.FileDescriptor; public class UriArchiveAccessor { ParcelFileDescriptor pfd; @@ -39,7 +43,7 @@ public class UriArchiveAccessor { private native int openArchive(int fd, long size); - public native int extractToMemfd(int index); + public native long extracttoOutputStream(int index); public native boolean needPassword(); diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/ArchiveGalleryProvider.java b/app/src/main/java/com/hippo/ehviewer/gallery/ArchiveGalleryProvider.java index e8556b865..e0e4785f5 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/ArchiveGalleryProvider.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/ArchiveGalleryProvider.java @@ -49,7 +49,7 @@ public class ArchiveGalleryProvider extends GalleryProvider2 { private final UriArchiveAccessor archiveAccessor; private final Stack requests = new Stack<>(); private final AtomicInteger extractingIndex = new AtomicInteger(GalleryPageView.INVALID_INDEX); - private final LinkedHashMap streams = new LinkedHashMap<>(); + private final LinkedHashMap streams = new LinkedHashMap<>(); private final AtomicInteger decodingIndex = new AtomicInteger(GalleryPageView.INVALID_INDEX); private Thread archiveThread; private Thread decodeThread; @@ -255,10 +255,10 @@ public class ArchiveGalleryProvider extends GalleryProvider2 { } } - int fd = archiveAccessor.extractToMemfd(index); + long addr = archiveAccessor.extracttoOutputStream(index); synchronized (streams) { - streams.put(index, fd); + streams.put(index, addr); streams.notify(); } } @@ -270,7 +270,7 @@ public class ArchiveGalleryProvider extends GalleryProvider2 { public void run() { while (!Thread.currentThread().isInterrupted()) { int index; - int fd; + Long addr; synchronized (streams) { if (streams.isEmpty()) { try { @@ -282,16 +282,16 @@ public class ArchiveGalleryProvider extends GalleryProvider2 { continue; } - Iterator> iterator = streams.entrySet().iterator(); - Map.Entry entry = iterator.next(); + Iterator> iterator = streams.entrySet().iterator(); + Map.Entry entry = iterator.next(); iterator.remove(); index = entry.getKey(); - fd = entry.getValue(); + addr = entry.getValue(); decodingIndex.lazySet(index); } try { - Image image = Image.decode(fd, false); + Image image = Image.decodeAddr(addr, true); if (image != null) { notifyPageSucceed(index, image); } else { diff --git a/app/src/main/java/com/hippo/image/Image.java b/app/src/main/java/com/hippo/image/Image.java index 11722b932..772ef2f4f 100644 --- a/app/src/main/java/com/hippo/image/Image.java +++ b/app/src/main/java/com/hippo/image/Image.java @@ -71,6 +71,14 @@ public final class Image { return newFromAddr(nativeDecodeFdInt(fd)); } + /** + * Decode image from {@code InputStream} + */ + @Nullable + public static Image decodeAddr(Long addr, boolean partially) { + return newFromAddr(nativeDecodeAddr(addr)); + } + /** * Create a plain image from Bitmap */ @@ -91,6 +99,8 @@ public final class Image { private static native long nativeDecodeFdInt(int fd); + private static native long nativeDecodeAddr(long addr); + private static native long nativeCreate(Bitmap bitmap); private static native void nativeRender(long nativePtr,