Merge "Frameworks: Move SharedPreferencesImpl to tristate"

This commit is contained in:
Treehugger Robot
2018-01-11 23:52:46 +00:00
committed by Gerrit Code Review

View File

@@ -71,6 +71,8 @@ final class SharedPreferencesImpl implements SharedPreferences {
@GuardedBy("mLock") @GuardedBy("mLock")
private Map<String, Object> mMap; private Map<String, Object> mMap;
@GuardedBy("mLock")
private Throwable mThrowable;
@GuardedBy("mLock") @GuardedBy("mLock")
private int mDiskWritesInFlight = 0; private int mDiskWritesInFlight = 0;
@@ -107,6 +109,7 @@ final class SharedPreferencesImpl implements SharedPreferences {
mMode = mode; mMode = mode;
mLoaded = false; mLoaded = false;
mMap = null; mMap = null;
mThrowable = null;
startLoadFromDisk(); startLoadFromDisk();
} }
@@ -139,6 +142,7 @@ final class SharedPreferencesImpl implements SharedPreferences {
Map<String, Object> map = null; Map<String, Object> map = null;
StructStat stat = null; StructStat stat = null;
Throwable thrown = null;
try { try {
stat = Os.stat(mFile.getPath()); stat = Os.stat(mFile.getPath());
if (mFile.canRead()) { if (mFile.canRead()) {
@@ -154,11 +158,21 @@ final class SharedPreferencesImpl implements SharedPreferences {
} }
} }
} catch (ErrnoException e) { } catch (ErrnoException e) {
/* ignore */ // An errno exception means the stat failed. Treat as empty/non-existing by
// ignoring.
} catch (Throwable t) {
thrown = t;
} }
synchronized (mLock) { synchronized (mLock) {
mLoaded = true; mLoaded = true;
mThrowable = thrown;
// It's important that we always signal waiters, even if we'll make
// them fail with an exception. The try-finally is pretty wide, but
// better safe than sorry.
try {
if (thrown == null) {
if (map != null) { if (map != null) {
mMap = map; mMap = map;
mStatTimestamp = stat.st_mtim; mStatTimestamp = stat.st_mtim;
@@ -166,9 +180,16 @@ final class SharedPreferencesImpl implements SharedPreferences {
} else { } else {
mMap = new HashMap<>(); mMap = new HashMap<>();
} }
}
// In case of a thrown exception, we retain the old map. That allows
// any open editors to commit and store updates.
} catch (Throwable t) {
mThrowable = t;
} finally {
mLock.notifyAll(); mLock.notifyAll();
} }
} }
}
static File makeBackupFile(File prefsFile) { static File makeBackupFile(File prefsFile) {
return new File(prefsFile.getPath() + ".bak"); return new File(prefsFile.getPath() + ".bak");
@@ -226,6 +247,7 @@ final class SharedPreferencesImpl implements SharedPreferences {
} }
} }
@GuardedBy("mLock")
private void awaitLoadedLocked() { private void awaitLoadedLocked() {
if (!mLoaded) { if (!mLoaded) {
// Raise an explicit StrictMode onReadFromDisk for this // Raise an explicit StrictMode onReadFromDisk for this
@@ -239,6 +261,9 @@ final class SharedPreferencesImpl implements SharedPreferences {
} catch (InterruptedException unused) { } catch (InterruptedException unused) {
} }
} }
if (mThrowable != null) {
throw new IllegalStateException(mThrowable);
}
} }
@Override @Override