diff options
| -rwxr-xr-x | api/current.txt | 1 | ||||
| -rw-r--r-- | graphics/java/android/graphics/ImageDecoder.java | 90 |
2 files changed, 71 insertions, 20 deletions
diff --git a/api/current.txt b/api/current.txt index 5a2667121bb4..51a5e79d6331 100755 --- a/api/current.txt +++ b/api/current.txt @@ -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; diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index 6ce66bdc925b..009e042f74a7 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -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. */ @@ -971,6 +1000,27 @@ public final class ImageDecoder implements AutoCloseable { } /** + * 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. * * <p>This takes an input that functions like |