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

Commit 75eadf0f authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Make new storage and old starge seperate" into main am: cebf3ed9 am: de2e4869

parents 92ab65c6 de2e4869
Loading
Loading
Loading
Loading
+97 −238
Original line number Diff line number Diff line
@@ -137,6 +137,7 @@ struct FlagElement {
    pub default_value: bool,
    pub device_config_namespace: String,
    pub device_config_flag: String,
    pub flag_name: String,
    pub flag_name_constant_suffix: String,
    pub flag_offset: u16,
    pub is_read_write: bool,
@@ -156,6 +157,7 @@ fn create_flag_element(
        default_value: pf.state() == ProtoFlagState::ENABLED,
        device_config_namespace: pf.namespace().to_string(),
        device_config_flag,
        flag_name: pf.name().to_string(),
        flag_name_constant_suffix: pf.name().to_ascii_uppercase(),
        flag_offset: *flag_offsets.get(pf.name()).expect("didnt find package offset :("),
        is_read_write: pf.permission() == ProtoFlagPermission::READ_WRITE,
@@ -507,25 +509,79 @@ mod tests {
            private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl();
        }"#;

        let expected_featureflagsmpl_content_0 = r#"
        let expected_featureflagsmpl_content = r#"
        package com.android.aconfig.test;
        // TODO(b/303773055): Remove the annotation after access issue is resolved.
        import android.compat.annotation.UnsupportedAppUsage;
        import android.provider.DeviceConfig;
        import android.provider.DeviceConfig.Properties;
        "#;
        import android.aconfig.storage.StorageInternalReader;
        import java.nio.file.Files;
        import java.nio.file.Paths;

        let expected_featureflagsmpl_content_1 = r#"
        /** @hide */
        public final class FeatureFlagsImpl implements FeatureFlags {
            private static final boolean isReadFromNew = Files.exists(Paths.get("/metadata/aconfig/boot/enable_only_new_storage"));
            private static volatile boolean isCached = false;
            private static volatile boolean aconfig_test_is_cached = false;
            private static volatile boolean other_namespace_is_cached = false;
            private static boolean disabledRw = false;
            private static boolean disabledRwExported = false;
            private static boolean disabledRwInOtherNamespace = false;
            private static boolean enabledRw = true;
        "#;
        let expected_featureflagsmpl_content_2 = r#"
            private void init() {
                StorageInternalReader reader = null;
                try {
                    reader = new StorageInternalReader("system", "com.android.aconfig.test");
                    disabledRw = reader.getBooleanFlagValue(1);
                    disabledRwExported = reader.getBooleanFlagValue(2);
                    enabledRw = reader.getBooleanFlagValue(8);
                    disabledRwInOtherNamespace = reader.getBooleanFlagValue(3);
                } catch (Exception e) {
                    throw new RuntimeException("Cannot read flag in codegen", e);
                }
                isCached = true;
            }
            private void load_overrides_aconfig_test() {
                try {
                    Properties properties = DeviceConfig.getProperties("aconfig_test");
                    disabledRw =
                        properties.getBoolean(Flags.FLAG_DISABLED_RW, false);
                    disabledRwExported =
                        properties.getBoolean(Flags.FLAG_DISABLED_RW_EXPORTED, false);
                    enabledRw =
                        properties.getBoolean(Flags.FLAG_ENABLED_RW, true);
                } catch (NullPointerException e) {
                    throw new RuntimeException(
                        "Cannot read value from namespace aconfig_test "
                        + "from DeviceConfig. It could be that the code using flag "
                        + "executed before SettingsProvider initialization. Please use "
                        + "fixed read-only flag by adding is_fixed_read_only: true in "
                        + "flag declaration.",
                        e
                    );
                }
                aconfig_test_is_cached = true;
            }

            private void load_overrides_other_namespace() {
                try {
                    Properties properties = DeviceConfig.getProperties("other_namespace");
                    disabledRwInOtherNamespace =
                        properties.getBoolean(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false);
                } catch (NullPointerException e) {
                    throw new RuntimeException(
                        "Cannot read value from namespace other_namespace "
                        + "from DeviceConfig. It could be that the code using flag "
                        + "executed before SettingsProvider initialization. Please use "
                        + "fixed read-only flag by adding is_fixed_read_only: true in "
                        + "flag declaration.",
                        e
                    );
                }
                other_namespace_is_cached = true;
            }

            @Override
            @com.android.aconfig.annotations.AconfigFlagAccessor
            @UnsupportedAppUsage
@@ -536,27 +592,45 @@ mod tests {
            @com.android.aconfig.annotations.AconfigFlagAccessor
            @UnsupportedAppUsage
            public boolean disabledRw() {
                if (isReadFromNew) {
                    if (!isCached) {
                        init();
                    }
                } else {
                    if (!aconfig_test_is_cached) {
                        load_overrides_aconfig_test();
                    }
                }
                return disabledRw;
            }
            @Override
            @com.android.aconfig.annotations.AconfigFlagAccessor
            @UnsupportedAppUsage
            public boolean disabledRwExported() {
                if (isReadFromNew) {
                    if (!isCached) {
                        init();
                    }
                } else {
                    if (!aconfig_test_is_cached) {
                        load_overrides_aconfig_test();
                    }
                }
                return disabledRwExported;
            }
            @Override
            @com.android.aconfig.annotations.AconfigFlagAccessor
            @UnsupportedAppUsage
            public boolean disabledRwInOtherNamespace() {
                if (isReadFromNew) {
                    if (!isCached) {
                        init();
                    }
                } else {
                    if (!other_namespace_is_cached) {
                        load_overrides_other_namespace();
                    }
                }
                return disabledRwInOtherNamespace;
            }
            @Override
@@ -587,237 +661,23 @@ mod tests {
            @com.android.aconfig.annotations.AconfigFlagAccessor
            @UnsupportedAppUsage
            public boolean enabledRw() {
                if (isReadFromNew) {
                    if (!isCached) {
                        init();
                    }
                } else {
                    if (!aconfig_test_is_cached) {
                        load_overrides_aconfig_test();
                    }
                }
                return enabledRw;
            }
        }
        "#;

        let expect_featureflagsimpl_content_old = expected_featureflagsmpl_content_0.to_owned()
            + expected_featureflagsmpl_content_1
            + r#"
            private void load_overrides_aconfig_test() {
                try {
                    Properties properties = DeviceConfig.getProperties("aconfig_test");
                    disabledRw =
                        properties.getBoolean(Flags.FLAG_DISABLED_RW, false);
                    disabledRwExported =
                        properties.getBoolean(Flags.FLAG_DISABLED_RW_EXPORTED, false);
                    enabledRw =
                        properties.getBoolean(Flags.FLAG_ENABLED_RW, true);
                } catch (NullPointerException e) {
                    throw new RuntimeException(
                        "Cannot read value from namespace aconfig_test "
                        + "from DeviceConfig. It could be that the code using flag "
                        + "executed before SettingsProvider initialization. Please use "
                        + "fixed read-only flag by adding is_fixed_read_only: true in "
                        + "flag declaration.",
                        e
                    );
                }
                aconfig_test_is_cached = true;
            }

            private void load_overrides_other_namespace() {
                try {
                    Properties properties = DeviceConfig.getProperties("other_namespace");
                    disabledRwInOtherNamespace =
                        properties.getBoolean(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false);
                } catch (NullPointerException e) {
                    throw new RuntimeException(
                        "Cannot read value from namespace other_namespace "
                        + "from DeviceConfig. It could be that the code using flag "
                        + "executed before SettingsProvider initialization. Please use "
                        + "fixed read-only flag by adding is_fixed_read_only: true in "
                        + "flag declaration.",
                        e
                    );
                }
                other_namespace_is_cached = true;
            }"#
            + expected_featureflagsmpl_content_2;

        let mut file_set = HashMap::from([
            ("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()),
            (
                "com/android/aconfig/test/FeatureFlagsImpl.java",
                &expect_featureflagsimpl_content_old,
            ),
            ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT),
            (
                "com/android/aconfig/test/CustomFeatureFlags.java",
                EXPECTED_CUSTOMFEATUREFLAGS_CONTENT,
            ),
            (
                "com/android/aconfig/test/FakeFeatureFlagsImpl.java",
                EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
            ),
        ]);

        for file in generated_files {
            let file_path = file.path.to_str().unwrap();
            assert!(file_set.contains_key(file_path), "Cannot find {}", file_path);
            assert_eq!(
                None,
                crate::test::first_significant_code_diff(
                    file_set.get(file_path).unwrap(),
                    &String::from_utf8(file.contents).unwrap()
                ),
                "File {} content is not correct",
                file_path
            );
            file_set.remove(file_path);
        }

        assert!(file_set.is_empty());

        let parsed_flags = crate::test::parse_test_flags();
        let mode = CodegenMode::Production;
        let modified_parsed_flags =
            crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap();
        let flag_ids =
            assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap();
        let generated_files = generate_java_code(
            crate::test::TEST_PACKAGE,
            modified_parsed_flags.into_iter(),
            mode,
            flag_ids,
            true,
        )
        .unwrap();

        let expect_featureflagsimpl_content_new = expected_featureflagsmpl_content_0.to_owned()
            + r#"
            import android.aconfig.storage.StorageInternalReader;
            import android.util.Log;
            "#
            + expected_featureflagsmpl_content_1
            + r#"
        StorageInternalReader reader;
        boolean readFromNewStorage;

        boolean useNewStorageValueAndDiscardOld = false;

        private final static String TAG = "AconfigJavaCodegen";
        private final static String SUCCESS_LOG = "success: %s value matches";
        private final static String MISMATCH_LOG = "error: %s value mismatch, new storage value is %s, old storage value is %s";
        private final static String ERROR_LOG = "error: failed to read flag value";

        private void init() {
            if (reader != null) return;
            if (DeviceConfig.getBoolean("core_experiments_team_internal", "com.android.providers.settings.storage_test_mission_1", false)) {
                readFromNewStorage = true;
                try {
                    reader = new StorageInternalReader("system", "com.android.aconfig.test");
                } catch (Exception e) {
                    reader = null;
                }
            }

            useNewStorageValueAndDiscardOld =
                DeviceConfig.getBoolean("core_experiments_team_internal", "com.android.providers.settings.use_new_storage_value", false);
        }

        private void load_overrides_aconfig_test() {
            try {
                Properties properties = DeviceConfig.getProperties("aconfig_test");
                disabledRw =
                    properties.getBoolean(Flags.FLAG_DISABLED_RW, false);
                disabledRwExported =
                    properties.getBoolean(Flags.FLAG_DISABLED_RW_EXPORTED, false);
                enabledRw =
                    properties.getBoolean(Flags.FLAG_ENABLED_RW, true);
            } catch (NullPointerException e) {
                throw new RuntimeException(
                    "Cannot read value from namespace aconfig_test "
                    + "from DeviceConfig. It could be that the code using flag "
                    + "executed before SettingsProvider initialization. Please use "
                    + "fixed read-only flag by adding is_fixed_read_only: true in "
                    + "flag declaration.",
                    e
                );
            }
            aconfig_test_is_cached = true;
            init();
            if (readFromNewStorage && reader != null) {
                boolean val;
                try {
                    val = reader.getBooleanFlagValue(1);
                    if (val != disabledRw) {
                        Log.w(TAG, String.format(MISMATCH_LOG, "disabledRw", val, disabledRw));
                    }

                    if (useNewStorageValueAndDiscardOld) {
                        disabledRw = val;
                    }

                    val = reader.getBooleanFlagValue(2);
                    if (val != disabledRwExported) {
                        Log.w(TAG, String.format(MISMATCH_LOG, "disabledRwExported", val, disabledRwExported));
                    }

                    if (useNewStorageValueAndDiscardOld) {
                        disabledRwExported = val;
                    }

                    val = reader.getBooleanFlagValue(8);
                    if (val != enabledRw) {
                        Log.w(TAG, String.format(MISMATCH_LOG, "enabledRw", val, enabledRw));
                    }

                    if (useNewStorageValueAndDiscardOld) {
                        enabledRw = val;
                    }

                } catch (Exception e) {
                    Log.e(TAG, ERROR_LOG, e);
                }
            }
        }

        private void load_overrides_other_namespace() {
            try {
                Properties properties = DeviceConfig.getProperties("other_namespace");
                disabledRwInOtherNamespace =
                    properties.getBoolean(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false);
            } catch (NullPointerException e) {
                throw new RuntimeException(
                    "Cannot read value from namespace other_namespace "
                    + "from DeviceConfig. It could be that the code using flag "
                    + "executed before SettingsProvider initialization. Please use "
                    + "fixed read-only flag by adding is_fixed_read_only: true in "
                    + "flag declaration.",
                    e
                );
            }
            other_namespace_is_cached = true;
            init();
            if (readFromNewStorage && reader != null) {
                boolean val;
                try {
                    val = reader.getBooleanFlagValue(3);
                    if (val != disabledRwInOtherNamespace) {
                        Log.w(TAG, String.format(MISMATCH_LOG, "disabledRwInOtherNamespace", val, disabledRwInOtherNamespace));
                    }

                    if (useNewStorageValueAndDiscardOld) {
                        disabledRwInOtherNamespace = val;
                    }

                } catch (Exception e) {
                    Log.e(TAG, ERROR_LOG, e);
                }
            }
        }"# + expected_featureflagsmpl_content_2;

        let mut file_set = HashMap::from([
            ("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()),
            (
                "com/android/aconfig/test/FeatureFlagsImpl.java",
                &expect_featureflagsimpl_content_new,
            ),
            ("com/android/aconfig/test/FeatureFlagsImpl.java", expected_featureflagsmpl_content),
            ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT),
            (
                "com/android/aconfig/test/CustomFeatureFlags.java",
@@ -908,7 +768,6 @@ mod tests {
            private static boolean enabledFixedRoExported = false;
            private static boolean enabledRoExported = false;


            private void load_overrides_aconfig_test() {
                try {
                    Properties properties = DeviceConfig.getProperties("aconfig_test");
+40 −59
Original line number Diff line number Diff line
@@ -9,18 +9,20 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;


{{ -if not library_exported }}
{{ -if allow_instrumentation }}
import android.aconfig.storage.StorageInternalReader;
import android.util.Log;
{{ -endif }}
import java.nio.file.Files;
import java.nio.file.Paths;
{{ -endif }}

{{ -endif }}
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags \{
{{ -if runtime_lookup_required }}
{{ -if not library_exported }}
    private static final boolean isReadFromNew = Files.exists(Paths.get("/metadata/aconfig/boot/enable_only_new_storage"));
    private static volatile boolean isCached = false;
{{ -endif }}
{{ -for namespace_with_flags in namespace_flags }}
    private static volatile boolean {namespace_with_flags.namespace}_is_cached = false;
{{ -endfor- }}
@@ -30,35 +32,27 @@ public final class FeatureFlagsImpl implements FeatureFlags \{
    private static boolean {flag.method_name} = {flag.default_value};
{{ -endif }}
{{ -endfor }}
{{ -if not library_exported }}
{{ -if allow_instrumentation }}
    StorageInternalReader reader;
    boolean readFromNewStorage;

    boolean useNewStorageValueAndDiscardOld = false;

    private final static String TAG = "AconfigJavaCodegen";
    private final static String SUCCESS_LOG = "success: %s value matches";
    private final static String MISMATCH_LOG = "error: %s value mismatch, new storage value is %s, old storage value is %s";
    private final static String ERROR_LOG = "error: failed to read flag value";

{{ if not library_exported }}
    private void init() \{
        if (reader != null) return;
        if (DeviceConfig.getBoolean("core_experiments_team_internal", "com.android.providers.settings.storage_test_mission_1", false)) \{
            readFromNewStorage = true;
        StorageInternalReader reader = null;
        try \{
            reader = new StorageInternalReader("{container}", "{package_name}");
{{ for namespace_with_flags in namespace_flags }}
{{ -for flag in namespace_with_flags.flags }}
{{ if flag.is_read_write }}
            {flag.method_name} = reader.getBooleanFlagValue({flag.flag_offset});
{{ endif }}
{{ -endfor }}
{{ -endfor }}
        } catch (Exception e) \{
                reader = null;
            throw new RuntimeException("Cannot read flag in codegen", e);
        }
        isCached = true;
    }
{{ endif }}

        useNewStorageValueAndDiscardOld =
            DeviceConfig.getBoolean("core_experiments_team_internal", "com.android.providers.settings.use_new_storage_value", false);
    }

{{ -endif }}
{{ -endif }}
{{ for namespace_with_flags in namespace_flags }}
    private void load_overrides_{namespace_with_flags.namespace}() \{
        try \{
@@ -80,34 +74,9 @@ public final class FeatureFlagsImpl implements FeatureFlags \{
            );
        }
        {namespace_with_flags.namespace}_is_cached = true;
{{ -if not library_exported }}
{{ -if allow_instrumentation }}
        init();
        if (readFromNewStorage && reader != null) \{
            boolean val;
            try \{
{{ -for flag in namespace_with_flags.flags }}
{{ -if flag.is_read_write }}

                val = reader.getBooleanFlagValue({flag.flag_offset});
                if (val != {flag.method_name}) \{
                    Log.w(TAG, String.format(MISMATCH_LOG, "{flag.method_name}", val, {flag.method_name}));
                }

                if (useNewStorageValueAndDiscardOld) \{
                    {flag.method_name} = val;
                }

{{ -endif }}
{{ -endfor }}
            } catch (Exception e) \{
                    Log.e(TAG, ERROR_LOG, e);
            }
        }
{{ -endif }}
{{ -endif }}
    }
{{ endfor- }}

{{ -endif }}{#- end of runtime_lookup_required #}
{{ -for flag in flag_elements }}
    @Override
@@ -116,19 +85,31 @@ public final class FeatureFlagsImpl implements FeatureFlags \{
    @UnsupportedAppUsage
{{ -endif }}
    public boolean {flag.method_name}() \{
{{ -if not library_exported }}
{{ -if flag.is_read_write }}
        if (isReadFromNew) \{
            if (!isCached) \{
                init();
            }
        } else \{
            if (!{flag.device_config_namespace}_is_cached) \{
                load_overrides_{flag.device_config_namespace}();
            }
        }
        return {flag.method_name};
{{ -else }}
        return {flag.default_value};
{{ -endif }}
{{ else }}
        if (!{flag.device_config_namespace}_is_cached) \{
            load_overrides_{flag.device_config_namespace}();
        }
        return {flag.method_name};
{{ -endif }}
    }
{{ endfor }}
}
{{ else }}
{#- Generate only stub if in test mode #}
{{ else }} {#- Generate only stub if in test mode #}
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags \{
{{ for flag in flag_elements }}