Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5844d3fb authored by Dennis Shen's avatar Dennis Shen Committed by Android (Google) Code Review
Browse files

Merge "system_server remove old optimization when syncing over to system property" into main

parents 135efb62 bd29fe42
Loading
Loading
Loading
Loading
+39 −92
Original line number Diff line number Diff line
@@ -342,33 +342,29 @@ public class SettingsToPropertiesMapper {
            AsyncTask.THREAD_POOL_EXECUTOR,
            (DeviceConfig.Properties properties) -> {

              HashMap<String, HashMap<String, String>> propsToStage =
                  getStagedFlagsWithValueChange(properties);

              // send prop stage request to sys prop
              for (HashMap.Entry<String, HashMap<String, String>> entry : propsToStage.entrySet()) {
                String actualNamespace = entry.getKey();
                HashMap<String, String> flagValuesToStage = entry.getValue();

                for (String flagName : flagValuesToStage.keySet()) {
                  String stagedValue = flagValuesToStage.get(flagName);
                  String propertyName = "next_boot." + makeAconfigFlagPropertyName(
                      actualNamespace, flagName);

                  if (!propertyName.matches(SYSTEM_PROPERTY_VALID_CHARACTERS_REGEX)
                      || propertyName.contains(SYSTEM_PROPERTY_INVALID_SUBSTRING)) {
                    logErr("unable to construct system property for " + actualNamespace
                        + "/" + flagName);
              for (String flagName : properties.getKeyset()) {
                  String flagValue = properties.getString(flagName, null);
                  if (flagName == null || flagValue == null) {
                      continue;
                  }

                  setProperty(propertyName, stagedValue);
                  int idx = flagName.indexOf(NAMESPACE_REBOOT_STAGING_DELIMITER);
                  if (idx == -1 || idx == flagName.length() - 1 || idx == 0) {
                      logErr("invalid staged flag: " + flagName);
                      continue;
                  }

                  String actualNamespace = flagName.substring(0, idx);
                  String actualFlagName = flagName.substring(idx+1);
                  String propertyName = "next_boot." + makeAconfigFlagPropertyName(
                      actualNamespace, actualFlagName);

                  setProperty(propertyName, flagValue);
              }

              // send prop stage request to new storage
              if (enableAconfigStorageDaemon()) {
                  stageFlagsInNewStorage(propsToStage);
                  stageFlagsInNewStorage(properties);
              }

        });
@@ -607,26 +603,34 @@ public class SettingsToPropertiesMapper {
     * @param propsToStage
     */
    @VisibleForTesting
    static void stageFlagsInNewStorage(HashMap<String, HashMap<String, String>> propsToStage) {
    static void stageFlagsInNewStorage(DeviceConfig.Properties props) {
        // write aconfigd requests proto to proto output stream
        int num_requests = 0;
        ProtoOutputStream requests = new ProtoOutputStream();
        for (HashMap.Entry<String, HashMap<String, String>> entry : propsToStage.entrySet()) {
            String actualNamespace = entry.getKey();
            HashMap<String, String> flagValuesToStage = entry.getValue();
            for (String fullFlagName : flagValuesToStage.keySet()) {
                String stagedValue = flagValuesToStage.get(fullFlagName);
                int idx = fullFlagName.lastIndexOf(".");
        for (String flagName : props.getKeyset()) {
            String flagValue = props.getString(flagName, null);
            if (flagName == null || flagValue == null) {
                continue;
            }

            int idx = flagName.indexOf("*");
            if (idx == -1 || idx == flagName.length() - 1 || idx == 0) {
                logErr("invalid local flag override: " + flagName);
                continue;
            }
            String actualNamespace = flagName.substring(0, idx);
            String fullFlagName = flagName.substring(idx+1);

            idx = fullFlagName.lastIndexOf(".");
            if (idx == -1) {
                logErr("invalid flag name: " + fullFlagName);
                continue;
            }
            String packageName = fullFlagName.substring(0, idx);
                String flagName = fullFlagName.substring(idx+1);
                writeFlagOverrideRequest(requests, packageName, flagName, stagedValue, false);
            String realFlagName = fullFlagName.substring(idx+1);
            writeFlagOverrideRequest(requests, packageName, realFlagName, flagValue, false);
            ++num_requests;
        }
        }

        if (num_requests == 0) {
          return;
@@ -665,63 +669,6 @@ public class SettingsToPropertiesMapper {
        return propertyName;
    }

    /**
     * Get the flags that need to be staged in sys prop, only these with a real value
     * change needs to be staged in sys prop. Otherwise, the flag stage is useless and
     * create performance problem at sys prop side.
     * @param properties
     * @return a hash map of namespace name to actual flags to stage
     */
    @VisibleForTesting
    static HashMap<String, HashMap<String, String>> getStagedFlagsWithValueChange(
        DeviceConfig.Properties properties) {

      // sort flags by actual namespace of the flag
      HashMap<String, HashMap<String, String>> stagedProps = new HashMap<>();
      for (String flagName : properties.getKeyset()) {
        int idx = flagName.indexOf(NAMESPACE_REBOOT_STAGING_DELIMITER);
        if (idx == -1 || idx == flagName.length() - 1 || idx == 0) {
          logErr("invalid staged flag: " + flagName);
          continue;
        }
        String actualNamespace = flagName.substring(0, idx);
        String actualFlagName = flagName.substring(idx+1);
        HashMap<String, String> flagStagedValues = stagedProps.get(actualNamespace);
        if (flagStagedValues == null) {
          flagStagedValues = new HashMap<String, String>();
          stagedProps.put(actualNamespace, flagStagedValues);
        }
        flagStagedValues.put(actualFlagName, properties.getString(flagName, null));
      }

      // for each namespace, find flags with real flag value change
      HashMap<String, HashMap<String, String>> propsToStage = new HashMap<>();
      for (HashMap.Entry<String, HashMap<String, String>> entry : stagedProps.entrySet()) {
        String actualNamespace = entry.getKey();
        HashMap<String, String> flagStagedValues = entry.getValue();
        Map<String, String> flagCurrentValues = Settings.Config.getStrings(
            actualNamespace, new ArrayList<String>(flagStagedValues.keySet()));

        HashMap<String, String> flagsToStage = new HashMap<>();
        for (String flagName : flagStagedValues.keySet()) {
          String stagedValue = flagStagedValues.get(flagName);
          String currentValue = flagCurrentValues.get(flagName);
          if (stagedValue == null) {
            continue;
          }
          if (currentValue == null || !stagedValue.equalsIgnoreCase(currentValue)) {
            flagsToStage.put(flagName, stagedValue);
          }
        }

        if (!flagsToStage.isEmpty()) {
          propsToStage.put(actualNamespace, flagsToStage);
        }
      }

      return propsToStage;
    }

    private void setProperty(String key, String value) {
        // Check if need to clear the property
        if (value == null) {
+0 −55
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import android.content.ContentResolver;
import android.os.SystemProperties;
import android.provider.Settings;
import android.provider.DeviceConfig.Properties;
import android.text.TextUtils;

import com.android.dx.mockito.inline.extended.ExtendedMockito;
@@ -43,7 +42,6 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

/**
 * Test SettingsToPropertiesMapper.
@@ -63,7 +61,6 @@ public class SettingsToPropertiesMapperTest {

    private HashMap<String, String> mSystemSettingsMap;
    private HashMap<String, String> mGlobalSettingsMap;
    private HashMap<String, String> mConfigSettingsMap;

    @Before
    public void setUp() throws Exception {
@@ -74,11 +71,9 @@ public class SettingsToPropertiesMapperTest {
                        .spyStatic(SystemProperties.class)
                        .spyStatic(Settings.Global.class)
                        .spyStatic(SettingsToPropertiesMapper.class)
                        .spyStatic(Settings.Config.class)
                        .startMocking();
        mSystemSettingsMap = new HashMap<>();
        mGlobalSettingsMap = new HashMap<>();
        mConfigSettingsMap = new HashMap<>();

        // Mock SystemProperties setter and various getters
        doAnswer((Answer<Void>) invocationOnMock -> {
@@ -106,21 +101,6 @@ public class SettingsToPropertiesMapperTest {
                }
        ).when(() -> Settings.Global.getString(any(), anyString()));

        // Mock Settings.Config getstrings method
        doAnswer((Answer<Map<String, String>>) invocationOnMock -> {
                    String namespace = invocationOnMock.getArgument(0);
                    List<String> flags = invocationOnMock.getArgument(1);
                    HashMap<String, String> values = new HashMap<>();
                    for (String flag : flags) {
                      String value = mConfigSettingsMap.get(namespace + "/" + flag);
                      if (value != null) {
                        values.put(flag, value);
                      }
                    }
                    return values;
                }
        ).when(() -> Settings.Config.getStrings(anyString(), any()));

        mTestMapper = new SettingsToPropertiesMapper(
            mMockContentResolver, TEST_MAPPING, new String[] {}, new String[] {});
    }
@@ -259,39 +239,4 @@ public class SettingsToPropertiesMapperTest {
        Assert.assertTrue(categories.contains("category2"));
        Assert.assertTrue(categories.contains("category3"));
    }

  @Test
  public void testGetStagedFlagsWithValueChange() {
    // mock up what is in the setting already
    mConfigSettingsMap.put("namespace_1/flag_1", "true");
    mConfigSettingsMap.put("namespace_1/flag_2", "true");

    // mock up input
    String namespace = "staged";
    Map<String, String> keyValueMap = new HashMap<>();
    // case 1: existing prop, stage the same value
    keyValueMap.put("namespace_1*flag_1", "true");
    // case 2: existing prop, stage a different value
    keyValueMap.put("namespace_1*flag_2", "false");
    // case 3: new prop
    keyValueMap.put("namespace_2*flag_1", "true");
    Properties props = new Properties(namespace, keyValueMap);

    HashMap<String, HashMap<String, String>> toStageProps =
        SettingsToPropertiesMapper.getStagedFlagsWithValueChange(props);

    HashMap<String, String> namespace_1_to_stage = toStageProps.get("namespace_1");
    HashMap<String, String> namespace_2_to_stage = toStageProps.get("namespace_2");
    Assert.assertTrue(namespace_1_to_stage != null);
    Assert.assertTrue(namespace_2_to_stage != null);

    String namespace_1_flag_1 = namespace_1_to_stage.get("flag_1");
    String namespace_1_flag_2 = namespace_1_to_stage.get("flag_2");
    String namespace_2_flag_1 = namespace_2_to_stage.get("flag_1");
    Assert.assertTrue(namespace_1_flag_1 == null);
    Assert.assertTrue(namespace_1_flag_2 != null);
    Assert.assertTrue(namespace_2_flag_1 != null);
    Assert.assertTrue(namespace_1_flag_2.equals("false"));
    Assert.assertTrue(namespace_2_flag_1.equals("true"));
  }
}