Skip to content

Commit 1726cf2

Browse files
Romain GuyAndroid Code Review
authored andcommitted
Merge "Fix the problem that color drawable cache key conflicts another drawable one. The cache key of a color drawable resource may be the same as another drawable resource's value."
2 parents 3fb33c7 + c7d9d27 commit 1726cf2

File tree

1 file changed

+69
-38
lines changed

1 file changed

+69
-38
lines changed

core/java/android/content/res/Resources.java

100644100755
Lines changed: 69 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import android.graphics.Movie;
2626
import android.graphics.drawable.Drawable;
2727
import android.graphics.drawable.ColorDrawable;
28+
import android.graphics.drawable.Drawable.ConstantState;
2829
import android.os.Build;
2930
import android.os.Bundle;
3031
import android.os.SystemProperties;
@@ -66,6 +67,8 @@ public class Resources {
6667
= new LongSparseArray<Drawable.ConstantState>();
6768
private static final SparseArray<ColorStateList> mPreloadedColorStateLists
6869
= new SparseArray<ColorStateList>();
70+
private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
71+
= new LongSparseArray<Drawable.ConstantState>();
6972
private static boolean mPreloaded;
7073

7174
/*package*/ final TypedValue mTmpValue = new TypedValue();
@@ -75,6 +78,8 @@ public class Resources {
7578
= new LongSparseArray<WeakReference<Drawable.ConstantState> >();
7679
private final SparseArray<WeakReference<ColorStateList> > mColorStateListCache
7780
= new SparseArray<WeakReference<ColorStateList> >();
81+
private final LongSparseArray<WeakReference<Drawable.ConstantState> > mColorDrawableCache
82+
= new LongSparseArray<WeakReference<Drawable.ConstantState> >();
7883
private boolean mPreloading;
7984

8085
/*package*/ TypedArray mCachedStyledAttributes = null;
@@ -1299,37 +1304,13 @@ public void updateConfiguration(Configuration config,
12991304
(int)(mMetrics.density*160), mConfiguration.keyboard,
13001305
keyboardHidden, mConfiguration.navigation, width, height,
13011306
mConfiguration.screenLayout, mConfiguration.uiMode, sSdkVersion);
1302-
int N = mDrawableCache.size();
1303-
if (DEBUG_CONFIG) {
1304-
Log.d(TAG, "Cleaning up drawables config changes: 0x"
1305-
+ Integer.toHexString(configChanges));
1306-
}
1307-
for (int i=0; i<N; i++) {
1308-
WeakReference<Drawable.ConstantState> ref = mDrawableCache.valueAt(i);
1309-
if (ref != null) {
1310-
Drawable.ConstantState cs = ref.get();
1311-
if (cs != null) {
1312-
if (Configuration.needNewResources(
1313-
configChanges, cs.getChangingConfigurations())) {
1314-
if (DEBUG_CONFIG) {
1315-
Log.d(TAG, "FLUSHING #0x"
1316-
+ Long.toHexString(mDrawableCache.keyAt(i))
1317-
+ " / " + cs + " with changes: 0x"
1318-
+ Integer.toHexString(cs.getChangingConfigurations()));
1319-
}
1320-
mDrawableCache.setValueAt(i, null);
1321-
} else if (DEBUG_CONFIG) {
1322-
Log.d(TAG, "(Keeping #0x"
1323-
+ Long.toHexString(mDrawableCache.keyAt(i))
1324-
+ " / " + cs + " with changes: 0x"
1325-
+ Integer.toHexString(cs.getChangingConfigurations())
1326-
+ ")");
1327-
}
1328-
}
1329-
}
1330-
}
1331-
mDrawableCache.clear();
1307+
1308+
drawableCacheClear(mDrawableCache, configChanges);
1309+
drawableCacheClear(mColorDrawableCache, configChanges);
1310+
13321311
mColorStateListCache.clear();
1312+
1313+
13331314
flushLayoutCache();
13341315
}
13351316
synchronized (mSync) {
@@ -1339,6 +1320,41 @@ public void updateConfiguration(Configuration config,
13391320
}
13401321
}
13411322

1323+
private void drawableCacheClear(
1324+
LongSparseArray<WeakReference<ConstantState>> cache,
1325+
int configChanges) {
1326+
int N = cache.size();
1327+
if (DEBUG_CONFIG) {
1328+
Log.d(TAG, "Cleaning up drawables config changes: 0x"
1329+
+ Integer.toHexString(configChanges));
1330+
}
1331+
for (int i=0; i<N; i++) {
1332+
WeakReference<Drawable.ConstantState> ref = cache.valueAt(i);
1333+
if (ref != null) {
1334+
Drawable.ConstantState cs = ref.get();
1335+
if (cs != null) {
1336+
if (Configuration.needNewResources(
1337+
configChanges, cs.getChangingConfigurations())) {
1338+
if (DEBUG_CONFIG) {
1339+
Log.d(TAG, "FLUSHING #0x"
1340+
+ Long.toHexString(mDrawableCache.keyAt(i))
1341+
+ " / " + cs + " with changes: 0x"
1342+
+ Integer.toHexString(cs.getChangingConfigurations()));
1343+
}
1344+
cache.setValueAt(i, null);
1345+
} else if (DEBUG_CONFIG) {
1346+
Log.d(TAG, "(Keeping #0x"
1347+
+ Long.toHexString(cache.keyAt(i))
1348+
+ " / " + cs + " with changes: 0x"
1349+
+ Integer.toHexString(cs.getChangingConfigurations())
1350+
+ ")");
1351+
}
1352+
}
1353+
}
1354+
}
1355+
cache.clear();
1356+
}
1357+
13421358
/**
13431359
* Update the system resources configuration if they have previously
13441360
* been initialized.
@@ -1661,13 +1677,18 @@ public final void finishPreloading() {
16611677
}
16621678

16631679
final long key = (((long) value.assetCookie) << 32) | value.data;
1664-
Drawable dr = getCachedDrawable(key);
1680+
boolean isColorDrawable = false;
1681+
if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
1682+
value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
1683+
isColorDrawable = true;
1684+
}
1685+
Drawable dr = getCachedDrawable(isColorDrawable ? mColorDrawableCache : mDrawableCache, key);
16651686

16661687
if (dr != null) {
16671688
return dr;
16681689
}
16691690

1670-
Drawable.ConstantState cs = sPreloadedDrawables.get(key);
1691+
Drawable.ConstantState cs = isColorDrawable ? sPreloadedColorDrawables.get(key) : sPreloadedDrawables.get(key);
16711692
if (cs != null) {
16721693
dr = cs.newDrawable(this);
16731694
} else {
@@ -1726,13 +1747,21 @@ public final void finishPreloading() {
17261747
cs = dr.getConstantState();
17271748
if (cs != null) {
17281749
if (mPreloading) {
1729-
sPreloadedDrawables.put(key, cs);
1750+
if (isColorDrawable) {
1751+
sPreloadedColorDrawables.put(key, cs);
1752+
} else {
1753+
sPreloadedDrawables.put(key, cs);
1754+
}
17301755
} else {
17311756
synchronized (mTmpValue) {
17321757
//Log.i(TAG, "Saving cached drawable @ #" +
17331758
// Integer.toHexString(key.intValue())
17341759
// + " in " + this + ": " + cs);
1735-
mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
1760+
if (isColorDrawable) {
1761+
mColorDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
1762+
} else {
1763+
mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
1764+
}
17361765
}
17371766
}
17381767
}
@@ -1741,19 +1770,21 @@ public final void finishPreloading() {
17411770
return dr;
17421771
}
17431772

1744-
private Drawable getCachedDrawable(long key) {
1773+
private Drawable getCachedDrawable(
1774+
LongSparseArray<WeakReference<ConstantState>> drawableCache,
1775+
long key) {
17451776
synchronized (mTmpValue) {
1746-
WeakReference<Drawable.ConstantState> wr = mDrawableCache.get(key);
1777+
WeakReference<Drawable.ConstantState> wr = drawableCache.get(key);
17471778
if (wr != null) { // we have the key
17481779
Drawable.ConstantState entry = wr.get();
17491780
if (entry != null) {
17501781
//Log.i(TAG, "Returning cached drawable @ #" +
17511782
// Integer.toHexString(((Integer)key).intValue())
17521783
// + " in " + this + ": " + entry);
1753-
return entry.newDrawable(this);
1784+
return entry.newDrawable();
17541785
}
17551786
else { // our entry has been purged
1756-
mDrawableCache.delete(key);
1787+
drawableCache.delete(key);
17571788
}
17581789
}
17591790
}

0 commit comments

Comments
 (0)