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

Commit 299b0e4b authored by Leon Scroggins's avatar Leon Scroggins Committed by Android (Google) Code Review
Browse files

Merge "Reland "Call ImageDecoder directly in ResourcesImpl""

parents 1cfc06a1 513031d1
Loading
Loading
Loading
Loading
+24 −2
Original line number Diff line number Diff line
@@ -27,9 +27,11 @@ import android.annotation.StyleRes;
import android.annotation.StyleableRes;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
import android.content.res.AssetManager.AssetInputStream;
import android.content.res.Configuration.NativeConfig;
import android.content.res.Resources.NotFoundException;
import android.graphics.Bitmap;
import android.graphics.ImageDecoder;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -751,6 +753,26 @@ public class ResourcesImpl {
        return true;
    }

    /**
     * Loads a Drawable from an encoded image stream, or null.
     *
     * This call will handle closing ais.
     */
    private Drawable decodeImageDrawable(@NonNull AssetInputStream ais,
            @NonNull Resources wrapper, @NonNull TypedValue value) {
        ImageDecoder.Source src = new ImageDecoder.AssetInputStreamSource(ais,
                            wrapper, value);
        try {
            return ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
                decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
            });
        } catch (IOException ioe) {
            // This is okay. This may be something that ImageDecoder does not
            // support, like SVG.
            return null;
        }
    }

    /**
     * Loads a drawable from XML or resources stream.
     */
@@ -811,8 +833,8 @@ public class ResourcesImpl {
                } else {
                    final InputStream is = mAssets.openNonAsset(
                            value.assetCookie, file, AssetManager.ACCESS_STREAMING);
                    dr = Drawable.createFromResourceStream(wrapper, value, is, file, null);
                    is.close();
                    AssetInputStream ais = (AssetInputStream) is;
                    dr = decodeImageDrawable(ais, wrapper, value);
                }
            } finally {
                stack.pop();
+59 −6
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ import android.annotation.Nullable;
import android.annotation.RawRes;
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;
import android.graphics.drawable.Drawable;
@@ -263,6 +263,63 @@ public final class ImageDecoder implements AutoCloseable {
        }
    }

    /**
     * Takes ownership of the AssetInputStream.
     *
     * @hide
     */
    public static class AssetInputStreamSource extends Source {
        public AssetInputStreamSource(@NonNull AssetInputStream ais,
                @NonNull Resources res, @NonNull TypedValue value) {
            mAssetInputStream = ais;
            mResources = res;

            if (value.density == TypedValue.DENSITY_DEFAULT) {
                mDensity = DisplayMetrics.DENSITY_DEFAULT;
            } else if (value.density != TypedValue.DENSITY_NONE) {
                mDensity = value.density;
            } else {
                mDensity = Bitmap.DENSITY_NONE;
            }
        }

        private AssetInputStream mAssetInputStream;
        private final Resources  mResources;
        private final int        mDensity;

        @Override
        public Resources getResources() { return mResources; }

        @Override
        public int getDensity() {
            return mDensity;
        }

        @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;
            }
        }
    }

    private static class ResourceSource extends Source {
        ResourceSource(@NonNull Resources res, int resId) {
            mResources = res;
@@ -296,11 +353,7 @@ public final class ImageDecoder implements AutoCloseable {
                    mResDensity = value.density;
                }

                if (!(is instanceof AssetManager.AssetInputStream)) {
                    // This should never happen.
                    throw new RuntimeException("Resource is not an asset?");
                }
                long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
                long asset = ((AssetInputStream) is).getNativeAsset();
                decoder = nCreate(asset);
            } finally {
                if (decoder == null) {