summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@android.com>2010-09-07 21:41:09 -0700
committerBrad Fitzpatrick <bradfitz@android.com>2010-09-07 21:41:09 -0700
commitb1657b2bd6aea0c22b48e2cdd25dcc57581a3f3d (patch)
tree33e8328d5f86dc202f1f4cfc74651aece1d28a67
parentf870ee81089ddf5e0388f8b4c7b6a1d437d39ce0 (diff)
parent64591009409618ee67e71c4b345cac50ad0e4e31 (diff)
downloadframeworks_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.java101
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;
}
}