diff options
author | Brad Fitzpatrick <bradfitz@android.com> | 2010-09-07 21:41:09 -0700 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@android.com> | 2010-09-07 21:41:09 -0700 |
commit | b1657b2bd6aea0c22b48e2cdd25dcc57581a3f3d (patch) | |
tree | 33e8328d5f86dc202f1f4cfc74651aece1d28a67 | |
parent | f870ee81089ddf5e0388f8b4c7b6a1d437d39ce0 (diff) | |
parent | 64591009409618ee67e71c4b345cac50ad0e4e31 (diff) | |
download | frameworks_base-b1657b2bd6aea0c22b48e2cdd25dcc57581a3f3d.zip frameworks_base-b1657b2bd6aea0c22b48e2cdd25dcc57581a3f3d.tar.gz frameworks_base-b1657b2bd6aea0c22b48e2cdd25dcc57581a3f3d.tar.bz2 |
resolved conflicts for merge of 64591009 to gingerbread-plus-aosp
Change-Id: Id9ebca9993f97a79cb2a6c41a7566d473ccc5b7e
-rw-r--r-- | core/java/android/app/ContextImpl.java | 101 |
1 files changed, 62 insertions, 39 deletions
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 7513736..8899d76 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -334,54 +334,54 @@ class ContextImpl extends Context { @Override public SharedPreferences getSharedPreferences(String name, int mode) { SharedPreferencesImpl sp; + File prefsFile; + boolean needInitialLoad = false; synchronized (sSharedPrefs) { sp = sSharedPrefs.get(name); - if (sp != null && !sp.hasFileChanged()) { - //Log.i(TAG, "Returning existing prefs " + name + ": " + sp); + if (sp != null && !sp.hasFileChangedUnexpectedly()) { return sp; } - } - File f = getSharedPrefsFile(name); - FileInputStream str = null; - File backup = makeBackupFile(f); - if (backup.exists()) { - f.delete(); - backup.renameTo(f); + prefsFile = getSharedPrefsFile(name); + if (sp == null) { + sp = new SharedPreferencesImpl(prefsFile, mode, null); + sSharedPrefs.put(name, sp); + needInitialLoad = true; + } } - // Debugging - if (f.exists() && !f.canRead()) { - Log.w(TAG, "Attempt to read preferences file " + f + " without permission"); - } + synchronized (sp) { + if (needInitialLoad && sp.isLoaded()) { + // lost the race to load; another thread handled it + return sp; + } + File backup = makeBackupFile(prefsFile); + if (backup.exists()) { + prefsFile.delete(); + backup.renameTo(prefsFile); + } - Map map = null; - if (f.exists() && f.canRead()) { - try { - str = new FileInputStream(f); - map = XmlUtils.readMapXml(str); - str.close(); - } catch (org.xmlpull.v1.XmlPullParserException e) { - Log.w(TAG, "getSharedPreferences", e); - } catch (FileNotFoundException e) { - Log.w(TAG, "getSharedPreferences", e); - } catch (IOException e) { - Log.w(TAG, "getSharedPreferences", e); + // Debugging + if (prefsFile.exists() && !prefsFile.canRead()) { + Log.w(TAG, "Attempt to read preferences file " + prefsFile + " without permission"); } - } - synchronized (sSharedPrefs) { - if (sp != null) { - //Log.i(TAG, "Updating existing prefs " + name + " " + sp + ": " + map); - sp.replace(map); - } else { - sp = sSharedPrefs.get(name); - if (sp == null) { - sp = new SharedPreferencesImpl(f, mode, map); - sSharedPrefs.put(name, sp); + Map map = null; + if (prefsFile.exists() && prefsFile.canRead()) { + try { + FileInputStream str = new FileInputStream(prefsFile); + map = XmlUtils.readMapXml(str); + str.close(); + } catch (org.xmlpull.v1.XmlPullParserException e) { + Log.w(TAG, "getSharedPreferences", e); + } catch (FileNotFoundException e) { + Log.w(TAG, "getSharedPreferences", e); + } catch (IOException e) { + Log.w(TAG, "getSharedPreferences", e); } } - return sp; + sp.replace(map); } + return sp; } private File getPreferencesDir() { @@ -2709,6 +2709,10 @@ class ContextImpl extends Context { private static final class SharedPreferencesImpl implements SharedPreferences { + // Lock ordering rules: + // - acquire SharedPreferencesImpl.this before EditorImpl.this + // - acquire mWritingToDiskLock before EditorImpl.this + private final File mFile; private final File mBackupFile; private final int mMode; @@ -2716,6 +2720,7 @@ class ContextImpl extends Context { private Map<String, Object> mMap; // guarded by 'this' private long mTimestamp; // guarded by 'this' private int mDiskWritesInFlight = 0; // guarded by 'this' + private boolean mLoaded = false; // guarded by 'this' private final Object mWritingToDiskLock = new Object(); private static final Object mContent = new Object(); @@ -2726,6 +2731,7 @@ class ContextImpl extends Context { mFile = file; mBackupFile = makeBackupFile(file); mMode = mode; + mLoaded = initialContents != null; mMap = initialContents != null ? initialContents : new HashMap<String, Object>(); FileStatus stat = new FileStatus(); if (FileUtils.getFileStatus(file.getPath(), stat)) { @@ -2734,7 +2740,23 @@ class ContextImpl extends Context { mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>(); } - public boolean hasFileChanged() { + // Has this SharedPreferences ever had values assigned to it? + boolean isLoaded() { + synchronized (this) { + return mLoaded; + } + } + + // Has the file changed out from under us? i.e. writes that + // we didn't instigate. + public boolean hasFileChangedUnexpectedly() { + synchronized (this) { + if (mDiskWritesInFlight > 0) { + // If we know we caused it, it's not unexpected. + Log.d(TAG, "disk write in flight, not unexpected."); + return false; + } + } FileStatus stat = new FileStatus(); if (!FileUtils.getFileStatus(mFile.getPath(), stat)) { return true; @@ -2745,8 +2767,9 @@ class ContextImpl extends Context { } public void replace(Map newContents) { - if (newContents != null) { - synchronized (this) { + synchronized (this) { + mLoaded = true; + if (newContents != null) { mMap = newContents; } } |