From 6aec452f91868c42b9dee156e9d2e22d1a1e5566 Mon Sep 17 00:00:00 2001 From: Adam Lesinski Date: Mon, 27 Jun 2016 12:30:02 -0700 Subject: [PATCH] Fix AttributeCache AttributeCache relied on the frequency of the garbage collector to clean up resource references. The garbage collector seems to have gotten faster and the cache essentially doesn't cache anything. Switch to using an LRU cache that holds strong references to a finite set of Resources. This should be very small, just to keep the few working apps involved in app switches in memory. Bug:29405575 Change-Id: I64b34742c820f1e7872061a574e6cf1a76887149 --- .../com/android/server/AttributeCache.java | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/AttributeCache.java b/services/core/java/com/android/server/AttributeCache.java index 57f18c086c56c..58ec836547a7d 100644 --- a/services/core/java/com/android/server/AttributeCache.java +++ b/services/core/java/com/android/server/AttributeCache.java @@ -25,23 +25,24 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.os.UserHandle; import android.util.ArrayMap; +import android.util.LruCache; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; -import java.lang.ref.WeakReference; - /** * TODO: This should be better integrated into the system so it doesn't need * special calls from the activity manager to clear it. */ public final class AttributeCache { + private static final int CACHE_SIZE = 4; private static AttributeCache sInstance = null; private final Context mContext; @GuardedBy("this") - private final ArrayMap> mPackages = new ArrayMap<>(); + private final LruCache mPackages = new LruCache<>(CACHE_SIZE); + @GuardedBy("this") private final Configuration mConfiguration = new Configuration(); @@ -86,15 +87,12 @@ public final class AttributeCache { public void removePackage(String packageName) { synchronized (this) { - final WeakReference ref = mPackages.remove(packageName); - final Package pkg = (ref != null) ? ref.get() : null; + final Package pkg = mPackages.remove(packageName); if (pkg != null) { - if (pkg.mMap != null) { - for (int i = 0; i < pkg.mMap.size(); i++) { - final ArrayMap map = pkg.mMap.valueAt(i); - for (int j = 0; j < map.size(); j++) { - map.valueAt(j).recycle(); - } + for (int i = 0; i < pkg.mMap.size(); i++) { + final ArrayMap map = pkg.mMap.valueAt(i); + for (int j = 0; j < map.size(); j++) { + map.valueAt(j).recycle(); } } @@ -113,15 +111,14 @@ public final class AttributeCache { // The configurations being masked out are ones that commonly // change so we don't want flushing the cache... all others // will flush the cache. - mPackages.clear(); + mPackages.evictAll(); } } } public Entry get(String packageName, int resId, int[] styleable, int userId) { synchronized (this) { - WeakReference ref = mPackages.get(packageName); - Package pkg = (ref != null) ? ref.get() : null; + Package pkg = mPackages.get(packageName); ArrayMap map = null; Entry ent = null; if (pkg != null) { @@ -144,7 +141,7 @@ public final class AttributeCache { return null; } pkg = new Package(context); - mPackages.put(packageName, new WeakReference<>(pkg)); + mPackages.put(packageName, pkg); } if (map == null) {