Merge "Use openPipeHelper() for streaming IconsContentProvider data." into rvc-dev am: 100ae78d72

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

Change-Id: Icddb0e7bb1d58cd9e4ff788817accc76c635427e
This commit is contained in:
TreeHugger Robot
2020-06-30 10:16:10 +00:00
committed by Automerger Merge Worker
2 changed files with 44 additions and 27 deletions

View File

@@ -27,6 +27,7 @@ import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor.AutoCloseOutputStream; import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.server.textclassifier.IconsUriHelper.ResourceInfo; 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.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Arrays;
/** /**
* A content provider that is used to access icons returned from the TextClassifier service. * 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 { public final class IconsContentProvider extends ContentProvider {
private static final String TAG = "IconsContentProvider"; 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 @Override
public ParcelFileDescriptor openFile(Uri uri, String mode) { public ParcelFileDescriptor openFile(Uri uri, String mode) {
try { final ResourceInfo res = IconsUriHelper.getInstance().getResourceInfo(uri);
final ResourceInfo res = IconsUriHelper.getInstance().getResourceInfo(uri); if (res == null) {
final Drawable drawable = Icon.createWithResource(res.packageName, res.id) Log.e(TAG, "No icon found for uri: " + uri);
.loadDrawableAsUser(getContext(), UserHandle.getCallingUserId()); return null;
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;
}
} 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; return null;
} }
/** private static Bitmap getBitmap(Drawable drawable) {
* Returns the bitmap data for the specified drawable.
*/
@VisibleForTesting
public static byte[] getBitmapData(Drawable drawable) {
if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
throw new IllegalStateException("The icon is zero-sized"); 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.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas); drawable.draw(canvas);
final ByteArrayOutputStream stream = new ByteArrayOutputStream(); return bitmap;
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); }
final byte[] byteArray = stream.toByteArray();
bitmap.recycle(); /**
return byteArray; * 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 @Override
public String getType(Uri uri) { public String getType(Uri uri) {
return "image/png"; return MIME_TYPE;
} }
@Override @Override

View File

@@ -50,8 +50,7 @@ public final class IconsContentProviderTest {
final Drawable actual = Icon.createWithContentUri(uri).loadDrawable(context); final Drawable actual = Icon.createWithContentUri(uri).loadDrawable(context);
assertThat(actual).isNotNull(); assertThat(actual).isNotNull();
assertThat(IconsContentProvider.getBitmapData(actual)) assertThat(IconsContentProvider.sameIcon(actual, expected)).isTrue();
.isEqualTo(IconsContentProvider.getBitmapData(expected));
} }
@Test @Test