diff --git a/api/current.txt b/api/current.txt index e0c45e05c2754..414491cd57b7d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -13612,6 +13612,7 @@ package android.graphics { method public void close(); method public static android.graphics.ImageDecoder.Source createSource(android.content.res.Resources, int); method public static android.graphics.ImageDecoder.Source createSource(android.content.ContentResolver, android.net.Uri); + 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.Bitmap decodeBitmap(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 8196d6695d0c5..5e81c377d41db 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -26,6 +26,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ContentResolver; import android.content.res.AssetFileDescriptor; +import android.content.res.AssetManager; import android.content.res.AssetManager.AssetInputStream; import android.content.res.Resources; import android.graphics.drawable.AnimatedImageDrawable; @@ -294,25 +295,13 @@ public final class ImageDecoder implements AutoCloseable { @Override public ImageDecoder createImageDecoder() throws IOException { - ImageDecoder decoder = null; synchronized (this) { if (mAssetInputStream == null) { throw new IOException("Cannot reuse AssetInputStreamSource"); } AssetInputStream ais = mAssetInputStream; mAssetInputStream = null; - try { - long asset = ais.getNativeAsset(); - decoder = nCreate(asset); - } finally { - if (decoder == null) { - IoUtils.closeQuietly(ais); - } else { - decoder.mInputStream = ais; - decoder.mOwnsInputStream = true; - } - } - return decoder; + return createFromAsset(ais); } } } @@ -336,31 +325,53 @@ public final class ImageDecoder implements AutoCloseable { @Override public ImageDecoder createImageDecoder() throws IOException { - // This is just used in order to access the underlying Asset and - // keep it alive. FIXME: Can we skip creating this object? - InputStream is = null; - ImageDecoder decoder = null; TypedValue value = new TypedValue(); - try { - is = mResources.openRawResource(mResId, value); + // This is just used in order to access the underlying Asset and + // keep it alive. + InputStream is = mResources.openRawResource(mResId, value); - if (value.density == TypedValue.DENSITY_DEFAULT) { - mResDensity = DisplayMetrics.DENSITY_DEFAULT; - } else if (value.density != TypedValue.DENSITY_NONE) { - mResDensity = value.density; - } - - long asset = ((AssetInputStream) is).getNativeAsset(); - decoder = nCreate(asset); - } finally { - if (decoder == null) { - IoUtils.closeQuietly(is); - } else { - decoder.mInputStream = is; - decoder.mOwnsInputStream = true; - } + if (value.density == TypedValue.DENSITY_DEFAULT) { + mResDensity = DisplayMetrics.DENSITY_DEFAULT; + } else if (value.density != TypedValue.DENSITY_NONE) { + mResDensity = value.density; } - return decoder; + + return createFromAsset((AssetInputStream) is); + } + } + + /** + * ImageDecoder will own the AssetInputStream. + */ + private static ImageDecoder createFromAsset(AssetInputStream ais) throws IOException { + ImageDecoder decoder = null; + try { + long asset = ais.getNativeAsset(); + decoder = nCreate(asset); + } finally { + if (decoder == null) { + IoUtils.closeQuietly(ais); + } else { + decoder.mInputStream = ais; + decoder.mOwnsInputStream = true; + } + } + return decoder; + } + + private static class AssetSource extends Source { + AssetSource(@NonNull AssetManager assets, @NonNull String fileName) { + mAssets = assets; + mFileName = fileName; + } + + private final AssetManager mAssets; + private final String mFileName; + + @Override + public ImageDecoder createImageDecoder() throws IOException { + InputStream is = mAssets.open(mFileName); + return createFromAsset((AssetInputStream) is); } } @@ -580,6 +591,14 @@ public final class ImageDecoder implements AutoCloseable { return new ContentResolverSource(cr, uri, res); } + /** + * Create a new {@link Source} from a file in the "assets" directory. + */ + @NonNull + public static Source createSource(@NonNull AssetManager assets, @NonNull String fileName) { + return new AssetSource(assets, fileName); + } + /** * Create a new {@link Source} from a byte array. *