diff options
Diffstat (limited to 'packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java')
-rw-r--r-- | packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 942d32d..83937fa 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -60,6 +60,11 @@ public class SettingsProvider extends ContentProvider { private static final SettingsCache sSystemCache = new SettingsCache(); private static final SettingsCache sSecureCache = new SettingsCache(); + // Over this size we don't reject loading or saving settings but + // we do consider them broken/malicious and don't keep them in + // memory at least: + private static final int MAX_CACHE_ENTRY_SIZE = 500; + private static final Bundle NULL_SETTING = Bundle.forPair("value", null); protected DatabaseHelper mOpenHelper; @@ -264,10 +269,7 @@ public class SettingsProvider extends ContentProvider { null, null, null, null); if (cursor != null && cursor.getCount() == 1) { cursor.moveToFirst(); - String value = cursor.getString(0); - Bundle bundle = (value == null) ? NULL_SETTING : Bundle.forPair("value", value); - cache.putIfAbsentLocked(key, bundle); - return bundle; + return cache.putIfAbsent(key, cursor.getString(0)); } } catch (SQLiteException e) { Log.w(TAG, "settings lookup error", e); @@ -275,7 +277,7 @@ public class SettingsProvider extends ContentProvider { } finally { if (cursor != null) cursor.close(); } - cache.putIfAbsentLocked(key, NULL_SETTING); + cache.putIfAbsent(key, null); return NULL_SETTING; } @@ -592,6 +594,7 @@ public class SettingsProvider extends ContentProvider { * database. */ private static final class SettingsCache extends LinkedHashMap<String, Bundle> { + public SettingsCache() { super(MAX_CACHE_ENTRIES, 0.75f /* load factor */, true /* access ordered */); } @@ -601,14 +604,23 @@ public class SettingsProvider extends ContentProvider { return size() > MAX_CACHE_ENTRIES; } - public void putIfAbsentLocked(String key, Bundle value) { - synchronized (this) { - if (containsKey(key)) { - // Lost a race. - return; + /** + * Atomic cache population, conditional on size of value and if + * we lost a race. + * + * @returns a Bundle to send back to the client from call(), even + * if we lost the race. + */ + public Bundle putIfAbsent(String key, String value) { + Bundle bundle = (value == null) ? NULL_SETTING : Bundle.forPair("value", value); + if (value == null || value.length() <= MAX_CACHE_ENTRY_SIZE) { + synchronized (this) { + if (!containsKey(key)) { + put(key, bundle); + } } - put(key, value); } + return bundle; } public static SettingsCache forTable(String tableName) { @@ -635,7 +647,11 @@ public class SettingsProvider extends ContentProvider { } String value = contentValues.getAsString(Settings.NameValueTable.VALUE); synchronized (cache) { - cache.put(name, Bundle.forPair(Settings.NameValueTable.VALUE, value)); + if (value == null || value.length() <= MAX_CACHE_ENTRY_SIZE) { + cache.put(name, Bundle.forPair(Settings.NameValueTable.VALUE, value)); + } else { + cache.remove(name); + } } } |