diff options
| author | 2018-01-11 23:52:46 +0000 | |
|---|---|---|
| committer | 2018-01-11 23:52:46 +0000 | |
| commit | 5edae415b08bd62eb50c7857a897173c4050983d (patch) | |
| tree | 5065c1ba0c754c860d319385e7517ed5c917dca2 | |
| parent | 68ad3d119c47509780ad9676bf19b29a89136ff2 (diff) | |
| parent | 1aa0d01cc859ba0a99e373759fab634f0ae9b17a (diff) | |
Merge "Frameworks: Move SharedPreferencesImpl to tristate"
| -rw-r--r-- | core/java/android/app/SharedPreferencesImpl.java | 43 |
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 |