a possible fix for the bug http://b/issue?id=2200637
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 456181c..1cf559d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -43,8 +43,10 @@
import java.net.URISyntaxException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
/**
@@ -476,7 +478,10 @@
private static class NameValueCache {
private final String mVersionSystemProperty;
- private final HashMap<String, String> mValues = Maps.newHashMap();
+ // the following needs synchronization because this structure is accessed from different
+ // threads and they could be performing clear(), get(), put() at the same time.
+ private final Map<String, String> mValues =
+ Collections.synchronizedMap(new HashMap<String, String>());
private long mValuesVersion = 0;
private final Uri mUri;
@@ -491,8 +496,29 @@
mValues.clear();
mValuesVersion = newValuesVersion;
}
- if (!mValues.containsKey(name)) {
- String value = null;
+ /*
+ * don't look for the key using containsKey() method because (key, object) mapping
+ * could be removed from mValues before get() is done like so:
+ *
+ * say, mValues contains mapping for "foo"
+ * Thread# 1
+ * performs containsKey("foo")
+ * receives true
+ * Thread #2
+ * triggers mValues.clear()
+ * Thread#1
+ * since containsKey("foo") = true, performs get("foo")
+ * receives null
+ * thats incorrect!
+ *
+ * to avoid the above, thread#1 should do get("foo") instead of containsKey("foo")
+ * since mValues is synchronized, get() will get a consistent value.
+ *
+ * we don't want to make this method synchronized tho - because
+ * holding mutex is not desirable while a call could be made to database.
+ */
+ String value = mValues.get(name);
+ if (value == null) {
Cursor c = null;
try {
c = cr.query(mUri, new String[] { Settings.NameValueTable.VALUE },
@@ -505,10 +531,8 @@
} finally {
if (c != null) c.close();
}
- return value;
- } else {
- return mValues.get(name);
}
+ return value;
}
}