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

Commit 50924336 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Use openPipeHelper() for streaming IconsContentProvider data." into...

Merge "Use openPipeHelper() for streaming IconsContentProvider data." into rvc-dev am: 100ae78d am: 7378cf38 am: 2365d61a

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/12000566

Change-Id: I29bebb557acf5d2885ee6c4975b2413a471b4cba
parents d5b5cd3e 2365d61a
Loading
Loading
Loading
Loading
+42 −24
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.textclassifier.IconsUriHelper.ResourceInfo;
@@ -34,6 +35,7 @@ import com.android.server.textclassifier.IconsUriHelper.ResourceInfo;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;

/**
 * A content provider that is used to access icons returned from the TextClassifier service.
@@ -46,32 +48,40 @@ import java.io.OutputStream;
public final class IconsContentProvider extends ContentProvider {

    private static final String TAG = "IconsContentProvider";
    private static final String MIME_TYPE = "image/png";

    private final PipeDataWriter<Pair<ResourceInfo, Integer>> mWriter =
            (writeSide, uri, mimeType, bundle, args) -> {
                try (OutputStream out = new AutoCloseOutputStream(writeSide)) {
                    final ResourceInfo res = args.first;
                    final int userId = args.second;
                    final Drawable drawable = Icon.createWithResource(res.packageName, res.id)
                                .loadDrawableAsUser(getContext(), userId);
                    getBitmap(drawable).compress(Bitmap.CompressFormat.PNG, 100, out);
                } catch (Exception e) {
                    Log.e(TAG, "Error retrieving icon for uri: " + uri, e);
                }
            };

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) {
        try {
        final ResourceInfo res = IconsUriHelper.getInstance().getResourceInfo(uri);
            final Drawable drawable = Icon.createWithResource(res.packageName, res.id)
                    .loadDrawableAsUser(getContext(), UserHandle.getCallingUserId());
            final byte[] data = getBitmapData(drawable);
            final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
            final ParcelFileDescriptor readSide = pipe[0];
            final ParcelFileDescriptor writeSide = pipe[1];
            try (OutputStream out = new AutoCloseOutputStream(writeSide)) {
                out.write(data);
                return readSide;
        if (res == null) {
            Log.e(TAG, "No icon found for uri: " + uri);
            return null;
        }
        } catch (IOException | RuntimeException e) {
            Log.e(TAG, "Error retrieving icon for uri: " + uri, e);

        try {
            final Pair<ResourceInfo, Integer> args = new Pair(res, UserHandle.getCallingUserId());
            return openPipeHelper(uri, MIME_TYPE, /* bundle= */ null, args, mWriter);
        } catch (IOException e) {
            Log.e(TAG, "Error opening pipe helper for icon at uri: " + uri, e);
        }

        return null;
    }

    /**
     * Returns the bitmap data for the specified drawable.
     */
    @VisibleForTesting
    public static byte[] getBitmapData(Drawable drawable) {
    private static Bitmap getBitmap(Drawable drawable) {
        if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
            throw new IllegalStateException("The icon is zero-sized");
        }
@@ -85,16 +95,24 @@ public final class IconsContentProvider extends ContentProvider {
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        final ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
        final byte[] byteArray = stream.toByteArray();
        bitmap.recycle();
        return byteArray;
        return bitmap;
    }

    /**
     * Returns true if the drawables are considered the same.
     */
    @VisibleForTesting
    public static boolean sameIcon(Drawable one, Drawable two) {
        final ByteArrayOutputStream stream1 = new ByteArrayOutputStream();
        getBitmap(one).compress(Bitmap.CompressFormat.PNG, 100, stream1);
        final ByteArrayOutputStream stream2 = new ByteArrayOutputStream();
        getBitmap(two).compress(Bitmap.CompressFormat.PNG, 100, stream2);
        return Arrays.equals(stream1.toByteArray(), stream2.toByteArray());
    }

    @Override
    public String getType(Uri uri) {
        return "image/png";
        return MIME_TYPE;
    }

    @Override
+1 −2
Original line number Diff line number Diff line
@@ -50,8 +50,7 @@ public final class IconsContentProviderTest {

        final Drawable actual = Icon.createWithContentUri(uri).loadDrawable(context);
        assertThat(actual).isNotNull();
        assertThat(IconsContentProvider.getBitmapData(actual))
                .isEqualTo(IconsContentProvider.getBitmapData(expected));
        assertThat(IconsContentProvider.sameIcon(actual, expected)).isTrue();
    }

    @Test