Make new storage and old starge seperate

This commit separates the new and old storage accessing code, so we can
ramp a flag to switch the storage used in java codegen from old to new.

This change doens't include switch the storage for exported mode. For
exported mode, it will still use DeviceConfig as the storage.

Bug: 368135182
Test: atest aconfig.test.java
Change-Id: I6e45d1ca98b3c7aeb1937669a8074805181903fe
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index 1ac58c1..a34166d 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -137,6 +137,7 @@
     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 @@
         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,97 +509,39 @@
             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#"
-            @Override
-            @com.android.aconfig.annotations.AconfigFlagAccessor
-            @UnsupportedAppUsage
-            public boolean disabledRo() {
-                return false;
-            }
-            @Override
-            @com.android.aconfig.annotations.AconfigFlagAccessor
-            @UnsupportedAppUsage
-            public boolean disabledRw() {
-                if (!aconfig_test_is_cached) {
-                    load_overrides_aconfig_test();
+            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);
                 }
-                return disabledRw;
+                isCached = true;
             }
-            @Override
-            @com.android.aconfig.annotations.AconfigFlagAccessor
-            @UnsupportedAppUsage
-            public boolean disabledRwExported() {
-                if (!aconfig_test_is_cached) {
-                    load_overrides_aconfig_test();
-                }
-                return disabledRwExported;
-            }
-            @Override
-            @com.android.aconfig.annotations.AconfigFlagAccessor
-            @UnsupportedAppUsage
-            public boolean disabledRwInOtherNamespace() {
-                if (!other_namespace_is_cached) {
-                    load_overrides_other_namespace();
-                }
-                return disabledRwInOtherNamespace;
-            }
-            @Override
-            @com.android.aconfig.annotations.AconfigFlagAccessor
-            @UnsupportedAppUsage
-            public boolean enabledFixedRo() {
-                return true;
-            }
-            @Override
-            @com.android.aconfig.annotations.AconfigFlagAccessor
-            @UnsupportedAppUsage
-            public boolean enabledFixedRoExported() {
-                return true;
-            }
-            @Override
-            @com.android.aconfig.annotations.AconfigFlagAccessor
-            @UnsupportedAppUsage
-            public boolean enabledRo() {
-                return true;
-            }
-            @Override
-            @com.android.aconfig.annotations.AconfigFlagAccessor
-            @UnsupportedAppUsage
-            public boolean enabledRoExported() {
-                return true;
-            }
-            @Override
-            @com.android.aconfig.annotations.AconfigFlagAccessor
-            @UnsupportedAppUsage
-            public boolean enabledRw() {
-                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");
@@ -636,188 +580,104 @@
                     );
                 }
                 other_namespace_is_cached = true;
-            }"#
-            + expected_featureflagsmpl_content_2;
+            }
+
+            @Override
+            @com.android.aconfig.annotations.AconfigFlagAccessor
+            @UnsupportedAppUsage
+            public boolean disabledRo() {
+                return false;
+            }
+            @Override
+            @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
+            @com.android.aconfig.annotations.AconfigFlagAccessor
+            @UnsupportedAppUsage
+            public boolean enabledFixedRo() {
+                return true;
+            }
+            @Override
+            @com.android.aconfig.annotations.AconfigFlagAccessor
+            @UnsupportedAppUsage
+            public boolean enabledFixedRoExported() {
+                return true;
+            }
+            @Override
+            @com.android.aconfig.annotations.AconfigFlagAccessor
+            @UnsupportedAppUsage
+            public boolean enabledRo() {
+                return true;
+            }
+            @Override
+            @com.android.aconfig.annotations.AconfigFlagAccessor
+            @UnsupportedAppUsage
+            public boolean enabledRoExported() {
+                return true;
+            }
+            @Override
+            @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 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 @@
             private static boolean enabledFixedRoExported = false;
             private static boolean enabledRoExported = false;
 
-
             private void load_overrides_aconfig_test() {
                 try {
                     Properties properties = DeviceConfig.getProperties("aconfig_test");
@@ -933,21 +792,21 @@
             @Override
             public boolean disabledRwExported() {
                 if (!aconfig_test_is_cached) {
-                    load_overrides_aconfig_test();
+                        load_overrides_aconfig_test();
                 }
                 return disabledRwExported;
             }
             @Override
             public boolean enabledFixedRoExported() {
                 if (!aconfig_test_is_cached) {
-                    load_overrides_aconfig_test();
+                        load_overrides_aconfig_test();
                 }
                 return enabledFixedRoExported;
             }
             @Override
             public boolean enabledRoExported() {
                 if (!aconfig_test_is_cached) {
-                    load_overrides_aconfig_test();
+                        load_overrides_aconfig_test();
                 }
                 return enabledRoExported;
             }
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
index bc01aa4..d1cf191 100644
--- a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
@@ -9,56 +9,50 @@
 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- }}
 
 {{ for flag in flag_elements }}
-{{- if flag.is_read_write }}
+{{ -if flag.is_read_write }}
     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;
-            try \{
-                reader = new StorageInternalReader("{container}", "{package_name}");
-            } catch (Exception e) \{
-                reader = null;
-            }
+        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) \{
+            throw new RuntimeException("Cannot read flag in codegen", e);
         }
-
-        useNewStorageValueAndDiscardOld =
-            DeviceConfig.getBoolean("core_experiments_team_internal", "com.android.providers.settings.use_new_storage_value", false);
+        isCached = true;
     }
+{{ endif }}
 
-{{ -endif }}
-{{ -endif }}
+
 {{ for namespace_with_flags in namespace_flags }}
     private void load_overrides_{namespace_with_flags.namespace}() \{
         try \{
@@ -80,34 +74,9 @@
             );
         }
         {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 @@
     @UnsupportedAppUsage
 {{ -endif }}
     public boolean {flag.method_name}() \{
+{{ -if not library_exported }}
 {{ -if flag.is_read_write }}
-        if (!{flag.device_config_namespace}_is_cached) \{
-            load_overrides_{flag.device_config_namespace}();
+        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 }}