summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java221
-rw-r--r--packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java265
2 files changed, 403 insertions, 83 deletions
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 04922d6e2c99..c8992c344b2d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -64,6 +64,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.io.InputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
@@ -85,13 +86,13 @@ import java.util.concurrent.CountDownLatch;
// FOR ACONFIGD TEST MISSION AND ROLLOUT
import java.io.DataInputStream;
import java.io.DataOutputStream;
-import android.net.LocalSocketAddress;
-import android.net.LocalSocket;
import android.util.proto.ProtoInputStream;
import android.aconfigd.Aconfigd.StorageRequestMessage;
import android.aconfigd.Aconfigd.StorageRequestMessages;
import android.aconfigd.Aconfigd.StorageReturnMessage;
import android.aconfigd.Aconfigd.StorageReturnMessages;
+import android.aconfigd.AconfigdClientSocket;
+import android.aconfigd.AconfigdFlagInfo;
import android.aconfigd.AconfigdJavaUtils;
import static com.android.aconfig_new_storage.Flags.enableAconfigStorageDaemon;
/**
@@ -265,6 +266,10 @@ final class SettingsState {
@NonNull
private Map<String, Map<String, String>> mNamespaceDefaults;
+ // TOBO(b/312444587): remove the comparison logic after Test Mission 2.
+ @NonNull
+ private Map<String, AconfigdFlagInfo> mAconfigDefaultFlags;
+
public static final int SETTINGS_TYPE_GLOBAL = 0;
public static final int SETTINGS_TYPE_SYSTEM = 1;
public static final int SETTINGS_TYPE_SECURE = 2;
@@ -334,8 +339,13 @@ final class SettingsState {
+ settingTypeToString(getTypeFromKey(key)) + "]";
}
- public SettingsState(Context context, Object lock, File file, int key,
- int maxBytesPerAppPackage, Looper looper) {
+ public SettingsState(
+ Context context,
+ Object lock,
+ File file,
+ int key,
+ int maxBytesPerAppPackage,
+ Looper looper) {
// It is important that we use the same lock as the settings provider
// to ensure multiple mutations on this state are atomically persisted
// as the async persistence should be blocked while we make changes.
@@ -353,12 +363,15 @@ final class SettingsState {
mPackageToMemoryUsage = null;
}
- mHistoricalOperations = Build.IS_DEBUGGABLE
- ? new ArrayList<>(HISTORICAL_OPERATION_COUNT) : null;
+ mHistoricalOperations =
+ Build.IS_DEBUGGABLE ? new ArrayList<>(HISTORICAL_OPERATION_COUNT) : null;
mNamespaceDefaults = new HashMap<>();
+ mAconfigDefaultFlags = new HashMap<>();
ProtoOutputStream requests = null;
+ Map<String, AconfigdFlagInfo> aconfigFlagMap = new HashMap<>();
+
synchronized (mLock) {
readStateSyncLocked();
@@ -375,39 +388,114 @@ final class SettingsState {
}
}
+ if (enableAconfigStorageDaemon()) {
+ if (isConfigSettingsKey(mKey)) {
+ aconfigFlagMap = getAllAconfigFlagsFromSettings();
+ }
+ }
+
if (isConfigSettingsKey(mKey)) {
- requests = handleBulkSyncToNewStorage();
+ requests = handleBulkSyncToNewStorage(aconfigFlagMap);
}
}
- if (requests != null) {
- LocalSocket client = new LocalSocket();
- try{
- client.connect(new LocalSocketAddress(
- "aconfigd", LocalSocketAddress.Namespace.RESERVED));
- Slog.d(LOG_TAG, "connected to aconfigd socket");
- } catch (IOException ioe) {
- Slog.e(LOG_TAG, "failed to connect to aconfigd socket", ioe);
- return;
+ if (enableAconfigStorageDaemon()) {
+ if (isConfigSettingsKey(mKey)){
+ AconfigdClientSocket localSocket = AconfigdJavaUtils.getAconfigdClientSocket();
+ if (requests != null) {
+ InputStream res = localSocket.send(requests.getBytes());
+ if (res == null) {
+ Slog.w(LOG_TAG, "Bulk sync request to acongid failed.");
+ }
+ }
+ // TOBO(b/312444587): remove the comparison logic after Test Mission 2.
+ if (mSettings.get("aconfigd_marker/bulk_synced").value.equals("true")
+ && requests == null) {
+ Map<String, AconfigdFlagInfo> aconfigdFlagMap =
+ AconfigdJavaUtils.listFlagsValueInNewStorage(localSocket);
+ compareFlagValueInNewStorage(
+ aconfigFlagMap,
+ mAconfigDefaultFlags,
+ aconfigdFlagMap);
+ }
}
- AconfigdJavaUtils.sendAconfigdRequests(client, requests);
}
}
- // TODO(b/341764371): migrate aconfig flag push to GMS core
- public static class FlagOverrideToSync {
- public String packageName;
- public String flagName;
- public String flagValue;
- public boolean isLocal;
+ // TOBO(b/312444587): remove the comparison logic after Test Mission 2.
+ public int compareFlagValueInNewStorage(
+ Map<String, AconfigdFlagInfo> settingFlagMap,
+ Map<String, AconfigdFlagInfo> defaultFlagMap,
+ Map<String, AconfigdFlagInfo> aconfigdFlagMap) {
+
+ // Get all defaults from the default map. The mSettings may not contain
+ // all flags, since it only contains updated flags.
+ int diffNum = 0;
+ for (Map.Entry<String, AconfigdFlagInfo> entry : defaultFlagMap.entrySet()) {
+ String key = entry.getKey();
+ AconfigdFlagInfo flag = entry.getValue();
+ if (settingFlagMap.containsKey(key)) {
+ flag.merge(settingFlagMap.get(key));
+ }
+
+ AconfigdFlagInfo aconfigdFlag = aconfigdFlagMap.get(key);
+ if (aconfigdFlag == null) {
+ Slog.w(LOG_TAG, String.format("Flag %s is missing from aconfigd", key));
+ diffNum++;
+ continue;
+ }
+ String diff = flag.dumpDiff(aconfigdFlag);
+ if (!diff.isEmpty()) {
+ Slog.w(
+ LOG_TAG,
+ String.format(
+ "Flag %s is different in Settings and aconfig: %s", key, diff));
+ diffNum++;
+ }
+ }
+
+ for (String key : aconfigdFlagMap.keySet()) {
+ if (defaultFlagMap.containsKey(key)) continue;
+ Slog.w(LOG_TAG, String.format("Flag %s is missing from Settings", key));
+ diffNum++;
+ }
+
+ if (diffNum == 0) {
+ Slog.i(LOG_TAG, "Settings and new storage have same flags.");
+ }
+ return diffNum;
+ }
+
+ @GuardedBy("mLock")
+ public Map<String, AconfigdFlagInfo> getAllAconfigFlagsFromSettings() {
+ Map<String, AconfigdFlagInfo> ret = new HashMap<>();
+ int numSettings = mSettings.size();
+ int num_requests = 0;
+ for (int i = 0; i < numSettings; i++) {
+ String name = mSettings.keyAt(i);
+ Setting setting = mSettings.valueAt(i);
+ AconfigdFlagInfo flag =
+ getFlagOverrideToSync(name, setting.getValue());
+ if (flag == null) {
+ continue;
+ }
+ String fullFlagName = flag.getFullFlagName();
+ AconfigdFlagInfo prev = ret.putIfAbsent(fullFlagName,flag);
+ if (prev != null) {
+ prev.merge(flag);
+ }
+ ++num_requests;
+ }
+ Slog.i(LOG_TAG, num_requests + " flag override requests created");
+ return ret;
}
// TODO(b/341764371): migrate aconfig flag push to GMS core
@VisibleForTesting
@GuardedBy("mLock")
- public FlagOverrideToSync getFlagOverrideToSync(String name, String value) {
+ public AconfigdFlagInfo getFlagOverrideToSync(String name, String value) {
int slashIdx = name.indexOf("/");
- if (slashIdx <= 0 || slashIdx >= name.length()-1) {
+ if (slashIdx <= 0 || slashIdx >= name.length() - 1) {
Slog.e(LOG_TAG, "invalid flag name " + name);
return null;
}
@@ -430,8 +518,9 @@ final class SettingsState {
}
String aconfigName = namespace + "/" + fullFlagName;
- boolean isAconfig = mNamespaceDefaults.containsKey(namespace)
- && mNamespaceDefaults.get(namespace).containsKey(aconfigName);
+ boolean isAconfig =
+ mNamespaceDefaults.containsKey(namespace)
+ && mNamespaceDefaults.get(namespace).containsKey(aconfigName);
if (!isAconfig) {
return null;
}
@@ -443,25 +532,30 @@ final class SettingsState {
return null;
}
- FlagOverrideToSync flag = new FlagOverrideToSync();
- flag.packageName = fullFlagName.substring(0, dotIdx);
- flag.flagName = fullFlagName.substring(dotIdx + 1);
- flag.isLocal = isLocal;
- flag.flagValue = value;
- return flag;
+ AconfigdFlagInfo.Builder builder = AconfigdFlagInfo.newBuilder()
+ .setPackageName(fullFlagName.substring(0, dotIdx))
+ .setFlagName(fullFlagName.substring(dotIdx + 1))
+ .setDefaultFlagValue(mNamespaceDefaults.get(namespace).get(aconfigName));
+
+ if (isLocal) {
+ builder.setHasLocalOverride(isLocal).setBootFlagValue(value).setLocalFlagValue(value);
+ } else {
+ builder.setHasServerOverride(true).setServerFlagValue(value).setBootFlagValue(value);
+ }
+ return builder.build();
}
// TODO(b/341764371): migrate aconfig flag push to GMS core
@VisibleForTesting
@GuardedBy("mLock")
- public ProtoOutputStream handleBulkSyncToNewStorage() {
+ public ProtoOutputStream handleBulkSyncToNewStorage(
+ Map<String, AconfigdFlagInfo> aconfigFlagMap) {
// get marker or add marker if it does not exist
final String bulkSyncMarkerName = new String("aconfigd_marker/bulk_synced");
Setting markerSetting = mSettings.get(bulkSyncMarkerName);
if (markerSetting == null) {
- markerSetting = new Setting(
- bulkSyncMarkerName, "false", false, "aconfig", "aconfig");
+ markerSetting = new Setting(bulkSyncMarkerName, "false", false, "aconfig", "aconfig");
mSettings.put(bulkSyncMarkerName, markerSetting);
}
@@ -479,24 +573,19 @@ final class SettingsState {
AconfigdJavaUtils.writeResetStorageRequest(requests);
// loop over all settings and add flag override requests
- final int numSettings = mSettings.size();
- int num_requests = 0;
- for (int i = 0; i < numSettings; i++) {
- String name = mSettings.keyAt(i);
- Setting setting = mSettings.valueAt(i);
- FlagOverrideToSync flag =
- getFlagOverrideToSync(name, setting.getValue());
- if (flag == null) {
- continue;
- }
- ++num_requests;
+ for (AconfigdFlagInfo flag : aconfigFlagMap.values()) {
+ String value =
+ flag.getHasLocalOverride()
+ ? flag.getLocalFlagValue()
+ : flag.getServerFlagValue();
AconfigdJavaUtils.writeFlagOverrideRequest(
- requests, flag.packageName, flag.flagName, flag.flagValue,
- flag.isLocal);
+ requests,
+ flag.getPackageName(),
+ flag.getFlagName(),
+ value,
+ flag.getHasLocalOverride());
}
- Slog.i(LOG_TAG, num_requests + " flag override requests created");
-
// mark sync has been done
markerSetting.value = "true";
scheduleWriteIfNeededLocked();
@@ -513,14 +602,14 @@ final class SettingsState {
return null;
}
}
-
}
@GuardedBy("mLock")
private void loadAconfigDefaultValuesLocked(List<String> filePaths) {
for (String fileName : filePaths) {
try (FileInputStream inputStream = new FileInputStream(fileName)) {
- loadAconfigDefaultValues(inputStream.readAllBytes(), mNamespaceDefaults);
+ loadAconfigDefaultValues(
+ inputStream.readAllBytes(), mNamespaceDefaults, mAconfigDefaultFlags);
} catch (IOException e) {
Slog.e(LOG_TAG, "failed to read protobuf", e);
}
@@ -566,21 +655,30 @@ final class SettingsState {
@VisibleForTesting
@GuardedBy("mLock")
- public static void loadAconfigDefaultValues(byte[] fileContents,
- @NonNull Map<String, Map<String, String>> defaultMap) {
+ public static void loadAconfigDefaultValues(
+ byte[] fileContents,
+ @NonNull Map<String, Map<String, String>> defaultMap,
+ @NonNull Map<String, AconfigdFlagInfo> flagInfoDefault) {
try {
- parsed_flags parsedFlags =
- parsed_flags.parseFrom(fileContents);
+ parsed_flags parsedFlags = parsed_flags.parseFrom(fileContents);
for (parsed_flag flag : parsedFlags.getParsedFlagList()) {
if (!defaultMap.containsKey(flag.getNamespace())) {
Map<String, String> defaults = new HashMap<>();
defaultMap.put(flag.getNamespace(), defaults);
}
- String flagName = flag.getNamespace()
- + "/" + flag.getPackage() + "." + flag.getName();
- String flagValue = flag.getState() == flag_state.ENABLED
- ? "true" : "false";
+ String fullFlagName = flag.getPackage() + "." + flag.getName();
+ String flagName = flag.getNamespace() + "/" + fullFlagName;
+ String flagValue = flag.getState() == flag_state.ENABLED ? "true" : "false";
defaultMap.get(flag.getNamespace()).put(flagName, flagValue);
+ if (!flagInfoDefault.containsKey(fullFlagName)) {
+ flagInfoDefault.put(
+ fullFlagName,
+ AconfigdFlagInfo.newBuilder()
+ .setPackageName(flag.getPackage())
+ .setFlagName(flag.getName())
+ .setDefaultFlagValue(flagValue)
+ .build());
+ }
}
} catch (IOException e) {
Slog.e(LOG_TAG, "failed to parse protobuf", e);
@@ -1646,7 +1744,6 @@ final class SettingsState {
}
}
}
-
mSettings.put(name, new Setting(name, value, defaultValue, packageName, tag,
fromSystem, id, isPreservedInRestore));
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 244c8c4d99bc..256b999ca6c5 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
@@ -24,13 +24,13 @@ import static junit.framework.Assert.fail;
import android.aconfig.Aconfig;
import android.aconfig.Aconfig.parsed_flag;
import android.aconfig.Aconfig.parsed_flags;
+import android.aconfigd.AconfigdFlagInfo;
import android.os.Looper;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.util.Xml;
import android.util.proto.ProtoOutputStream;
-import com.android.providers.settings.SettingsState.FlagOverrideToSync;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -145,16 +145,32 @@ public class SettingsStateTest {
.setState(Aconfig.flag_state.ENABLED)
.setPermission(Aconfig.flag_permission.READ_WRITE))
.build();
+
+ AconfigdFlagInfo flag1 = AconfigdFlagInfo.newBuilder()
+ .setPackageName("com.android.flags")
+ .setFlagName("flag1")
+ .setDefaultFlagValue("false")
+ .build();
+ AconfigdFlagInfo flag2 = AconfigdFlagInfo.newBuilder()
+ .setPackageName("com.android.flags")
+ .setFlagName("flag2")
+ .setDefaultFlagValue("true")
+ .build();
+ Map<String, AconfigdFlagInfo> flagInfoDefault = new HashMap<>();
synchronized (lock) {
Map<String, Map<String, String>> defaults = new HashMap<>();
- settingsState.loadAconfigDefaultValues(flags.toByteArray(), defaults);
+ settingsState.loadAconfigDefaultValues(
+ flags.toByteArray(), defaults, flagInfoDefault);
Map<String, String> namespaceDefaults = defaults.get("test_namespace");
assertEquals(2, namespaceDefaults.keySet().size());
assertEquals("false", namespaceDefaults.get("test_namespace/com.android.flags.flag1"));
assertEquals("true", namespaceDefaults.get("test_namespace/com.android.flags.flag2"));
}
+
+ assertEquals(flag1, flagInfoDefault.get(flag1.getFullFlagName()));
+ assertEquals(flag2, flagInfoDefault.get(flag2.getFullFlagName()));
}
@Test
@@ -165,6 +181,8 @@ public class SettingsStateTest {
InstrumentationRegistry.getContext(), lock, mSettingsFile, configKey,
SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED, Looper.getMainLooper());
+ Map<String, AconfigdFlagInfo> flagInfoDefault = new HashMap<>();
+
parsed_flags flags = parsed_flags
.newBuilder()
.addParsedFlag(parsed_flag
@@ -177,7 +195,8 @@ public class SettingsStateTest {
synchronized (lock) {
Map<String, Map<String, String>> defaults = new HashMap<>();
- settingsState.loadAconfigDefaultValues(flags.toByteArray(), defaults);
+ settingsState.loadAconfigDefaultValues(
+ flags.toByteArray(), defaults, flagInfoDefault);
Map<String, String> namespaceDefaults = defaults.get("test_namespace");
assertEquals(null, namespaceDefaults);
@@ -204,10 +223,12 @@ public class SettingsStateTest {
.setState(Aconfig.flag_state.DISABLED)
.setPermission(Aconfig.flag_permission.READ_WRITE))
.build();
+ Map<String, AconfigdFlagInfo> flagInfoDefault = new HashMap<>();
synchronized (lock) {
Map<String, Map<String, String>> defaults = new HashMap<>();
- settingsState.loadAconfigDefaultValues(flags.toByteArray(), defaults);
+ settingsState.loadAconfigDefaultValues(
+ flags.toByteArray(), defaults, flagInfoDefault);
settingsState.addAconfigDefaultValuesFromMap(defaults);
settingsState.insertSettingLocked("test_namespace/com.android.flags.flag5",
@@ -238,8 +259,10 @@ public class SettingsStateTest {
@Test
public void testInvalidAconfigProtoDoesNotCrash() {
Map<String, Map<String, String>> defaults = new HashMap<>();
+ Map<String, AconfigdFlagInfo> flagInfoDefault = new HashMap<>();
SettingsState settingsState = getSettingStateObject();
- settingsState.loadAconfigDefaultValues("invalid protobuf".getBytes(), defaults);
+ settingsState.loadAconfigDefaultValues(
+ "invalid protobuf".getBytes(), defaults, flagInfoDefault);
}
@Test
@@ -759,6 +782,8 @@ public class SettingsStateTest {
Map<String, String> keyValues =
Map.of("test_namespace/com.android.flags.flag3", "true");
+ Map<String, AconfigdFlagInfo> flagInfoDefault = new HashMap<>();
+
parsed_flags flags = parsed_flags
.newBuilder()
.addParsedFlag(parsed_flag
@@ -774,7 +799,8 @@ public class SettingsStateTest {
synchronized (mLock) {
settingsState.loadAconfigDefaultValues(
- flags.toByteArray(), settingsState.getAconfigDefaultValues());
+ flags.toByteArray(),
+ settingsState.getAconfigDefaultValues(), flagInfoDefault);
List<String> updates =
settingsState.setSettingsLocked("test_namespace/", keyValues, packageName);
assertEquals(1, updates.size());
@@ -840,10 +866,13 @@ public class SettingsStateTest {
.setState(Aconfig.flag_state.DISABLED)
.setPermission(Aconfig.flag_permission.READ_WRITE))
.build();
+ Map<String, AconfigdFlagInfo> flagInfoDefault = new HashMap<>();
synchronized (mLock) {
settingsState.loadAconfigDefaultValues(
- flags.toByteArray(), settingsState.getAconfigDefaultValues());
+ flags.toByteArray(),
+ settingsState.getAconfigDefaultValues(),
+ flagInfoDefault);
List<String> updates =
settingsState.setSettingsLocked("test_namespace/", keyValues, packageName);
assertEquals(3, updates.size());
@@ -973,10 +1002,12 @@ public class SettingsStateTest {
.setState(Aconfig.flag_state.DISABLED)
.setPermission(Aconfig.flag_permission.READ_WRITE))
.build();
+ Map<String, AconfigdFlagInfo> flagInfoDefault = new HashMap<>();
synchronized (lock) {
Map<String, Map<String, String>> defaults = new HashMap<>();
- settingsState.loadAconfigDefaultValues(flags.toByteArray(), defaults);
+ settingsState.loadAconfigDefaultValues(
+ flags.toByteArray(), defaults, flagInfoDefault);
Map<String, String> namespaceDefaults = defaults.get("test_namespace");
assertEquals(1, namespaceDefaults.keySet().size());
settingsState.addAconfigDefaultValuesFromMap(defaults);
@@ -991,22 +1022,28 @@ public class SettingsStateTest {
"some_namespace/some_flag", "false") == null);
// server override
- FlagOverrideToSync flag = settingsState.getFlagOverrideToSync(
+ AconfigdFlagInfo flag = settingsState.getFlagOverrideToSync(
"test_namespace/com.android.flags.flag1", "false");
assertTrue(flag != null);
- assertEquals(flag.packageName, "com.android.flags");
- assertEquals(flag.flagName, "flag1");
- assertEquals(flag.flagValue, "false");
- assertEquals(flag.isLocal, false);
+ assertEquals(flag.getPackageName(), "com.android.flags");
+ assertEquals(flag.getFlagName(), "flag1");
+ assertEquals("false", flag.getBootFlagValue());
+ assertEquals("false", flag.getServerFlagValue());
+ assertFalse(flag.getHasLocalOverride());
+ assertNull(flag.getLocalFlagValue());
+ assertEquals("false", flag.getDefaultFlagValue());
// local override
flag = settingsState.getFlagOverrideToSync(
"device_config_overrides/test_namespace:com.android.flags.flag1", "false");
assertTrue(flag != null);
- assertEquals(flag.packageName, "com.android.flags");
- assertEquals(flag.flagName, "flag1");
- assertEquals(flag.flagValue, "false");
- assertEquals(flag.isLocal, true);
+ assertEquals(flag.getPackageName(), "com.android.flags");
+ assertEquals(flag.getFlagName(), "flag1");
+ assertEquals("false", flag.getLocalFlagValue());
+ assertEquals("false", flag.getBootFlagValue());
+ assertTrue(flag.getHasLocalOverride());
+ assertNull(flag.getServerFlagValue());
+ assertEquals("false", flag.getDefaultFlagValue());
}
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -1020,18 +1057,25 @@ public class SettingsStateTest {
InstrumentationRegistry.getContext(), lock, mSettingsFile, configKey,
SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED, Looper.getMainLooper());
+ Map<String, AconfigdFlagInfo> flags = new HashMap<>();
+ AconfigdFlagInfo flag = AconfigdFlagInfo.newBuilder()
+ .setPackageName("com.android.flags")
+ .setFlagName("flag1")
+ .setBootFlagValue("true").build();
+ flags.put("com.android.flags/flag1", flag);
+
synchronized (lock) {
settingsState.insertSettingLocked("aconfigd_marker/bulk_synced",
"false", null, false, "aconfig");
// first bulk sync
- ProtoOutputStream requests = settingsState.handleBulkSyncToNewStorage();
+ ProtoOutputStream requests = settingsState.handleBulkSyncToNewStorage(flags);
assertTrue(requests != null);
String value = settingsState.getSettingLocked("aconfigd_marker/bulk_synced").getValue();
assertEquals("true", value);
// send time should no longer bulk sync
- requests = settingsState.handleBulkSyncToNewStorage();
+ requests = settingsState.handleBulkSyncToNewStorage(flags);
assertTrue(requests == null);
value = settingsState.getSettingLocked("aconfigd_marker/bulk_synced").getValue();
assertEquals("true", value);
@@ -1047,21 +1091,200 @@ public class SettingsStateTest {
InstrumentationRegistry.getContext(), lock, mSettingsFile, configKey,
SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED, Looper.getMainLooper());
+ Map<String, AconfigdFlagInfo> flags = new HashMap<>();
synchronized (lock) {
settingsState.insertSettingLocked("aconfigd_marker/bulk_synced",
"true", null, false, "aconfig");
// when aconfigd is off, should change the marker to false
- ProtoOutputStream requests = settingsState.handleBulkSyncToNewStorage();
+ ProtoOutputStream requests = settingsState.handleBulkSyncToNewStorage(flags);
assertTrue(requests == null);
String value = settingsState.getSettingLocked("aconfigd_marker/bulk_synced").getValue();
assertEquals("false", value);
// marker started with false value, after call, it should remain false
- requests = settingsState.handleBulkSyncToNewStorage();
+ requests = settingsState.handleBulkSyncToNewStorage(flags);
assertTrue(requests == null);
value = settingsState.getSettingLocked("aconfigd_marker/bulk_synced").getValue();
assertEquals("false", value);
}
}
+
+ @Test
+ public void testGetAllAconfigFlagsFromSettings() throws Exception {
+ final Object lock = new Object();
+ final PrintStream os = new PrintStream(new FileOutputStream(mSettingsFile));
+ os.print(
+ "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>"
+ + "<settings version=\"120\">"
+ + " <setting id=\"0\" name=\"test_namespace/com.android.flags.flag1\" "
+ + "value=\"false\" package=\"com.android.flags\" />"
+ + " <setting id=\"1\" name=\"device_config_overrides/test_namespace:com.android.flags.flag1\" "
+ + "value=\"true\" package=\"com.android.flags\" />"
+ + " <setting id=\"2\" name=\"device_config_overrides/test_namespace:com.android.flags.flag2\" "
+ + "value=\"true\" package=\"com.android.flags\" />"
+ + " <setting id=\"3\" name=\"test_namespace/com.android.flags.flag3\" "
+ + "value=\"true\" package=\"com.android.flags\" />"
+ + "</settings>");
+ os.close();
+
+ int configKey = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_CONFIG, 0);
+
+ SettingsState settingsState = new SettingsState(
+ InstrumentationRegistry.getContext(), lock, mSettingsFile, configKey,
+ SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED, Looper.getMainLooper());
+
+ Map<String, AconfigdFlagInfo> ret;
+ synchronized (lock) {
+ ret = settingsState.getAllAconfigFlagsFromSettings();
+ }
+
+ assertTrue(ret.isEmpty());
+
+ parsed_flags flags =
+ parsed_flags
+ .newBuilder()
+ .addParsedFlag(
+ parsed_flag
+ .newBuilder()
+ .setPackage("com.android.flags")
+ .setName("flag1")
+ .setNamespace("test_namespace")
+ .setDescription("test flag")
+ .addBug("12345678")
+ .setState(Aconfig.flag_state.DISABLED)
+ .setPermission(Aconfig.flag_permission.READ_WRITE))
+ .addParsedFlag(
+ parsed_flag
+ .newBuilder()
+ .setPackage("com.android.flags")
+ .setName("flag2")
+ .setNamespace("test_namespace")
+ .setDescription("test flag")
+ .addBug("12345678")
+ .setState(Aconfig.flag_state.DISABLED)
+ .setPermission(Aconfig.flag_permission.READ_WRITE))
+ .addParsedFlag(
+ parsed_flag
+ .newBuilder()
+ .setPackage("com.android.flags")
+ .setName("flag3")
+ .setNamespace("test_namespace")
+ .setDescription("test flag")
+ .addBug("12345678")
+ .setState(Aconfig.flag_state.DISABLED)
+ .setPermission(Aconfig.flag_permission.READ_WRITE))
+ .build();
+
+ Map<String, Map<String, String>> defaults = new HashMap<>();
+ Map<String, AconfigdFlagInfo> flagInfoDefault = new HashMap<>();
+ synchronized (lock) {
+ settingsState.loadAconfigDefaultValues(
+ flags.toByteArray(), defaults, flagInfoDefault);
+ settingsState.addAconfigDefaultValuesFromMap(defaults);
+ ret = settingsState.getAllAconfigFlagsFromSettings();
+ }
+
+ AconfigdFlagInfo expectedFlag1 =
+ AconfigdFlagInfo.newBuilder()
+ .setPackageName("com.android.flags")
+ .setFlagName("flag1")
+ .setServerFlagValue("false")
+ .setLocalFlagValue("true")
+ .setDefaultFlagValue("false")
+ .setBootFlagValue("true")
+ .setHasServerOverride(true)
+ .setHasLocalOverride(true)
+ .setIsReadWrite(false)
+ .build();
+
+ AconfigdFlagInfo expectedFlag2 =
+ AconfigdFlagInfo.newBuilder()
+ .setPackageName("com.android.flags")
+ .setFlagName("flag2")
+ .setLocalFlagValue("true")
+ .setDefaultFlagValue("false")
+ .setBootFlagValue("true")
+ .setHasLocalOverride(true)
+ .setHasServerOverride(false)
+ .setIsReadWrite(false)
+ .build();
+
+
+ AconfigdFlagInfo expectedFlag3 =
+ AconfigdFlagInfo.newBuilder()
+ .setPackageName("com.android.flags")
+ .setFlagName("flag3")
+ .setServerFlagValue("true")
+ .setBootFlagValue("true")
+ .setDefaultFlagValue("false")
+ .setHasServerOverride(true)
+ .setIsReadWrite(false)
+ .build();
+
+ assertEquals(expectedFlag1, ret.get("com.android.flags.flag1"));
+ assertEquals(expectedFlag2, ret.get("com.android.flags.flag2"));
+ assertEquals(expectedFlag3, ret.get("com.android.flags.flag3"));
+ }
+
+ @Test
+ public void testCompareFlagValueInNewStorage() {
+ int configKey = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_CONFIG, 0);
+ Object lock = new Object();
+ SettingsState settingsState =
+ new SettingsState(
+ InstrumentationRegistry.getContext(),
+ lock,
+ mSettingsFile,
+ configKey,
+ SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED,
+ Looper.getMainLooper());
+
+ AconfigdFlagInfo defaultFlag1 =
+ AconfigdFlagInfo.newBuilder()
+ .setPackageName("com.android.flags")
+ .setFlagName("flag1")
+ .setDefaultFlagValue("false")
+ .build();
+
+ AconfigdFlagInfo settingFlag1 =
+ AconfigdFlagInfo.newBuilder()
+ .setPackageName("com.android.flags")
+ .setFlagName("flag1")
+ .setServerFlagValue("true")
+ .setHasServerOverride(true)
+ .build();
+
+ AconfigdFlagInfo expectedFlag1 =
+ AconfigdFlagInfo.newBuilder()
+ .setPackageName("com.android.flags")
+ .setFlagName("flag1")
+ .setBootFlagValue("true")
+ .setServerFlagValue("true")
+ .setDefaultFlagValue("false")
+ .setHasServerOverride(true)
+ .build();
+
+ Map<String, AconfigdFlagInfo> settingMap = new HashMap<>();
+ Map<String, AconfigdFlagInfo> aconfigdMap = new HashMap<>();
+ Map<String, AconfigdFlagInfo> defaultMap = new HashMap<>();
+
+ defaultMap.put("com.android.flags.flag1", defaultFlag1);
+ settingMap.put("com.android.flags.flag1", settingFlag1);
+ aconfigdMap.put("com.android.flags.flag1", expectedFlag1);
+
+ int ret = settingsState.compareFlagValueInNewStorage(settingMap, defaultMap, aconfigdMap);
+ assertEquals(0, ret);
+
+ AconfigdFlagInfo defaultFlag2 =
+ AconfigdFlagInfo.newBuilder()
+ .setPackageName("com.android.flags")
+ .setFlagName("flag2")
+ .setDefaultFlagValue("false")
+ .build();
+ defaultMap.put("com.android.flags.flag2", defaultFlag2);
+
+ ret = settingsState.compareFlagValueInNewStorage(settingMap, defaultMap, aconfigdMap);
+ assertEquals(1, ret);
+ }
}