Only persist last Shared Preferences state am: d15c4f1da5
am: 889a420a9e
Change-Id: If0849eedacedf9197e19616dc56edad2ca39f015
This commit is contained in:
@@ -26,6 +26,8 @@ import android.system.StructStat;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.google.android.collect.Maps;
|
import com.google.android.collect.Maps;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.util.XmlUtils;
|
import com.android.internal.util.XmlUtils;
|
||||||
|
|
||||||
import dalvik.system.BlockGuard;
|
import dalvik.system.BlockGuard;
|
||||||
@@ -72,6 +74,14 @@ final class SharedPreferencesImpl implements SharedPreferences {
|
|||||||
private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
|
private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
|
||||||
new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
|
new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
|
||||||
|
|
||||||
|
/** Current memory state (always increasing) */
|
||||||
|
@GuardedBy("this")
|
||||||
|
private long mCurrentMemoryStateGeneration;
|
||||||
|
|
||||||
|
/** Latest memory state that was committed to disk */
|
||||||
|
@GuardedBy("mWritingToDiskLock")
|
||||||
|
private long mDiskStateGeneration;
|
||||||
|
|
||||||
SharedPreferencesImpl(File file, int mode) {
|
SharedPreferencesImpl(File file, int mode) {
|
||||||
mFile = file;
|
mFile = file;
|
||||||
mBackupFile = makeBackupFile(file);
|
mBackupFile = makeBackupFile(file);
|
||||||
@@ -289,7 +299,7 @@ final class SharedPreferencesImpl implements SharedPreferences {
|
|||||||
|
|
||||||
// Return value from EditorImpl#commitToMemory()
|
// Return value from EditorImpl#commitToMemory()
|
||||||
private static class MemoryCommitResult {
|
private static class MemoryCommitResult {
|
||||||
public boolean changesMade; // any keys different?
|
public long memoryStateGeneration;
|
||||||
public List<String> keysModified; // may be null
|
public List<String> keysModified; // may be null
|
||||||
public Set<OnSharedPreferenceChangeListener> listeners; // may be null
|
public Set<OnSharedPreferenceChangeListener> listeners; // may be null
|
||||||
public Map<?, ?> mapToWriteToDisk;
|
public Map<?, ?> mapToWriteToDisk;
|
||||||
@@ -412,9 +422,11 @@ final class SharedPreferencesImpl implements SharedPreferences {
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
boolean changesMade = false;
|
||||||
|
|
||||||
if (mClear) {
|
if (mClear) {
|
||||||
if (!mMap.isEmpty()) {
|
if (!mMap.isEmpty()) {
|
||||||
mcr.changesMade = true;
|
changesMade = true;
|
||||||
mMap.clear();
|
mMap.clear();
|
||||||
}
|
}
|
||||||
mClear = false;
|
mClear = false;
|
||||||
@@ -441,13 +453,19 @@ final class SharedPreferencesImpl implements SharedPreferences {
|
|||||||
mMap.put(k, v);
|
mMap.put(k, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
mcr.changesMade = true;
|
changesMade = true;
|
||||||
if (hasListeners) {
|
if (hasListeners) {
|
||||||
mcr.keysModified.add(k);
|
mcr.keysModified.add(k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mModified.clear();
|
mModified.clear();
|
||||||
|
|
||||||
|
if (changesMade) {
|
||||||
|
mCurrentMemoryStateGeneration++;
|
||||||
|
}
|
||||||
|
|
||||||
|
mcr.memoryStateGeneration = mCurrentMemoryStateGeneration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mcr;
|
return mcr;
|
||||||
@@ -509,10 +527,12 @@ final class SharedPreferencesImpl implements SharedPreferences {
|
|||||||
*/
|
*/
|
||||||
private void enqueueDiskWrite(final MemoryCommitResult mcr,
|
private void enqueueDiskWrite(final MemoryCommitResult mcr,
|
||||||
final Runnable postWriteRunnable) {
|
final Runnable postWriteRunnable) {
|
||||||
|
final boolean isFromSyncCommit = (postWriteRunnable == null);
|
||||||
|
|
||||||
final Runnable writeToDiskRunnable = new Runnable() {
|
final Runnable writeToDiskRunnable = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
synchronized (mWritingToDiskLock) {
|
synchronized (mWritingToDiskLock) {
|
||||||
writeToFile(mcr);
|
writeToFile(mcr, isFromSyncCommit);
|
||||||
}
|
}
|
||||||
synchronized (SharedPreferencesImpl.this) {
|
synchronized (SharedPreferencesImpl.this) {
|
||||||
mDiskWritesInFlight--;
|
mDiskWritesInFlight--;
|
||||||
@@ -523,8 +543,6 @@ final class SharedPreferencesImpl implements SharedPreferences {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
final boolean isFromSyncCommit = (postWriteRunnable == null);
|
|
||||||
|
|
||||||
// Typical #commit() path with fewer allocations, doing a write on
|
// Typical #commit() path with fewer allocations, doing a write on
|
||||||
// the current thread.
|
// the current thread.
|
||||||
if (isFromSyncCommit) {
|
if (isFromSyncCommit) {
|
||||||
@@ -538,6 +556,10 @@ final class SharedPreferencesImpl implements SharedPreferences {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "added " + mcr.memoryStateGeneration + " -> " + mFile.getName());
|
||||||
|
}
|
||||||
|
|
||||||
QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
|
QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,17 +587,34 @@ final class SharedPreferencesImpl implements SharedPreferences {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Note: must hold mWritingToDiskLock
|
// Note: must hold mWritingToDiskLock
|
||||||
private void writeToFile(MemoryCommitResult mcr) {
|
private void writeToFile(MemoryCommitResult mcr, boolean isFromSyncCommit) {
|
||||||
// Rename the current file so it may be used as a backup during the next read
|
// Rename the current file so it may be used as a backup during the next read
|
||||||
if (mFile.exists()) {
|
if (mFile.exists()) {
|
||||||
if (!mcr.changesMade) {
|
boolean needsWrite = false;
|
||||||
// If the file already exists, but no changes were
|
|
||||||
// made to the underlying map, it's wasteful to
|
if (isFromSyncCommit) {
|
||||||
// re-write the file. Return as if we wrote it
|
// Only need to write if the disk state is older than this commit
|
||||||
// out.
|
if (mDiskStateGeneration < mcr.memoryStateGeneration) {
|
||||||
|
needsWrite = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
synchronized (this) {
|
||||||
|
// No need to persist intermediate states. Just wait for the latest state to be
|
||||||
|
// persisted.
|
||||||
|
if (mCurrentMemoryStateGeneration == mcr.memoryStateGeneration) {
|
||||||
|
needsWrite = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!needsWrite) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "skipped " + mcr.memoryStateGeneration + " -> " + mFile.getName());
|
||||||
|
}
|
||||||
mcr.setDiskWriteResult(true);
|
mcr.setDiskWriteResult(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mBackupFile.exists()) {
|
if (!mBackupFile.exists()) {
|
||||||
if (!mFile.renameTo(mBackupFile)) {
|
if (!mFile.renameTo(mBackupFile)) {
|
||||||
Log.e(TAG, "Couldn't rename file " + mFile
|
Log.e(TAG, "Couldn't rename file " + mFile
|
||||||
@@ -599,6 +638,11 @@ final class SharedPreferencesImpl implements SharedPreferences {
|
|||||||
}
|
}
|
||||||
XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
|
XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
|
||||||
FileUtils.sync(str);
|
FileUtils.sync(str);
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "wrote " + mcr.memoryStateGeneration + " -> " + mFile.getName());
|
||||||
|
}
|
||||||
|
|
||||||
str.close();
|
str.close();
|
||||||
ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
|
ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
|
||||||
try {
|
try {
|
||||||
@@ -612,7 +656,11 @@ final class SharedPreferencesImpl implements SharedPreferences {
|
|||||||
}
|
}
|
||||||
// Writing was successful, delete the backup file if there is one.
|
// Writing was successful, delete the backup file if there is one.
|
||||||
mBackupFile.delete();
|
mBackupFile.delete();
|
||||||
|
|
||||||
|
mDiskStateGeneration = mcr.memoryStateGeneration;
|
||||||
|
|
||||||
mcr.setDiskWriteResult(true);
|
mcr.setDiskWriteResult(true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} catch (XmlPullParserException e) {
|
} catch (XmlPullParserException e) {
|
||||||
Log.w(TAG, "writeToFile: Got exception:", e);
|
Log.w(TAG, "writeToFile: Got exception:", e);
|
||||||
|
|||||||
Reference in New Issue
Block a user