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

Commit 8ad9ef4a authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Support custom creation of AFD for ImageDecoder."

parents 42f4e79d 685c4aef
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -13757,6 +13757,7 @@ package android.graphics {
    method public static android.graphics.ImageDecoder.Source createSource(android.content.res.AssetManager, java.lang.String);
    method public static android.graphics.ImageDecoder.Source createSource(java.nio.ByteBuffer);
    method public static android.graphics.ImageDecoder.Source createSource(java.io.File);
    method public static android.graphics.ImageDecoder.Source createSource(java.util.concurrent.Callable<android.content.res.AssetFileDescriptor>);
    method public static android.graphics.Bitmap decodeBitmap(android.graphics.ImageDecoder.Source, android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException;
    method public static android.graphics.Bitmap decodeBitmap(android.graphics.ImageDecoder.Source) throws java.io.IOException;
    method public static android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source, android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException;
+70 −20
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Retention;
import java.nio.ByteBuffer;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;

/**
@@ -283,26 +284,7 @@ public final class ImageDecoder implements AutoCloseable {

                return createFromStream(is, true, this);
            }

            final FileDescriptor fd = assetFd.getFileDescriptor();
            final long offset = assetFd.getStartOffset();

            ImageDecoder decoder = null;
            try {
                try {
                    Os.lseek(fd, offset, SEEK_SET);
                    decoder = nCreate(fd, this);
                } catch (ErrnoException e) {
                    decoder = createFromStream(new FileInputStream(fd), true, this);
                }
            } finally {
                if (decoder == null) {
                    IoUtils.closeQuietly(assetFd);
                } else {
                    decoder.mAssetFd = assetFd;
                }
            }
            return decoder;
            return createFromAssetFileDescriptor(assetFd, this);
        }
    }

@@ -354,6 +336,30 @@ public final class ImageDecoder implements AutoCloseable {
        return decoder;
    }

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

        ImageDecoder decoder = null;
        try {
            try {
                Os.lseek(fd, offset, SEEK_SET);
                decoder = nCreate(fd, source);
            } catch (ErrnoException e) {
                decoder = createFromStream(new FileInputStream(fd), true, source);
            }
        } finally {
            if (decoder == null) {
                IoUtils.closeQuietly(assetFd);
            } else {
                decoder.mAssetFd = assetFd;
            }
        }
        return decoder;
    }

    /**
     * For backwards compatibility, this does *not* close the InputStream.
     *
@@ -528,6 +534,29 @@ public final class ImageDecoder implements AutoCloseable {
        }
    }

    private static class CallableSource extends Source {
        CallableSource(@NonNull Callable<AssetFileDescriptor> callable) {
            mCallable = callable;
        }

        private final Callable<AssetFileDescriptor> mCallable;

        @Override
        public ImageDecoder createImageDecoder() throws IOException {
            AssetFileDescriptor assetFd = null;
            try {
                assetFd = mCallable.call();
            } catch (Exception e) {
                if (e instanceof IOException) {
                    throw (IOException) e;
                } else {
                    throw new IOException(e);
                }
            }
            return createFromAssetFileDescriptor(assetFd, this);
        }
    }

    /**
     *  Information about an encoded image.
     */
@@ -970,6 +999,27 @@ public final class ImageDecoder implements AutoCloseable {
        return new FileSource(file);
    }

    /**
     * Create a new {@link Source Source} from a {@link Callable} that returns a
     * new {@link AssetFileDescriptor} for each request. This provides control
     * over how the {@link AssetFileDescriptor} is created, such as passing
     * options into {@link ContentResolver#openTypedAssetFileDescriptor}, or
     * enabling use of a {@link android.os.CancellationSignal}.
     * <p>
     * It's important for the given {@link Callable} to return a new, unique
     * {@link AssetFileDescriptor} for each invocation, to support reuse of the
     * returned {@link Source Source}.
     *
     * @return a new Source object, which can be passed to
     *         {@link #decodeDrawable decodeDrawable} or {@link #decodeBitmap
     *         decodeBitmap}.
     */
    @AnyThread
    @NonNull
    public static Source createSource(@NonNull Callable<AssetFileDescriptor> callable) {
        return new CallableSource(callable);
    }

    /**
     *  Return the width and height of a given sample size.
     *