diff --git a/app/src/main/cpp/archive.c b/app/src/main/cpp/archive.c index 714738554..6e4e12b7d 100644 --- a/app/src/main/cpp/archive.c +++ b/app/src/main/cpp/archive.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -103,6 +104,7 @@ 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; } @@ -143,35 +145,27 @@ Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *_, jobject thiz, jint fd, return r; } -typedef struct Memarea { - void *buffer; - long size; -} Memarea; - -JNIEXPORT jlong JNICALL -Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *_, jobject thiz, jint index) { +JNIEXPORT jint JNICALL +Java_com_hippo_UriArchiveAccessor_extractToMemfd(JNIEnv *_, jobject thiz, jint index) { struct archive_entry *entry; int ret; if (!arc || index < cur_index) { archive_alloc(); cur_index = 0; } - Memarea *memarea = malloc(sizeof(Memarea)); + int memfd = syscall(SYS_memfd_create, "ArchiveMemFD", 0); while (archive_read_next_header(arc, &entry) == ARCHIVE_OK) { if (!filename_is_playable_file(archive_entry_pathname(entry))) continue; if (cur_index++ == index) { - 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?"); + ret = archive_read_data_into_fd(arc, memfd); if (ret < 0) LOGE("%s%s", "Archive read failed:", archive_error_string(arc)); break; } } - return (jlong) memarea; + lseek64(memfd, 0, SEEK_SET); + return memfd; } JNIEXPORT void JNICALL diff --git a/app/src/main/cpp/image.c b/app/src/main/cpp/image.c index 71a6aae72..50174cbe6 100644 --- a/app/src/main/cpp/image.c +++ b/app/src/main/cpp/image.c @@ -19,8 +19,10 @@ #include #include +#include #include +#include #include #include @@ -52,7 +54,6 @@ void image_onUnload() { typedef struct { AImageDecoder *decoder; - void *srcBuffer; size_t stride; int fd; } SOURCE; @@ -72,7 +73,8 @@ static void recycleSource(SOURCE *src) { if (!src) return; AImageDecoder_delete(src->decoder); - free(src->srcBuffer); + if (!android_fdsan_get_owner_tag(src->fd)) + close(src->fd); free(src); } @@ -84,11 +86,6 @@ 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) { @@ -216,17 +213,6 @@ 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; @@ -356,14 +342,6 @@ 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 cc540335a..220219958 100644 --- a/app/src/main/cpp/main.c +++ b/app/src/main/cpp/main.c @@ -23,6 +23,8 @@ #include #include +#include + #include "image.h" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { @@ -36,6 +38,8 @@ 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 d913922e4..e6ebeac97 100644 --- a/app/src/main/java/com/hippo/UriArchiveAccessor.java +++ b/app/src/main/java/com/hippo/UriArchiveAccessor.java @@ -21,10 +21,6 @@ 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; @@ -43,7 +39,7 @@ public class UriArchiveAccessor { private native int openArchive(int fd, long size); - public native long extracttoOutputStream(int index); + public native int extractToMemfd(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 e0e4785f5..e8556b865 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 { } } - long addr = archiveAccessor.extracttoOutputStream(index); + int fd = archiveAccessor.extractToMemfd(index); synchronized (streams) { - streams.put(index, addr); + streams.put(index, fd); streams.notify(); } } @@ -270,7 +270,7 @@ public class ArchiveGalleryProvider extends GalleryProvider2 { public void run() { while (!Thread.currentThread().isInterrupted()) { int index; - Long addr; + int fd; 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(); - addr = entry.getValue(); + fd = entry.getValue(); decodingIndex.lazySet(index); } try { - Image image = Image.decodeAddr(addr, true); + Image image = Image.decode(fd, false); 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 772ef2f4f..11722b932 100644 --- a/app/src/main/java/com/hippo/image/Image.java +++ b/app/src/main/java/com/hippo/image/Image.java @@ -71,14 +71,6 @@ 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 */ @@ -99,8 +91,6 @@ 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,