From 21a8baaeb1d88161f476898de4a9346dd454ec7e Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Tue, 12 Apr 2022 17:04:56 -0700 Subject: [PATCH] RemoteViews: make bitmaps immutable Because mutability is propagated across Parcel and Binder, any mutable Bitmaps passed to RemoteViews will end up mutable on the other side even though those Bitmaps can't be modified from the RemoteViews recipient. Make all Bitmaps passed to RemoteViews immutable in order to ensure that they can be sent without additional copies instead of the one ashmem object. Test: TH, RemoteViews work for widgets Bug: 227920378 Change-Id: I477e7132f9ff78333c1eda56b9d0fc6ac520abd0 --- core/java/android/widget/RemoteViews.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index fbad38f27a23b..2879cd888d2d8 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -1588,24 +1588,33 @@ public class RemoteViews implements Parcelable, Filter { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) ArrayList mBitmaps; + SparseIntArray mBitmapHashes; int mBitmapMemory = -1; public BitmapCache() { mBitmaps = new ArrayList<>(); + mBitmapHashes = new SparseIntArray(); } public BitmapCache(Parcel source) { mBitmaps = source.createTypedArrayList(Bitmap.CREATOR); + mBitmapHashes = source.readSparseIntArray(); } public int getBitmapId(Bitmap b) { if (b == null) { return -1; } else { - if (mBitmaps.contains(b)) { - return mBitmaps.indexOf(b); + int hash = b.hashCode(); + int hashId = mBitmapHashes.get(hash, -1); + if (hashId != -1) { + return hashId; } else { + if (b.isMutable()) { + b = b.asShared(); + } mBitmaps.add(b); + mBitmapHashes.put(mBitmaps.size() - 1, hash); mBitmapMemory = -1; return (mBitmaps.size() - 1); } @@ -1616,13 +1625,13 @@ public class RemoteViews implements Parcelable, Filter { public Bitmap getBitmapForId(int id) { if (id == -1 || id >= mBitmaps.size()) { return null; - } else { - return mBitmaps.get(id); } + return mBitmaps.get(id); } public void writeBitmapsToParcel(Parcel dest, int flags) { dest.writeTypedList(mBitmaps, flags); + dest.writeSparseIntArray(mBitmapHashes); } public int getBitmapMemory() {