summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Treehugger Robot <treehugger-gerrit@google.com> 2018-01-11 23:52:46 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2018-01-11 23:52:46 +0000
commit5edae415b08bd62eb50c7857a897173c4050983d (patch)
tree5065c1ba0c754c860d319385e7517ed5c917dca2
parent68ad3d119c47509780ad9676bf19b29a89136ff2 (diff)
parent1aa0d01cc859ba0a99e373759fab634f0ae9b17a (diff)
Merge "Frameworks: Move SharedPreferencesImpl to tristate"
-rw-r--r--core/java/android/app/SharedPreferencesImpl.java43
1 files changed, 34 insertions, 9 deletions
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 8c47598fff34..6ac15a5f8c91 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -71,6 +71,8 @@ final class SharedPreferencesImpl implements SharedPreferences {
@GuardedBy("mLock")
private Map<String, Object> mMap;
+ @GuardedBy("mLock")
+ private Throwable mThrowable;
@GuardedBy("mLock")
private int mDiskWritesInFlight = 0;
@@ -107,6 +109,7 @@ final class SharedPreferencesImpl implements SharedPreferences {
mMode = mode;
mLoaded = false;
mMap = null;
+ mThrowable = null;
startLoadFromDisk();
}
@@ -139,13 +142,14 @@ final class SharedPreferencesImpl implements SharedPreferences {
Map<String, Object> map = null;
StructStat stat = null;
+ Throwable thrown = null;
try {
stat = Os.stat(mFile.getPath());
if (mFile.canRead()) {
BufferedInputStream str = null;
try {
str = new BufferedInputStream(
- new FileInputStream(mFile), 16*1024);
+ new FileInputStream(mFile), 16 * 1024);
map = (Map<String, Object>) XmlUtils.readMapXml(str);
} catch (Exception e) {
Log.w(TAG, "Cannot read " + mFile.getAbsolutePath(), e);
@@ -154,19 +158,36 @@ final class SharedPreferencesImpl implements SharedPreferences {
}
}
} 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) {
mLoaded = true;
- if (map != null) {
- mMap = map;
- mStatTimestamp = stat.st_mtim;
- mStatSize = stat.st_size;
- } else {
- mMap = new HashMap<>();
+ 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) {
+ mMap = map;
+ mStatTimestamp = stat.st_mtim;
+ mStatSize = stat.st_size;
+ } else {
+ 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();
}
}
@@ -226,6 +247,7 @@ final class SharedPreferencesImpl implements SharedPreferences {
}
}
+ @GuardedBy("mLock")
private void awaitLoadedLocked() {
if (!mLoaded) {
// Raise an explicit StrictMode onReadFromDisk for this
@@ -239,6 +261,9 @@ final class SharedPreferencesImpl implements SharedPreferences {
} catch (InterruptedException unused) {
}
}
+ if (mThrowable != null) {
+ throw new IllegalStateException(mThrowable);
+ }
}
@Override