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

Commit 0368b482 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: 15107230

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

Change-Id: I08ce31d9065913f49dcb6e8c7a92b9b5698204a5
parents 00ffec8e 15107230
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