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

Commit 046a99eb authored by Leon Scroggins III's avatar Leon Scroggins III
Browse files

Use ImageDecoder in ImageView.getDrawableFromUri

Bug: 63909536
Test: Existing CTS tests

ImageDecoder will bypass the InputStream if possible, allowing it to be
more efficient. In addition, it handles density scaling differently;
instead of using more RAM to scale the image up, it results in scaling
at draw time.

Change-Id: Ied7c0865a736f9ef0de367299264e18ccc3e0b92
parent ce9bcc49
Loading
Loading
Loading
Loading
+9 −14
Original line number Diff line number Diff line
@@ -23,10 +23,12 @@ import android.annotation.TestApi;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.ImageDecoder;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
@@ -53,7 +55,6 @@ import android.widget.RemoteViews.RemoteView;
import com.android.internal.R;

import java.io.IOException;
import java.io.InputStream;

/**
 * Displays image resources, for example {@link android.graphics.Bitmap}
@@ -946,21 +947,15 @@ public class ImageView extends View {
            }
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
                || ContentResolver.SCHEME_FILE.equals(scheme)) {
            InputStream stream = null;
            try {
                stream = mContext.getContentResolver().openInputStream(uri);
                return Drawable.createFromResourceStream(sCompatUseCorrectStreamDensity
                        ? getResources() : null, null, stream, null);
            } catch (Exception e) {
                Log.w(LOG_TAG, "Unable to open content: " + uri, e);
            } finally {
                if (stream != null) {
                    try {
                        stream.close();
                Resources res = sCompatUseCorrectStreamDensity ? getResources() : null;
                ImageDecoder.Source src = ImageDecoder.createSource(mContext.getContentResolver(),
                        uri, res);
                return ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
                    decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
                });
            } catch (IOException e) {
                        Log.w(LOG_TAG, "Unable to close content: " + uri, e);
                    }
                }
                Log.w(LOG_TAG, "Unable to open content: " + uri, e);
            }
        } else {
            return Drawable.createFromPath(uri.toString());
+20 −3
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ public final class ImageDecoder implements AutoCloseable {
        int getDensity() { return Bitmap.DENSITY_NONE; }

        /* @hide */
        int computeDstDensity() {
        final int computeDstDensity() {
            Resources res = getResources();
            if (res == null) {
                return Bitmap.getDefaultDensity();
@@ -122,13 +122,19 @@ public final class ImageDecoder implements AutoCloseable {
    }

    private static class ContentResolverSource extends Source {
        ContentResolverSource(@NonNull ContentResolver resolver, @NonNull Uri uri) {
        ContentResolverSource(@NonNull ContentResolver resolver, @NonNull Uri uri,
                @Nullable Resources res) {
            mResolver = resolver;
            mUri = uri;
            mResources = res;
        }

        private final ContentResolver mResolver;
        private final Uri mUri;
        private final Resources mResources;

        @Nullable
        Resources getResources() { return mResources; }

        @Override
        public ImageDecoder createImageDecoder() throws IOException {
@@ -511,7 +517,18 @@ public final class ImageDecoder implements AutoCloseable {
    @NonNull
    public static Source createSource(@NonNull ContentResolver cr,
            @NonNull Uri uri) {
        return new ContentResolverSource(cr, uri);
        return new ContentResolverSource(cr, uri, null);
    }

    /**
     * Provide Resources for density scaling.
     *
     * @hide
     */
    @NonNull
    public static Source createSource(@NonNull ContentResolver cr,
            @NonNull Uri uri, @Nullable Resources res) {
        return new ContentResolverSource(cr, uri, res);
    }

    /**