Merge "[SettingsProvider] do not write under mLock" into main
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 46cd725..4e2fad0 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3243,7 +3243,7 @@
}
if (success && criticalSettings != null && criticalSettings.contains(name)) {
- settingsState.persistSyncLocked();
+ settingsState.persistSettingsLocked();
}
if (forceNotify || success) {
@@ -3294,7 +3294,7 @@
}
if (success && criticalSettings != null && criticalSettings.contains(name)) {
- settingsState.persistSyncLocked();
+ settingsState.persistSettingsLocked();
}
if (forceNotify || success) {
@@ -3319,7 +3319,7 @@
}
if (success && criticalSettings != null && criticalSettings.contains(name)) {
- settingsState.persistSyncLocked();
+ settingsState.persistSettingsLocked();
}
if (forceNotify || success) {
@@ -3385,7 +3385,7 @@
}
}
if (someSettingChanged) {
- settingsState.persistSyncLocked();
+ settingsState.persistSettingsLocked();
success = true;
}
}
@@ -3407,7 +3407,7 @@
}
}
if (someSettingChanged) {
- settingsState.persistSyncLocked();
+ settingsState.persistSettingsLocked();
success = true;
}
}
@@ -3435,7 +3435,7 @@
}
}
if (someSettingChanged) {
- settingsState.persistSyncLocked();
+ settingsState.persistSettingsLocked();
success = true;
}
}
@@ -3460,7 +3460,7 @@
logSettingChanged(userId, name, type, CHANGE_TYPE_DELETE);
}
if (someSettingChanged) {
- settingsState.persistSyncLocked();
+ settingsState.persistSettingsLocked();
success = true;
}
}
@@ -3559,7 +3559,7 @@
ensureSettingsStateLocked(systemKey);
SettingsState systemSettings = mSettingsStates.get(systemKey);
migrateLegacySettingsLocked(systemSettings, database, TABLE_SYSTEM);
- systemSettings.persistSyncLocked();
+ systemSettings.persistSettingsLocked();
// Move over the secure settings.
// Do this after System settings, since this is the first thing we check when deciding
@@ -3569,7 +3569,7 @@
SettingsState secureSettings = mSettingsStates.get(secureKey);
migrateLegacySettingsLocked(secureSettings, database, TABLE_SECURE);
ensureSecureSettingAndroidIdSetLocked(secureSettings);
- secureSettings.persistSyncLocked();
+ secureSettings.persistSettingsLocked();
// Move over the global settings if owner.
// Do this last, since this is the first thing we check when deciding
@@ -3585,7 +3585,7 @@
mSettingsCreationBuildId, null, true,
SettingsState.SYSTEM_PACKAGE_NAME);
}
- globalSettings.persistSyncLocked();
+ globalSettings.persistSettingsLocked();
}
// Drop the database as now all is moved and persisted.
@@ -4404,16 +4404,16 @@
if (userId == UserHandle.USER_SYSTEM) {
SettingsState globalSettings = getGlobalSettingsLocked();
ensureLegacyDefaultValueAndSystemSetUpdatedLocked(globalSettings, userId);
- globalSettings.persistSyncLocked();
+ globalSettings.persistSettingsLocked();
}
SettingsState secureSettings = getSecureSettingsLocked(mUserId);
ensureLegacyDefaultValueAndSystemSetUpdatedLocked(secureSettings, userId);
- secureSettings.persistSyncLocked();
+ secureSettings.persistSettingsLocked();
SettingsState systemSettings = getSystemSettingsLocked(mUserId);
ensureLegacyDefaultValueAndSystemSetUpdatedLocked(systemSettings, userId);
- systemSettings.persistSyncLocked();
+ systemSettings.persistSettingsLocked();
currentVersion = 146;
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index e9533e5..7cec99d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -72,6 +72,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.CountDownLatch;
/**
* This class contains the state for one type of settings. It is responsible
@@ -589,9 +590,10 @@
}
// The settings provider must hold its lock when calling here.
- public void persistSyncLocked() {
+ public void persistSettingsLocked() {
mHandler.removeMessages(MyHandler.MSG_PERSIST_SETTINGS);
- doWriteState();
+ // schedule a write operation right away
+ mHandler.obtainMessage(MyHandler.MSG_PERSIST_SETTINGS).sendToTarget();
}
// The settings provider must hold its lock when calling here.
@@ -1725,4 +1727,20 @@
return mPackageToMemoryUsage.getOrDefault(packageName, 0);
}
}
+
+ /**
+ * Allow tests to wait for the handler to finish handling all the remaining messages
+ */
+ @VisibleForTesting
+ public void waitForHandler() {
+ final CountDownLatch latch = new CountDownLatch(1);
+ synchronized (mLock) {
+ mHandler.post(latch::countDown);
+ }
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ // ignored
+ }
+ }
}
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
index df4d2a1..02a7bc1 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
@@ -76,6 +76,14 @@
mSettingsFile.delete();
}
+ @Override
+ protected void tearDown() throws Exception {
+ if (mSettingsFile != null) {
+ mSettingsFile.delete();
+ }
+ super.tearDown();
+ }
+
public void testIsBinary() {
assertFalse(SettingsState.isBinary(" abc 日本語"));
@@ -149,11 +157,10 @@
* Make sure settings can be written to a file and also can be read.
*/
public void testReadWrite() {
- final File file = new File(getContext().getCacheDir(), "setting.xml");
- file.delete();
final Object lock = new Object();
- final SettingsState ssWriter = new SettingsState(getContext(), lock, file, 1,
+ assertFalse(mSettingsFile.exists());
+ final SettingsState ssWriter = new SettingsState(getContext(), lock, mSettingsFile, 1,
SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED, Looper.getMainLooper());
ssWriter.setVersionLocked(SettingsState.SETTINGS_VERSION_NEW_ENCODING);
@@ -162,11 +169,13 @@
ssWriter.insertSettingLocked("k3", null, null, false, "p2");
ssWriter.insertSettingLocked("k4", CRAZY_STRING, null, false, "p3");
synchronized (lock) {
- ssWriter.persistSyncLocked();
+ ssWriter.persistSettingsLocked();
}
-
- final SettingsState ssReader = new SettingsState(getContext(), lock, file, 1,
+ ssWriter.waitForHandler();
+ assertTrue(mSettingsFile.exists());
+ final SettingsState ssReader = new SettingsState(getContext(), lock, mSettingsFile, 1,
SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED, Looper.getMainLooper());
+
synchronized (lock) {
assertEquals("\u0000", ssReader.getSettingLocked("k1").getValue());
assertEquals("abc", ssReader.getSettingLocked("k2").getValue());
@@ -179,10 +188,8 @@
* In version 120, value "null" meant {code NULL}.
*/
public void testUpgrade() throws Exception {
- final File file = new File(getContext().getCacheDir(), "setting.xml");
- file.delete();
final Object lock = new Object();
- final PrintStream os = new PrintStream(new FileOutputStream(file));
+ final PrintStream os = new PrintStream(new FileOutputStream(mSettingsFile));
os.print(
"<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>" +
"<settings version=\"120\">" +
@@ -192,7 +199,7 @@
"</settings>");
os.close();
- final SettingsState ss = new SettingsState(getContext(), lock, file, 1,
+ final SettingsState ss = new SettingsState(getContext(), lock, mSettingsFile, 1,
SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED, Looper.getMainLooper());
synchronized (lock) {
SettingsState.Setting s;
@@ -213,7 +220,8 @@
public void testInitializeSetting_preserveFlagNotSet() {
SettingsState settingsWriter = getSettingStateObject();
settingsWriter.insertSettingLocked(SETTING_NAME, "1", null, false, TEST_PACKAGE);
- settingsWriter.persistSyncLocked();
+ settingsWriter.persistSettingsLocked();
+ settingsWriter.waitForHandler();
SettingsState settingsReader = getSettingStateObject();
assertFalse(settingsReader.getSettingLocked(SETTING_NAME).isValuePreservedInRestore());
@@ -223,7 +231,8 @@
SettingsState settingsWriter = getSettingStateObject();
settingsWriter.insertSettingLocked(SETTING_NAME, "1", null, false, TEST_PACKAGE);
settingsWriter.insertSettingLocked(SETTING_NAME, "2", null, false, TEST_PACKAGE);
- settingsWriter.persistSyncLocked();
+ settingsWriter.persistSettingsLocked();
+ settingsWriter.waitForHandler();
SettingsState settingsReader = getSettingStateObject();
assertTrue(settingsReader.getSettingLocked(SETTING_NAME).isValuePreservedInRestore());
@@ -234,7 +243,8 @@
settingsWriter.insertSettingLocked(SETTING_NAME, "1", null, false, TEST_PACKAGE);
settingsWriter.insertSettingLocked(SETTING_NAME, "2", null, false, false, TEST_PACKAGE,
/* overrideableByRestore */ true);
- settingsWriter.persistSyncLocked();
+ settingsWriter.persistSettingsLocked();
+ settingsWriter.waitForHandler();
SettingsState settingsReader = getSettingStateObject();
assertFalse(settingsReader.getSettingLocked(SETTING_NAME).isValuePreservedInRestore());
@@ -250,7 +260,8 @@
// already been set to true.
settingsWriter.insertSettingLocked(SETTING_NAME, "2", null, false, false, TEST_PACKAGE,
/* overrideableByRestore */ true);
- settingsWriter.persistSyncLocked();
+ settingsWriter.persistSettingsLocked();
+ settingsWriter.waitForHandler();
SettingsState settingsReader = getSettingStateObject();
assertTrue(settingsReader.getSettingLocked(SETTING_NAME).isValuePreservedInRestore());
@@ -481,8 +492,11 @@
settingsState.insertSettingLocked(
FLAG_NAME_1_STAGED, VALUE1, null, false, TEST_PACKAGE);
settingsState.insertSettingLocked(FLAG_NAME_2, VALUE2, null, false, TEST_PACKAGE);
- settingsState.persistSyncLocked();
+ settingsState.persistSettingsLocked();
+ }
+ settingsState.waitForHandler();
+ synchronized (lock) {
assertEquals(VALUE1, settingsState.getSettingLocked(FLAG_NAME_1_STAGED).getValue());
assertEquals(VALUE2, settingsState.getSettingLocked(FLAG_NAME_2).getValue());
}
@@ -522,7 +536,10 @@
synchronized (lock) {
settingsState.insertSettingLocked(INVALID_STAGED_FLAG_1,
VALUE2, null, false, TEST_PACKAGE);
- settingsState.persistSyncLocked();
+ settingsState.persistSettingsLocked();
+ }
+ settingsState.waitForHandler();
+ synchronized (lock) {
assertEquals(VALUE2, settingsState.getSettingLocked(INVALID_STAGED_FLAG_1).getValue());
}