Merge changes Iac69f180,I99b6cc0e into udc-dev
* changes: Revert "[SettingsProvider] tracking generation of non-predefined unset settings" Revert "[SettingsProvider] only increment generation of unset settings if new setting is non-predefined"
This commit is contained in:
committed by
Android (Google) Code Review
commit
c505edcb38
@@ -91,7 +91,7 @@ public class NameValueCacheTest {
|
|||||||
mConfigsCacheGenerationStore = new MemoryIntArray(2);
|
mConfigsCacheGenerationStore = new MemoryIntArray(2);
|
||||||
mConfigsCacheGenerationStore.set(0, 123);
|
mConfigsCacheGenerationStore.set(0, 123);
|
||||||
mConfigsCacheGenerationStore.set(1, 456);
|
mConfigsCacheGenerationStore.set(1, 456);
|
||||||
mSettingsCacheGenerationStore = new MemoryIntArray(3);
|
mSettingsCacheGenerationStore = new MemoryIntArray(2);
|
||||||
mSettingsCacheGenerationStore.set(0, 234);
|
mSettingsCacheGenerationStore.set(0, 234);
|
||||||
mSettingsCacheGenerationStore.set(1, 567);
|
mSettingsCacheGenerationStore.set(1, 567);
|
||||||
mConfigsStorage = new HashMap<>();
|
mConfigsStorage = new HashMap<>();
|
||||||
@@ -163,10 +163,6 @@ public class NameValueCacheTest {
|
|||||||
Bundle incomingBundle = invocationOnMock.getArgument(4);
|
Bundle incomingBundle = invocationOnMock.getArgument(4);
|
||||||
String key = invocationOnMock.getArgument(3);
|
String key = invocationOnMock.getArgument(3);
|
||||||
String value = incomingBundle.getString(Settings.NameValueTable.VALUE);
|
String value = incomingBundle.getString(Settings.NameValueTable.VALUE);
|
||||||
boolean newSetting = false;
|
|
||||||
if (!mSettingsStorage.containsKey(key)) {
|
|
||||||
newSetting = true;
|
|
||||||
}
|
|
||||||
mSettingsStorage.put(key, value);
|
mSettingsStorage.put(key, value);
|
||||||
int currentGeneration;
|
int currentGeneration;
|
||||||
// Different settings have different generation codes
|
// Different settings have different generation codes
|
||||||
@@ -177,18 +173,12 @@ public class NameValueCacheTest {
|
|||||||
currentGeneration = mSettingsCacheGenerationStore.get(1);
|
currentGeneration = mSettingsCacheGenerationStore.get(1);
|
||||||
mSettingsCacheGenerationStore.set(1, ++currentGeneration);
|
mSettingsCacheGenerationStore.set(1, ++currentGeneration);
|
||||||
}
|
}
|
||||||
if (newSetting) {
|
|
||||||
// Tracking the generation of all unset settings.
|
|
||||||
// Increment when a new setting is inserted
|
|
||||||
currentGeneration = mSettingsCacheGenerationStore.get(2);
|
|
||||||
mSettingsCacheGenerationStore.set(2, ++currentGeneration);
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Returns the value corresponding to a setting, or null if the setting
|
// Returns the value corresponding to a setting, or null if the setting
|
||||||
// doesn't have a value stored for it. Returns the generation key
|
// doesn't have a value stored for it. Returns the generation key if the value isn't null
|
||||||
// if the caller asked for the generation key.
|
// and the caller asked for the generation key.
|
||||||
when(mMockIContentProvider.call(any(), eq(Settings.Secure.CONTENT_URI.getAuthority()),
|
when(mMockIContentProvider.call(any(), eq(Settings.Secure.CONTENT_URI.getAuthority()),
|
||||||
eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class))).thenAnswer(
|
eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class))).thenAnswer(
|
||||||
invocationOnMock -> {
|
invocationOnMock -> {
|
||||||
@@ -199,15 +189,9 @@ public class NameValueCacheTest {
|
|||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putSerializable(Settings.NameValueTable.VALUE, value);
|
bundle.putSerializable(Settings.NameValueTable.VALUE, value);
|
||||||
|
|
||||||
if (incomingBundle.containsKey(
|
if (value != null && incomingBundle.containsKey(
|
||||||
Settings.CALL_METHOD_TRACK_GENERATION_KEY)) {
|
Settings.CALL_METHOD_TRACK_GENERATION_KEY)) {
|
||||||
int index;
|
int index = key.equals(SETTING) ? 0 : 1;
|
||||||
if (value != null) {
|
|
||||||
index = key.equals(SETTING) ? 0 : 1;
|
|
||||||
} else {
|
|
||||||
// special index for unset settings
|
|
||||||
index = 2;
|
|
||||||
}
|
|
||||||
bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
|
bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
|
||||||
mSettingsCacheGenerationStore);
|
mSettingsCacheGenerationStore);
|
||||||
bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
|
bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
|
||||||
@@ -377,38 +361,16 @@ public class NameValueCacheTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCaching_unsetSetting() throws Exception {
|
public void testCaching_nullSetting() throws Exception {
|
||||||
String returnedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
|
String returnedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
|
||||||
verify(mMockIContentProvider, times(1)).call(any(), any(),
|
verify(mMockIContentProvider, times(1)).call(any(), any(),
|
||||||
eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
|
eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
|
||||||
assertThat(returnedValue).isNull();
|
assertThat(returnedValue).isNull();
|
||||||
|
|
||||||
String cachedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
|
String cachedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
|
||||||
// The first unset setting's generation number is cached
|
// Empty list won't be cached
|
||||||
verifyNoMoreInteractions(mMockIContentProvider);
|
|
||||||
assertThat(cachedValue).isNull();
|
|
||||||
|
|
||||||
String returnedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING2);
|
|
||||||
verify(mMockIContentProvider, times(2)).call(any(), any(),
|
verify(mMockIContentProvider, times(2)).call(any(), any(),
|
||||||
eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
|
eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
|
||||||
assertThat(returnedValue2).isNull();
|
assertThat(cachedValue).isNull();
|
||||||
|
|
||||||
String cachedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING);
|
|
||||||
// The second unset setting's generation number is cached
|
|
||||||
verifyNoMoreInteractions(mMockIContentProvider);
|
|
||||||
assertThat(cachedValue2).isNull();
|
|
||||||
|
|
||||||
Settings.Secure.putString(mMockContentResolver, SETTING, "a");
|
|
||||||
// The generation for unset settings should have changed
|
|
||||||
returnedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING2);
|
|
||||||
verify(mMockIContentProvider, times(3)).call(any(), any(),
|
|
||||||
eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
|
|
||||||
assertThat(returnedValue2).isNull();
|
|
||||||
|
|
||||||
// The generation tracker for the first setting should have change because it's set now
|
|
||||||
returnedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
|
|
||||||
verify(mMockIContentProvider, times(4)).call(any(), any(),
|
|
||||||
eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
|
|
||||||
assertThat(returnedValue).isEqualTo("a");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.android.providers.settings;
|
package com.android.providers.settings;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
@@ -60,10 +59,6 @@ final class GenerationRegistry {
|
|||||||
// Maximum size of an individual backing store
|
// Maximum size of an individual backing store
|
||||||
static final int MAX_BACKING_STORE_SIZE = MemoryIntArray.getMaxSize();
|
static final int MAX_BACKING_STORE_SIZE = MemoryIntArray.getMaxSize();
|
||||||
|
|
||||||
// Use an empty string to track the generation number of all non-predefined, unset settings
|
|
||||||
// The generation number is only increased when a new non-predefined setting is inserted
|
|
||||||
private static final String DEFAULT_MAP_KEY_FOR_UNSET_SETTINGS = "";
|
|
||||||
|
|
||||||
public GenerationRegistry(Object lock) {
|
public GenerationRegistry(Object lock) {
|
||||||
mLock = lock;
|
mLock = lock;
|
||||||
}
|
}
|
||||||
@@ -77,10 +72,6 @@ final class GenerationRegistry {
|
|||||||
(SettingsState.getTypeFromKey(key) == SettingsState.SETTINGS_TYPE_CONFIG);
|
(SettingsState.getTypeFromKey(key) == SettingsState.SETTINGS_TYPE_CONFIG);
|
||||||
// Only store the prefix if the mutated setting is a config
|
// Only store the prefix if the mutated setting is a config
|
||||||
final String indexMapKey = isConfig ? (name.split("/")[0] + "/") : name;
|
final String indexMapKey = isConfig ? (name.split("/")[0] + "/") : name;
|
||||||
incrementGenerationInternal(key, indexMapKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void incrementGenerationInternal(int key, @NonNull String indexMapKey) {
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
final MemoryIntArray backingStore = getBackingStoreLocked(key,
|
final MemoryIntArray backingStore = getBackingStoreLocked(key,
|
||||||
/* createIfNotExist= */ false);
|
/* createIfNotExist= */ false);
|
||||||
@@ -96,8 +87,7 @@ final class GenerationRegistry {
|
|||||||
final int generation = backingStore.get(index) + 1;
|
final int generation = backingStore.get(index) + 1;
|
||||||
backingStore.set(index, generation);
|
backingStore.set(index, generation);
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.i(LOG_TAG, "Incremented generation for "
|
Slog.i(LOG_TAG, "Incremented generation for setting:" + indexMapKey
|
||||||
+ (indexMapKey.isEmpty() ? "unset settings" : "setting:" + indexMapKey)
|
|
||||||
+ " key:" + SettingsState.keyToString(key)
|
+ " key:" + SettingsState.keyToString(key)
|
||||||
+ " at index:" + index);
|
+ " at index:" + index);
|
||||||
}
|
}
|
||||||
@@ -108,18 +98,6 @@ final class GenerationRegistry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A new, non-predefined setting has been inserted, increment the tracking number for all unset
|
|
||||||
// settings
|
|
||||||
public void incrementGenerationForUnsetSettings(int key) {
|
|
||||||
final boolean isConfig =
|
|
||||||
(SettingsState.getTypeFromKey(key) == SettingsState.SETTINGS_TYPE_CONFIG);
|
|
||||||
if (isConfig) {
|
|
||||||
// No need to track new settings for configs
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
incrementGenerationInternal(key, DEFAULT_MAP_KEY_FOR_UNSET_SETTINGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the backing store's reference, the index and the current generation number
|
* Return the backing store's reference, the index and the current generation number
|
||||||
* of a cached setting. If it was not in the backing store, first create the entry in it before
|
* of a cached setting. If it was not in the backing store, first create the entry in it before
|
||||||
@@ -146,8 +124,8 @@ final class GenerationRegistry {
|
|||||||
bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
|
bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
|
||||||
backingStore.get(index));
|
backingStore.get(index));
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.i(LOG_TAG, "Exported index:" + index + " for "
|
Slog.i(LOG_TAG, "Exported index:" + index
|
||||||
+ (indexMapKey.isEmpty() ? "unset settings" : "setting:" + indexMapKey)
|
+ " for setting:" + indexMapKey
|
||||||
+ " key:" + SettingsState.keyToString(key));
|
+ " key:" + SettingsState.keyToString(key));
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -157,10 +135,6 @@ final class GenerationRegistry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addGenerationDataForUnsetSettings(Bundle bundle, int key) {
|
|
||||||
addGenerationData(bundle, key, /* indexMapKey= */ DEFAULT_MAP_KEY_FOR_UNSET_SETTINGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onUserRemoved(int userId) {
|
public void onUserRemoved(int userId) {
|
||||||
final int secureKey = SettingsState.makeKey(
|
final int secureKey = SettingsState.makeKey(
|
||||||
SettingsState.SETTINGS_TYPE_SECURE, userId);
|
SettingsState.SETTINGS_TYPE_SECURE, userId);
|
||||||
|
|||||||
@@ -2327,15 +2327,11 @@ public class SettingsProvider extends ContentProvider {
|
|||||||
result.putString(Settings.NameValueTable.VALUE,
|
result.putString(Settings.NameValueTable.VALUE,
|
||||||
(setting != null && !setting.isNull()) ? setting.getValue() : null);
|
(setting != null && !setting.isNull()) ? setting.getValue() : null);
|
||||||
|
|
||||||
synchronized (mLock) {
|
|
||||||
if ((setting != null && !setting.isNull()) || isSettingPreDefined(name, type)) {
|
if ((setting != null && !setting.isNull()) || isSettingPreDefined(name, type)) {
|
||||||
// Individual generation tracking for predefined settings even if they are unset
|
// Don't track generation for non-existent settings unless the name is predefined
|
||||||
|
synchronized (mLock) {
|
||||||
mSettingsRegistry.mGenerationRegistry.addGenerationData(result,
|
mSettingsRegistry.mGenerationRegistry.addGenerationData(result,
|
||||||
SettingsState.makeKey(type, userId), name);
|
SettingsState.makeKey(type, userId), name);
|
||||||
} else {
|
|
||||||
// All non-predefined, unset settings are tracked using the same generation number
|
|
||||||
mSettingsRegistry.mGenerationRegistry.addGenerationDataForUnsetSettings(result,
|
|
||||||
SettingsState.makeKey(type, userId));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -2349,8 +2345,7 @@ public class SettingsProvider extends ContentProvider {
|
|||||||
} else if (type == SETTINGS_TYPE_SYSTEM) {
|
} else if (type == SETTINGS_TYPE_SYSTEM) {
|
||||||
return sAllSystemSettings.contains(name);
|
return sAllSystemSettings.contains(name);
|
||||||
} else {
|
} else {
|
||||||
// Consider all config settings predefined because they are used by system apps only
|
return false;
|
||||||
return type == SETTINGS_TYPE_CONFIG;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2359,13 +2354,14 @@ public class SettingsProvider extends ContentProvider {
|
|||||||
Bundle result = new Bundle();
|
Bundle result = new Bundle();
|
||||||
result.putSerializable(Settings.NameValueTable.VALUE, keyValues);
|
result.putSerializable(Settings.NameValueTable.VALUE, keyValues);
|
||||||
if (trackingGeneration) {
|
if (trackingGeneration) {
|
||||||
|
// Track generation even if the namespace is empty because this is for system apps
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
// Track generation even if namespace is empty because this is for system apps only
|
|
||||||
mSettingsRegistry.mGenerationRegistry.addGenerationData(result,
|
mSettingsRegistry.mGenerationRegistry.addGenerationData(result,
|
||||||
SettingsState.makeKey(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM),
|
mSettingsRegistry.getSettingsLocked(SETTINGS_TYPE_CONFIG,
|
||||||
prefix);
|
UserHandle.USER_SYSTEM).mKey, prefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3056,15 +3052,10 @@ public class SettingsProvider extends ContentProvider {
|
|||||||
final int key = makeKey(type, userId);
|
final int key = makeKey(type, userId);
|
||||||
|
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
boolean wasUnsetNonPredefinedSetting = false;
|
|
||||||
SettingsState settingsState = peekSettingsStateLocked(key);
|
SettingsState settingsState = peekSettingsStateLocked(key);
|
||||||
if (settingsState != null) {
|
if (settingsState != null) {
|
||||||
if (!isSettingPreDefined(name, type) && !settingsState.hasSetting(name)) {
|
|
||||||
wasUnsetNonPredefinedSetting = true;
|
|
||||||
}
|
|
||||||
success = settingsState.insertSettingLocked(name, value,
|
success = settingsState.insertSettingLocked(name, value,
|
||||||
tag, makeDefault, forceNonSystemPackage, packageName,
|
tag, makeDefault, forceNonSystemPackage, packageName, overrideableByRestore);
|
||||||
overrideableByRestore);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success && criticalSettings != null && criticalSettings.contains(name)) {
|
if (success && criticalSettings != null && criticalSettings.contains(name)) {
|
||||||
@@ -3073,11 +3064,6 @@ public class SettingsProvider extends ContentProvider {
|
|||||||
|
|
||||||
if (forceNotify || success) {
|
if (forceNotify || success) {
|
||||||
notifyForSettingsChange(key, name);
|
notifyForSettingsChange(key, name);
|
||||||
if (wasUnsetNonPredefinedSetting) {
|
|
||||||
// Increment the generation number for all non-predefined, unset settings,
|
|
||||||
// because a new non-predefined setting has been inserted
|
|
||||||
mGenerationRegistry.incrementGenerationForUnsetSettings(key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
logSettingChanged(userId, name, type, CHANGE_TYPE_INSERT);
|
logSettingChanged(userId, name, type, CHANGE_TYPE_INSERT);
|
||||||
|
|||||||
@@ -759,12 +759,6 @@ final class SettingsState {
|
|||||||
mPackageToMemoryUsage.put(packageName, newSize);
|
mPackageToMemoryUsage.put(packageName, newSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasSetting(String name) {
|
|
||||||
synchronized (mLock) {
|
|
||||||
return hasSettingLocked(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private boolean hasSettingLocked(String name) {
|
private boolean hasSettingLocked(String name) {
|
||||||
return mSettings.indexOfKey(name) >= 0;
|
return mSettings.indexOfKey(name) >= 0;
|
||||||
|
|||||||
@@ -151,26 +151,6 @@ public class GenerationRegistryTest {
|
|||||||
checkBundle(b, 0, 1, false);
|
checkBundle(b, 0, 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUnsetSettings() throws IOException {
|
|
||||||
final GenerationRegistry generationRegistry = new GenerationRegistry(new Object());
|
|
||||||
final int secureKey = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SECURE, 0);
|
|
||||||
final String testSecureSetting = "test_secure_setting";
|
|
||||||
Bundle b = new Bundle();
|
|
||||||
generationRegistry.addGenerationData(b, secureKey, testSecureSetting);
|
|
||||||
checkBundle(b, 0, 1, false);
|
|
||||||
generationRegistry.addGenerationDataForUnsetSettings(b, secureKey);
|
|
||||||
checkBundle(b, 1, 1, false);
|
|
||||||
generationRegistry.addGenerationDataForUnsetSettings(b, secureKey);
|
|
||||||
// Test that unset settings always have the same index
|
|
||||||
checkBundle(b, 1, 1, false);
|
|
||||||
generationRegistry.incrementGenerationForUnsetSettings(secureKey);
|
|
||||||
// Test that the generation number of the unset settings have increased
|
|
||||||
generationRegistry.addGenerationDataForUnsetSettings(b, secureKey);
|
|
||||||
checkBundle(b, 1, 2, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void checkBundle(Bundle b, int expectedIndex, int expectedGeneration, boolean isNull)
|
private void checkBundle(Bundle b, int expectedIndex, int expectedGeneration, boolean isNull)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final MemoryIntArray array = getArray(b);
|
final MemoryIntArray array = getArray(b);
|
||||||
|
|||||||
Reference in New Issue
Block a user