aconfig: cache flag value in generated java code

This change add cache in generated jave code to improve the performance.

The cache is a DeviceConfig.Properties. One Properties contains all
flag values from the given namesapce.

The Properties for a given namespace is initialized as null, and the
first call for any flags in that Properties will trigger the call to
fetch all the values. After the first call, the flag values are stored
in the Properties, so the following calls will directly get the value
from the Properties instead from the backup storage.

Test: atest aconfig.test.java
Bug: 307511846
Change-Id: Ic43626101c28099199b6faa419cf1945bd53b15d
diff --git a/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template b/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template
index 72a896f..933d6a7 100644
--- a/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template
+++ b/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template
@@ -11,7 +11,7 @@
         resetAll();
     }
 
-{{ for item in class_elements}}
+{{ for item in flag_elements}}
     @Override
     @UnsupportedAppUsage
     public boolean {item.method_name}() \{
@@ -41,7 +41,7 @@
 
     private Map<String, Boolean> mFlagMap = new HashMap<>(
         Map.ofEntries(
-            {{-for item in class_elements}}
+            {{-for item in flag_elements}}
             Map.entry(Flags.FLAG_{item.flag_name_constant_suffix}, false)
             {{ -if not @last }},{{ endif }}
             {{ -endfor }}
diff --git a/tools/aconfig/templates/FeatureFlags.java.template b/tools/aconfig/templates/FeatureFlags.java.template
index 02305e6..da850ae 100644
--- a/tools/aconfig/templates/FeatureFlags.java.template
+++ b/tools/aconfig/templates/FeatureFlags.java.template
@@ -4,7 +4,7 @@
 
 /** @hide */
 public interface FeatureFlags \{
-{{ for item in class_elements}}
+{{ for item in flag_elements }}
 {{ -if not item.is_read_write }}
 {{ -if item.default_value }}
     @com.android.aconfig.annotations.AssumeTrueForR8
diff --git a/tools/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/templates/FeatureFlagsImpl.java.template
index 1620dfe..ff089df 100644
--- a/tools/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/templates/FeatureFlagsImpl.java.template
@@ -4,45 +4,58 @@
 {{ if not is_test_mode }}
 {{ if is_read_write- }}
 import android.provider.DeviceConfig;
+import android.provider.DeviceConfig.Properties;
 {{ endif }}
 /** @hide */
 public final class FeatureFlagsImpl implements FeatureFlags \{
-{{ for item in class_elements}}
+{{ if is_read_write- }}
+{{ for properties in properties_set }}
+    private Properties {properties};
+{{ endfor }}
+{{ endif- }}
+
+{{ for flag in flag_elements }}
     @Override
     @UnsupportedAppUsage
-    public boolean {item.method_name}() \{
-    {{ -if item.is_read_write }}
-        return getValue(
-            "{item.device_config_namespace}",
-            "{item.device_config_flag}",
-            {item.default_value}
-        );
+    public boolean {flag.method_name}() \{
+    {{ -if flag.is_read_write }}
+        if ({flag.properties} == null) \{
+            {flag.properties} =
+                getProperties(
+                    "{flag.device_config_namespace}",
+                    "{flag.device_config_flag}"
+                );
+        }
+        return {flag.properties}
+                .getBoolean(
+                    "{flag.device_config_flag}",
+                    {flag.default_value}
+                );
     {{ else }}
-        return {item.default_value};
+        return {flag.default_value};
     {{ endif- }}
     }
 {{ endfor }}
-{{ if is_read_write- }}
-    private boolean getValue(String nameSpace,
-        String flagName, boolean defaultValue) \{
-        boolean value = defaultValue;
+
+{{ -if is_read_write }}
+    private Properties getProperties(
+            String namespace,
+            String flagName) \{
+        Properties properties = null;
         try \{
-            value = DeviceConfig.getBoolean(
-                nameSpace,
-                flagName,
-                defaultValue
-            );
+            properties = DeviceConfig.getProperties(namespace);
         } catch (NullPointerException e) \{
             throw new RuntimeException(
-                "Cannot read value of flag " + flagName + " 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.",
+                "Cannot read value of flag " + flagName + " 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
             );
         }
-        return value;
+
+        return properties;
     }
 {{ endif- }}
 }
@@ -50,10 +63,10 @@
 {#- Generate only stub if in test mode #}
 /** @hide */
 public final class FeatureFlagsImpl implements FeatureFlags \{
-{{ for item in class_elements}}
+{{ for flag in flag_elements }}
     @Override
     @UnsupportedAppUsage
-    public boolean {item.method_name}() \{
+    public boolean {flag.method_name}() \{
         throw new UnsupportedOperationException(
             "Method is not implemented.");
     }
diff --git a/tools/aconfig/templates/Flags.java.template b/tools/aconfig/templates/Flags.java.template
index 66c4c5a..cf6604c 100644
--- a/tools/aconfig/templates/Flags.java.template
+++ b/tools/aconfig/templates/Flags.java.template
@@ -5,11 +5,11 @@
 
 /** @hide */
 public final class Flags \{
-{{- for item in class_elements}}
+{{- for item in flag_elements}}
     /** @hide */
     public static final String FLAG_{item.flag_name_constant_suffix} = "{item.device_config_flag}";
 {{- endfor }}
-{{ for item in class_elements}}
+{{ for item in flag_elements}}
 {{ -if not item.is_read_write }}
 {{ -if item.default_value }}
     @com.android.aconfig.annotations.AssumeTrueForR8