Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f333b2ca authored by Chong Zhang's avatar Chong Zhang Committed by Android (Google) Code Review
Browse files

Merge "Prefer animation in ImageDecoder.decodeDrawable"

parents ff31612e cba27925
Loading
Loading
Loading
Loading
+26 −20
Original line number Diff line number Diff line
@@ -78,14 +78,18 @@ static jobject throw_exception(JNIEnv* env, ImageDecoder::Error error, const cha
    return nullptr;
}

static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream, jobject source) {
static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream,
        jobject source, jboolean preferAnimation) {
    if (!stream.get()) {
        return throw_exception(env, ImageDecoder::kSourceMalformedData, "Failed to create a stream",
                               nullptr, source);
    }
    std::unique_ptr<ImageDecoder> decoder(new ImageDecoder);
    SkCodec::Result result;
    auto codec = SkCodec::MakeFromStream(std::move(stream), &result, decoder->mPeeker.get());
    auto codec = SkCodec::MakeFromStream(
            std::move(stream), &result, decoder->mPeeker.get(),
            preferAnimation ? SkCodec::SelectionPolicy::kPreferAnimation
                            : SkCodec::SelectionPolicy::kPreferStillImage);
    if (jthrowable jexception = get_and_clear_exception(env)) {
        return throw_exception(env, ImageDecoder::kSourceException, "", jexception, source);
    }
@@ -124,7 +128,7 @@ static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream, jobj
}

static jobject ImageDecoder_nCreateFd(JNIEnv* env, jobject /*clazz*/,
        jobject fileDescriptor, jobject source) {
        jobject fileDescriptor, jboolean preferAnimation, jobject source) {
    int descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor);

    struct stat fdStat;
@@ -142,11 +146,11 @@ static jobject ImageDecoder_nCreateFd(JNIEnv* env, jobject /*clazz*/,
    }

    std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file));
    return native_create(env, std::move(fileStream), source);
    return native_create(env, std::move(fileStream), source, preferAnimation);
}

static jobject ImageDecoder_nCreateInputStream(JNIEnv* env, jobject /*clazz*/,
        jobject is, jbyteArray storage, jobject source) {
        jobject is, jbyteArray storage, jboolean preferAnimation, jobject source) {
    std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage, false));

    if (!stream.get()) {
@@ -157,31 +161,33 @@ static jobject ImageDecoder_nCreateInputStream(JNIEnv* env, jobject /*clazz*/,
    std::unique_ptr<SkStream> bufferedStream(
        SkFrontBufferedStream::Make(std::move(stream),
        SkCodec::MinBufferedBytesNeeded()));
    return native_create(env, std::move(bufferedStream), source);
    return native_create(env, std::move(bufferedStream), source, preferAnimation);
}

static jobject ImageDecoder_nCreateAsset(JNIEnv* env, jobject /*clazz*/, jlong assetPtr,
                                         jobject source) {
static jobject ImageDecoder_nCreateAsset(JNIEnv* env, jobject /*clazz*/,
        jlong assetPtr, jboolean preferAnimation, jobject source) {
    Asset* asset = reinterpret_cast<Asset*>(assetPtr);
    std::unique_ptr<SkStream> stream(new AssetStreamAdaptor(asset));
    return native_create(env, std::move(stream), source);
    return native_create(env, std::move(stream), source, preferAnimation);
}

static jobject ImageDecoder_nCreateByteBuffer(JNIEnv* env, jobject /*clazz*/, jobject jbyteBuffer,
                                              jint initialPosition, jint limit, jobject source) {
static jobject ImageDecoder_nCreateByteBuffer(JNIEnv* env, jobject /*clazz*/,
        jobject jbyteBuffer, jint initialPosition, jint limit,
        jboolean preferAnimation, jobject source) {
    std::unique_ptr<SkStream> stream = CreateByteBufferStreamAdaptor(env, jbyteBuffer,
                                                                     initialPosition, limit);
    if (!stream) {
        return throw_exception(env, ImageDecoder::kSourceMalformedData, "Failed to read ByteBuffer",
                               nullptr, source);
    }
    return native_create(env, std::move(stream), source);
    return native_create(env, std::move(stream), source, preferAnimation);
}

static jobject ImageDecoder_nCreateByteArray(JNIEnv* env, jobject /*clazz*/, jbyteArray byteArray,
                                             jint offset, jint length, jobject source) {
static jobject ImageDecoder_nCreateByteArray(JNIEnv* env, jobject /*clazz*/,
        jbyteArray byteArray, jint offset, jint length,
        jboolean preferAnimation, jobject source) {
    std::unique_ptr<SkStream> stream(CreateByteArrayStreamAdaptor(env, byteArray, offset, length));
    return native_create(env, std::move(stream), source);
    return native_create(env, std::move(stream), source, preferAnimation);
}

jint postProcessAndRelease(JNIEnv* env, jobject jimageDecoder, std::unique_ptr<Canvas> canvas) {
@@ -514,11 +520,11 @@ static jobject ImageDecoder_nGetColorSpace(JNIEnv* env, jobject /*clazz*/, jlong
}

static const JNINativeMethod gImageDecoderMethods[] = {
    { "nCreate",        "(JLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;",    (void*) ImageDecoder_nCreateAsset },
    { "nCreate",        "(Ljava/nio/ByteBuffer;IILandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteBuffer },
    { "nCreate",        "([BIILandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteArray },
    { "nCreate",        "(Ljava/io/InputStream;[BLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateInputStream },
    { "nCreate",        "(Ljava/io/FileDescriptor;Landroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateFd },
    { "nCreate",        "(JZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;",    (void*) ImageDecoder_nCreateAsset },
    { "nCreate",        "(Ljava/nio/ByteBuffer;IIZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteBuffer },
    { "nCreate",        "([BIIZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteArray },
    { "nCreate",        "(Ljava/io/InputStream;[BZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateInputStream },
    { "nCreate",        "(Ljava/io/FileDescriptor;ZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateFd },
    { "nDecodeBitmap",  "(JLandroid/graphics/ImageDecoder;ZIILandroid/graphics/Rect;ZIZZZJZ)Landroid/graphics/Bitmap;",
                                                                 (void*) ImageDecoder_nDecodeBitmap },
    { "nGetSampledSize","(JI)Landroid/util/Size;",               (void*) ImageDecoder_nGetSampledSize },
+41 −39
Original line number Diff line number Diff line
@@ -214,7 +214,7 @@ public final class ImageDecoder implements AutoCloseable {

        /* @hide */
        @NonNull
        abstract ImageDecoder createImageDecoder() throws IOException;
        abstract ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException;
    };

    private static class ByteArraySource extends Source {
@@ -228,8 +228,8 @@ public final class ImageDecoder implements AutoCloseable {
        private final int    mLength;

        @Override
        public ImageDecoder createImageDecoder() throws IOException {
            return nCreate(mData, mOffset, mLength, this);
        public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException {
            return nCreate(mData, mOffset, mLength, preferAnimation, this);
        }
    }

@@ -240,14 +240,14 @@ public final class ImageDecoder implements AutoCloseable {
        private final ByteBuffer mBuffer;

        @Override
        public ImageDecoder createImageDecoder() throws IOException {
        public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException {
            if (!mBuffer.isDirect() && mBuffer.hasArray()) {
                int offset = mBuffer.arrayOffset() + mBuffer.position();
                int length = mBuffer.limit() - mBuffer.position();
                return nCreate(mBuffer.array(), offset, length, this);
                return nCreate(mBuffer.array(), offset, length, preferAnimation, this);
            }
            ByteBuffer buffer = mBuffer.slice();
            return nCreate(buffer, buffer.position(), buffer.limit(), this);
            return nCreate(buffer, buffer.position(), buffer.limit(), preferAnimation, this);
        }
    }

@@ -267,7 +267,7 @@ public final class ImageDecoder implements AutoCloseable {
        Resources getResources() { return mResources; }

        @Override
        public ImageDecoder createImageDecoder() throws IOException {
        public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException {
            AssetFileDescriptor assetFd = null;
            try {
                if (mUri.getScheme() == ContentResolver.SCHEME_CONTENT) {
@@ -284,26 +284,26 @@ public final class ImageDecoder implements AutoCloseable {
                    throw new FileNotFoundException(mUri.toString());
                }

                return createFromStream(is, true, this);
                return createFromStream(is, true, preferAnimation, this);
            }
            return createFromAssetFileDescriptor(assetFd, this);
            return createFromAssetFileDescriptor(assetFd, preferAnimation, this);
        }
    }

    @NonNull
    private static ImageDecoder createFromFile(@NonNull File file,
            @NonNull Source source) throws IOException {
            boolean preferAnimation, @NonNull Source source) throws IOException {
        FileInputStream stream = new FileInputStream(file);
        FileDescriptor fd = stream.getFD();
        try {
            Os.lseek(fd, 0, SEEK_CUR);
        } catch (ErrnoException e) {
            return createFromStream(stream, true, source);
            return createFromStream(stream, true, preferAnimation, source);
        }

        ImageDecoder decoder = null;
        try {
            decoder = nCreate(fd, source);
            decoder = nCreate(fd, preferAnimation, source);
        } finally {
            if (decoder == null) {
                IoUtils.closeQuietly(stream);
@@ -317,12 +317,12 @@ public final class ImageDecoder implements AutoCloseable {

    @NonNull
    private static ImageDecoder createFromStream(@NonNull InputStream is,
            boolean closeInputStream, Source source) throws IOException {
            boolean closeInputStream, boolean preferAnimation, Source source) throws IOException {
        // Arbitrary size matches BitmapFactory.
        byte[] storage = new byte[16 * 1024];
        ImageDecoder decoder = null;
        try {
            decoder = nCreate(is, storage, source);
            decoder = nCreate(is, storage, preferAnimation, source);
        } finally {
            if (decoder == null) {
                if (closeInputStream) {
@@ -340,7 +340,7 @@ public final class ImageDecoder implements AutoCloseable {

    @NonNull
    private static ImageDecoder createFromAssetFileDescriptor(@NonNull AssetFileDescriptor assetFd,
            Source source) throws IOException {
            boolean preferAnimation, Source source) throws IOException {
        final FileDescriptor fd = assetFd.getFileDescriptor();
        final long offset = assetFd.getStartOffset();

@@ -348,9 +348,9 @@ public final class ImageDecoder implements AutoCloseable {
        try {
            try {
                Os.lseek(fd, offset, SEEK_SET);
                decoder = nCreate(fd, source);
                decoder = nCreate(fd, preferAnimation, source);
            } catch (ErrnoException e) {
                decoder = createFromStream(new FileInputStream(fd), true, source);
                decoder = createFromStream(new FileInputStream(fd), true, preferAnimation, source);
            }
        } finally {
            if (decoder == null) {
@@ -388,7 +388,7 @@ public final class ImageDecoder implements AutoCloseable {
        public int getDensity() { return mInputDensity; }

        @Override
        public ImageDecoder createImageDecoder() throws IOException {
        public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException {

            synchronized (this) {
                if (mInputStream == null) {
@@ -396,7 +396,7 @@ public final class ImageDecoder implements AutoCloseable {
                }
                InputStream is = mInputStream;
                mInputStream = null;
                return createFromStream(is, false, this);
                return createFromStream(is, false, preferAnimation, this);
            }
        }
    }
@@ -434,14 +434,14 @@ public final class ImageDecoder implements AutoCloseable {
        }

        @Override
        public ImageDecoder createImageDecoder() throws IOException {
        public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException {
            synchronized (this) {
                if (mAssetInputStream == null) {
                    throw new IOException("Cannot reuse AssetInputStreamSource");
                }
                AssetInputStream ais = mAssetInputStream;
                mAssetInputStream = null;
                return createFromAsset(ais, this);
                return createFromAsset(ais, preferAnimation, this);
            }
        }
    }
@@ -469,7 +469,7 @@ public final class ImageDecoder implements AutoCloseable {
        }

        @Override
        public ImageDecoder createImageDecoder() throws IOException {
        public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException {
            TypedValue value = new TypedValue();
            // This is just used in order to access the underlying Asset and
            // keep it alive.
@@ -483,7 +483,7 @@ public final class ImageDecoder implements AutoCloseable {
                }
            }

            return createFromAsset((AssetInputStream) is, this);
            return createFromAsset((AssetInputStream) is, preferAnimation, this);
        }
    }

@@ -491,11 +491,11 @@ public final class ImageDecoder implements AutoCloseable {
     *  ImageDecoder will own the AssetInputStream.
     */
    private static ImageDecoder createFromAsset(AssetInputStream ais,
            Source source) throws IOException {
            boolean preferAnimation, Source source) throws IOException {
        ImageDecoder decoder = null;
        try {
            long asset = ais.getNativeAsset();
            decoder = nCreate(asset, source);
            decoder = nCreate(asset, preferAnimation, source);
        } finally {
            if (decoder == null) {
                IoUtils.closeQuietly(ais);
@@ -517,9 +517,9 @@ public final class ImageDecoder implements AutoCloseable {
        private final String mFileName;

        @Override
        public ImageDecoder createImageDecoder() throws IOException {
        public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException {
            InputStream is = mAssets.open(mFileName);
            return createFromAsset((AssetInputStream) is, this);
            return createFromAsset((AssetInputStream) is, preferAnimation, this);
        }
    }

@@ -531,8 +531,8 @@ public final class ImageDecoder implements AutoCloseable {
        private final File mFile;

        @Override
        public ImageDecoder createImageDecoder() throws IOException {
            return createFromFile(mFile, this);
        public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException {
            return createFromFile(mFile, preferAnimation, this);
        }
    }

@@ -544,7 +544,7 @@ public final class ImageDecoder implements AutoCloseable {
        private final Callable<AssetFileDescriptor> mCallable;

        @Override
        public ImageDecoder createImageDecoder() throws IOException {
        public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException {
            AssetFileDescriptor assetFd = null;
            try {
                assetFd = mCallable.call();
@@ -555,7 +555,7 @@ public final class ImageDecoder implements AutoCloseable {
                    throw new IOException(e);
                }
            }
            return createFromAssetFileDescriptor(assetFd, this);
            return createFromAssetFileDescriptor(assetFd, preferAnimation, this);
        }
    }

@@ -1740,7 +1740,7 @@ public final class ImageDecoder implements AutoCloseable {
    @NonNull
    private static Drawable decodeDrawableImpl(@NonNull Source src,
            @Nullable OnHeaderDecodedListener listener) throws IOException {
        try (ImageDecoder decoder = src.createImageDecoder()) {
        try (ImageDecoder decoder = src.createImageDecoder(true /*preferAnimation*/)) {
            decoder.mSource = src;
            decoder.callHeaderDecoded(listener, src);

@@ -1844,7 +1844,7 @@ public final class ImageDecoder implements AutoCloseable {
    @NonNull
    private static Bitmap decodeBitmapImpl(@NonNull Source src,
            @Nullable OnHeaderDecodedListener listener) throws IOException {
        try (ImageDecoder decoder = src.createImageDecoder()) {
        try (ImageDecoder decoder = src.createImageDecoder(false /*preferAnimation*/)) {
            decoder.mSource = src;
            decoder.callHeaderDecoded(listener, src);

@@ -1971,15 +1971,17 @@ public final class ImageDecoder implements AutoCloseable {
        }
    }

    private static native ImageDecoder nCreate(long asset, Source src) throws IOException;
    private static native ImageDecoder nCreate(ByteBuffer buffer, int position,
                                               int limit, Source src) throws IOException;
    private static native ImageDecoder nCreate(long asset,
            boolean preferAnimation, Source src) throws IOException;
    private static native ImageDecoder nCreate(ByteBuffer buffer, int position, int limit,
            boolean preferAnimation, Source src) throws IOException;
    private static native ImageDecoder nCreate(byte[] data, int offset, int length,
                                               Source src) throws IOException;
            boolean preferAnimation, Source src) throws IOException;
    private static native ImageDecoder nCreate(InputStream is, byte[] storage,
                                               Source src) throws IOException;
            boolean preferAnimation, Source src) throws IOException;
    // The fd must be seekable.
    private static native ImageDecoder nCreate(FileDescriptor fd, Source src) throws IOException;
    private static native ImageDecoder nCreate(FileDescriptor fd,
            boolean preferAnimation, Source src) throws IOException;
    @NonNull
    private static native Bitmap nDecodeBitmap(long nativePtr,
            @NonNull ImageDecoder decoder,