Merge "fix potential encoding issues in remote actions" into main
diff --git a/core/packaging/flags.mk b/core/packaging/flags.mk
index 3b0bde8..a7e8d35 100644
--- a/core/packaging/flags.mk
+++ b/core/packaging/flags.mk
@@ -72,42 +72,28 @@
 # $(1): built aconfig flags file (out)
 # $(2): installed aconfig flags file (out)
 # $(3): input aconfig files for the partition (in)
-# $(4): file format, passed to `aconfig dump` (in)
-# $(5): text placed in aconfig file when no flags present (out)
 define generate-partition-aconfig-flag-file
 $(eval $(strip $(1)): PRIVATE_OUT := $(strip $(1)))
 $(eval $(strip $(1)): PRIVATE_IN := $(strip $(3)))
 $(strip $(1)): $(ACONFIG) $(strip $(3))
 	mkdir -p $$(dir $$(PRIVATE_OUT))
 	$$(if $$(PRIVATE_IN), \
-		$$(ACONFIG) dump --format $(4) --out $$(PRIVATE_OUT) \
+		$$(ACONFIG) dump --format protobuf --out $$(PRIVATE_OUT) \
 			$$(addprefix --cache ,$$(PRIVATE_IN)), \
-		echo -n "$(5)" > $$(PRIVATE_OUT) \
+		echo -n > $$(PRIVATE_OUT) \
 	)
 $(call copy-one-file, $(1), $(2))
 endef
 
 
 $(foreach partition, $(_FLAG_PARTITIONS), \
-	$(eval aconfig_flag_summaries_textproto.$(partition) := $(PRODUCT_OUT)/$(partition)/etc/aconfig_flags.textproto) \
 	$(eval aconfig_flag_summaries_protobuf.$(partition) := $(PRODUCT_OUT)/$(partition)/etc/aconfig_flags.pb) \
 	$(eval $(call generate-partition-aconfig-flag-file, \
-				$(TARGET_OUT_FLAGS)/$(partition)/aconfig_flags.textproto, \
-				$(aconfig_flag_summaries_textproto.$(partition)), \
-				$(sort $(foreach m,$(call register-names-for-partition, $(partition)), \
-					$(ALL_MODULES.$(m).ACONFIG_FILES) \
-				)), \
-				textproto, \
-				"# No aconfig flags" \
-	)) \
-	$(eval $(call generate-partition-aconfig-flag-file, \
 				$(TARGET_OUT_FLAGS)/$(partition)/aconfig_flags.pb, \
 				$(aconfig_flag_summaries_protobuf.$(partition)), \
 				$(sort $(foreach m,$(call register-names-for-partition, $(partition)), \
 					$(ALL_MODULES.$(m).ACONFIG_FILES) \
 				)), \
-				protobuf, \
-				"" \
 	)) \
 )
 
@@ -117,7 +103,6 @@
 required_flags_files := \
 		$(sort $(foreach partition, $(filter $(IMAGES_TO_BUILD), $(_FLAG_PARTITIONS)), \
 			$(build_flag_summaries.$(partition)) \
-			$(aconfig_flag_summaries_textproto.$(partition)) \
 			$(aconfig_flag_summaries_protobuf.$(partition)) \
 		))
 
@@ -133,7 +118,6 @@
 required_flags_files:=
 $(foreach partition, $(_FLAG_PARTITIONS), \
 	$(eval build_flag_summaries.$(partition):=) \
-	$(eval aconfig_flag_summaries_textproto.$(partition):=) \
 	$(eval aconfig_flag_summaries_protobuf.$(partition):=) \
 )
 
diff --git a/core/product.mk b/core/product.mk
index 39c9eb7..ca65948 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -447,8 +447,6 @@
 
 _product_single_value_vars += PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API
 
-_product_list_vars += PRODUCT_RELEASE_CONFIG_MAPS
-
 .KATI_READONLY := _product_single_value_vars _product_list_vars
 _product_var_list :=$= $(_product_single_value_vars) $(_product_list_vars)
 
diff --git a/core/release_config.bzl b/core/release_config.bzl
index a29f3f2..0c08858 100644
--- a/core/release_config.bzl
+++ b/core/release_config.bzl
@@ -55,11 +55,6 @@
             },
             "declared_in": {"type": "string"},
         },
-        "optional_keys": {
-            "appends": {
-                "type": "bool",
-            },
-        },
     },
 }
 
@@ -80,23 +75,17 @@
     },
 }
 
-def flag(name, partitions, default, _kwmarker = (), appends = False):
+def flag(name, partitions, default):
     """Declare a flag.
 
     Args:
       name: name of the flag
       partitions: the partitions where this should be recorded.
       default: the default value of the flag.
-      _kwmarker: Used to detect argument misuse.
-      appends: Whether new values should be append (not replace) the old.
 
     Returns:
       A dictionary containing the flag declaration.
     """
-
-    # If specified, appends must be a keyword value.
-    if _kwmarker != ():
-        fail("Too many positional parameters")
     if not partitions:
         fail("At least 1 partition is required")
     if not name.startswith("RELEASE_"):
@@ -116,7 +105,6 @@
         "name": name,
         "partitions": partitions,
         "default": default,
-        "appends": appends,
     }
 
 def value(name, value):
@@ -165,12 +153,10 @@
 
     # Validate flags
     flag_names = []
-    flags_dict = {}
     for flag in all_flags:
         if flag["name"] in flag_names:
             fail(flag["declared_in"] + ": Duplicate declaration of flag " + flag["name"])
         flag_names.append(flag["name"])
-        flags_dict[flag["name"]] = flag
 
     # Record which flags go on which partition
     partitions = {}
@@ -184,21 +170,13 @@
             else:
                 partitions.setdefault(partition, []).append(flag["name"])
 
-    # Generate final values.
-    # Only declared flags may have a value.
+    # Validate values
+    # TODO(joeo): Disallow duplicate values after we've split AOSP and vendor flags.
     values = {}
     for value in all_values:
-        name = value["name"]
-        if name not in flag_names:
-            fail(value["set_in"] + ": Value set for undeclared build flag: " + name)
-        if flags_dict[name]["appends"]:
-            if name in values:
-                values[name]["value"] += " " + value["value"]
-                values[name]["set_in"] += " " + value["set_in"]
-            else:
-                values[name] = value
-        else:
-            values[name] = value
+        if value["name"] not in flag_names:
+            fail(value["set_in"] + ": Value set for undeclared build flag: " + value["name"])
+        values[value["name"]] = value
 
     # Collect values
     result = {
diff --git a/core/release_config.mk b/core/release_config.mk
index 5993e85..b72ee89 100644
--- a/core/release_config.mk
+++ b/core/release_config.mk
@@ -52,15 +52,6 @@
         ) \
     )
 
-# PRODUCT_RELEASE_CONFIG_MAPS is set by Soong using an initial run of product
-# config to capture only the list of config maps needed by the build.
-# Keep them in the order provided, but remove duplicates.
-$(foreach map,$(PRODUCT_RELEASE_CONFIG_MAPS), \
-    $(if $(filter $(map),$(config_map_files)),,$(eval config_map_files += $(map))) \
-)
-
-# Declare or extend a release-config.
-#
 # $1 config name
 # $2 release config files
 define declare-release-config
@@ -72,24 +63,10 @@
     $(eval _all_release_configs.$(strip $(1)).FILES := $(_all_release_configs.$(strip $(1)).FILES) $(strip $(2)))
 endef
 
-# Include the config map files and populate _flag_declaration_files.
-_flag_declaration_files :=
+# Include the config map files
 $(foreach f, $(config_map_files), \
-    $(eval FLAG_DECLARATION_FILES:= ) \
     $(eval _included := $(f)) \
     $(eval include $(f)) \
-    $(eval _flag_declaration_files += $(FLAG_DECLARATION_FILES)) \
-)
-FLAG_DECLARATION_FILES :=
-
-# Make sure that the flag definitions are included for vendor/google builds.
-# This decouples the change in vendor/google/release/release_config_map.mk
-# from this logic change.
-# TODO: Remove this once the vendor/google FLAG_DECLARATION_FILES change is there.
-$(if $(wildcard vendor/google/release/release_config_map.mk),\
-  $(if $(filter vendor/google/release/build_flags.bzl,$(_flag_declaration_files)),,\
-    $(eval _flag_declaration_files := vendor/google/release/build_flags.bzl $(_flag_declaration_files)) \
-  ) \
 )
 
 # If TARGET_RELEASE is set, fail if there is no matching release config
@@ -101,11 +78,7 @@
 else
     # Choose flag files
     # Don't sort this, use it in the order they gave us.
-    # Do allow duplicate entries, retaining only the first usage.
-    flag_value_files :=
-    $(foreach f,$(_all_release_configs.$(TARGET_RELEASE).FILES), \
-      $(if $(filter $(f),$(flag_value_files)),,$(eval flag_value_files += $(f)))\
-    )
+    flag_value_files := $(_all_release_configs.$(TARGET_RELEASE).FILES)
 endif
 else
 # Useful for finding scripts etc that aren't passing or setting TARGET_RELEASE
@@ -148,8 +121,21 @@
 # that we chose from the config map above.  Then we run that, and load the
 # results of that into the make environment.
 
-# _flag_declaration_files is the combined list of FLAG_DECLARATION_FILES set by
-# release_config_map.mk files above.
+# If this is a google source tree, restrict it to only the one file
+# which has OWNERS control.  If it isn't let others define their own.
+# TODO: Remove wildcard for build/release one when all branch manifests
+# have updated.
+flag_declaration_files := $(wildcard build/release/build_flags.bzl) \
+    $(if $(wildcard vendor/google/release/build_flags.bzl), \
+        vendor/google/release/build_flags.bzl, \
+        $(sort \
+            $(wildcard device/*/release/build_flags.bzl) \
+            $(wildcard device/*/*/release/build_flags.bzl) \
+            $(wildcard vendor/*/release/build_flags.bzl) \
+            $(wildcard vendor/*/*/release/build_flags.bzl) \
+        ) \
+    )
+
 
 # Because starlark can't find files with $(wildcard), write an entrypoint starlark script that
 # contains the result of the above wildcards for the starlark code to use.
@@ -159,8 +145,8 @@
 _c+=$(newline)$(space)d = dict(d)
 _c+=$(newline)$(space)d[k] = v
 _c+=$(newline)$(space)return d
-_c+=$(foreach f,$(_flag_declaration_files),$(newline)load("$(f)", flags_$(call filename_to_starlark,$(f)) = "flags"))
-_c+=$(newline)all_flags = [] $(foreach f,$(_flag_declaration_files),+ [add(x, "declared_in", "$(f)") for x in flags_$(call filename_to_starlark,$(f))])
+_c+=$(foreach f,$(flag_declaration_files),$(newline)load("$(f)", flags_$(call filename_to_starlark,$(f)) = "flags"))
+_c+=$(newline)all_flags = [] $(foreach f,$(flag_declaration_files),+ [add(x, "declared_in", "$(f)") for x in flags_$(call filename_to_starlark,$(f))])
 _c+=$(foreach f,$(flag_value_files),$(newline)load("//$(f)", values_$(call filename_to_starlark,$(f)) = "values"))
 _c+=$(newline)all_values = [] $(foreach f,$(flag_value_files),+ [add(x, "set_in", "$(f)") for x in values_$(call filename_to_starlark,$(f))])
 _c+=$(newline)variables_to_export_to_make = release_config(all_flags, all_values)
diff --git a/envsetup.sh b/envsetup.sh
index ee45280..3b76980 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -1880,6 +1880,10 @@
       >&2 echo "Couldn't locate the top of the tree. Try setting TOP."
       return 1
     fi
+
+    if [[ -z "${ANDROID_QUIET_BUILD:-}" && -n "${ANDROID_BUILD_BANNER}" ]]; then
+      echo "$ANDROID_BUILD_BANNER"
+    fi
 )
 
 function m()
diff --git a/target/product/angle_default.mk b/target/product/angle_default.mk
index bea0be6..fdfc7f5 100644
--- a/target/product/angle_default.mk
+++ b/target/product/angle_default.mk
@@ -15,9 +15,9 @@
 #
 
 # To enable ANGLE as the default system GLES drivers, add
-# $(call inherit-product, $(SRC_TARGET_DIR)/product/angle_enabled.mk) to the Makefile.
+# $(call inherit-product, $(SRC_TARGET_DIR)/product/angle_default.mk) to the Makefile.
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/angle_supported.mk)
 
-PRODUCT_VENDOR_PROPERTIES += \
+PRODUCT_SYSTEM_PROPERTIES += \
     persist.graphics.egl=angle
diff --git a/target/product/angle_supported.mk b/target/product/angle_supported.mk
index c83ff5f..59e6ea3 100644
--- a/target/product/angle_supported.mk
+++ b/target/product/angle_supported.mk
@@ -18,6 +18,7 @@
 # $(call inherit-product, $(SRC_TARGET_DIR)/product/angle_supported.mk) to the Makefile.
 # By default, this will allow ANGLE binaries to coexist with native GLES drivers.
 
+ifneq ($(RELEASE_ANGLE_ON_SYSTEM),true)
 PRODUCT_PACKAGES += \
     libEGL_angle \
     libGLESv1_CM_angle \
@@ -25,3 +26,4 @@
 
 # Set ro.gfx.angle.supported based on if ANGLE is installed in vendor partition
 PRODUCT_VENDOR_PROPERTIES += ro.gfx.angle.supported=true
+endif
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index eac3026..fd4318f 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -346,6 +346,15 @@
     WallpaperBackup
 endif
 
+# Moving angle from vendor to system
+ifeq ($(RELEASE_ANGLE_ON_SYSTEM),true)
+PRODUCT_PACKAGES += \
+    libEGL_angle \
+    libGLESv1_CM_angle \
+    libGLESv2_angle
+$(call soong_config_set,angle,angle_on_system,true)
+endif
+
 # For testing purposes
 ifeq ($(FORCE_AUDIO_SILENT), true)
     PRODUCT_SYSTEM_PROPERTIES += ro.audio.silent=1
diff --git a/tools/aconfig/fake_device_config/src/android/provider/DeviceConfig.java b/tools/aconfig/fake_device_config/src/android/provider/DeviceConfig.java
index 50b6289..dbb07ac 100644
--- a/tools/aconfig/fake_device_config/src/android/provider/DeviceConfig.java
+++ b/tools/aconfig/fake_device_config/src/android/provider/DeviceConfig.java
@@ -26,4 +26,14 @@
 	public static boolean getBoolean(String ns, String name, boolean def) {
 		return false;
 	}
+
+	public static Properties getProperties(String namespace, String... names) {
+		return new Properties();
+	}
+
+	public static class Properties {
+		public boolean getBoolean(String name, boolean def) {
+			return false;
+		}
+	}
 }
diff --git a/tools/aconfig/src/codegen_java.rs b/tools/aconfig/src/codegen_java.rs
index 43c2ecf..05ee0d7 100644
--- a/tools/aconfig/src/codegen_java.rs
+++ b/tools/aconfig/src/codegen_java.rs
@@ -16,6 +16,7 @@
 
 use anyhow::Result;
 use serde::Serialize;
+use std::collections::BTreeSet;
 use std::path::PathBuf;
 use tinytemplate::TinyTemplate;
 
@@ -31,12 +32,19 @@
 where
     I: Iterator<Item = &'a ProtoParsedFlag>,
 {
-    let class_elements: Vec<ClassElement> =
-        parsed_flags_iter.map(|pf| create_class_element(package, pf)).collect();
-    let is_read_write = class_elements.iter().any(|elem| elem.is_read_write);
+    let flag_elements: Vec<FlagElement> =
+        parsed_flags_iter.map(|pf| create_flag_element(package, pf)).collect();
+    let properties_set: BTreeSet<String> =
+        flag_elements.iter().map(|fe| format_property_name(&fe.device_config_namespace)).collect();
+    let is_read_write = flag_elements.iter().any(|elem| elem.is_read_write);
     let is_test_mode = codegen_mode == CodegenMode::Test;
-    let context =
-        Context { class_elements, is_test_mode, is_read_write, package_name: package.to_string() };
+    let context = Context {
+        flag_elements,
+        is_test_mode,
+        is_read_write,
+        properties_set,
+        package_name: package.to_string(),
+    };
     let mut template = TinyTemplate::new();
     template.add_template("Flags.java", include_str!("../templates/Flags.java.template"))?;
     template.add_template(
@@ -66,49 +74,62 @@
 
 #[derive(Serialize)]
 struct Context {
-    pub class_elements: Vec<ClassElement>,
+    pub flag_elements: Vec<FlagElement>,
     pub is_test_mode: bool,
     pub is_read_write: bool,
+    pub properties_set: BTreeSet<String>,
     pub package_name: String,
 }
 
 #[derive(Serialize)]
-struct ClassElement {
+struct FlagElement {
     pub default_value: bool,
     pub device_config_namespace: String,
     pub device_config_flag: String,
     pub flag_name_constant_suffix: String,
     pub is_read_write: bool,
     pub method_name: String,
+    pub properties: String,
 }
 
-fn create_class_element(package: &str, pf: &ProtoParsedFlag) -> ClassElement {
+fn create_flag_element(package: &str, pf: &ProtoParsedFlag) -> FlagElement {
     let device_config_flag = codegen::create_device_config_ident(package, pf.name())
         .expect("values checked at flag parse time");
-    ClassElement {
+    FlagElement {
         default_value: pf.state() == ProtoFlagState::ENABLED,
         device_config_namespace: pf.namespace().to_string(),
         device_config_flag,
         flag_name_constant_suffix: pf.name().to_ascii_uppercase(),
         is_read_write: pf.permission() == ProtoFlagPermission::READ_WRITE,
         method_name: format_java_method_name(pf.name()),
+        properties: format_property_name(pf.namespace()),
     }
 }
 
 fn format_java_method_name(flag_name: &str) -> String {
-    flag_name
-        .split('_')
-        .filter(|&word| !word.is_empty())
-        .enumerate()
-        .map(|(index, word)| {
-            if index == 0 {
-                word.to_ascii_lowercase()
-            } else {
-                word[0..1].to_ascii_uppercase() + &word[1..].to_ascii_lowercase()
-            }
-        })
-        .collect::<Vec<String>>()
-        .join("")
+    let splits: Vec<&str> = flag_name.split('_').filter(|&word| !word.is_empty()).collect();
+    if splits.len() == 1 {
+        let name = splits[0];
+        name[0..1].to_ascii_lowercase() + &name[1..]
+    } else {
+        splits
+            .iter()
+            .enumerate()
+            .map(|(index, word)| {
+                if index == 0 {
+                    word.to_ascii_lowercase()
+                } else {
+                    word[0..1].to_ascii_uppercase() + &word[1..].to_ascii_lowercase()
+                }
+            })
+            .collect::<Vec<String>>()
+            .join("")
+    }
+}
+
+fn format_property_name(property_name: &str) -> String {
+    let name = format_java_method_name(property_name);
+    format!("mProperties{}{}", &name[0..1].to_ascii_uppercase(), &name[1..])
 }
 
 #[cfg(test)]
@@ -265,8 +286,10 @@
         // 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;
         /** @hide */
         public final class FeatureFlagsImpl implements FeatureFlags {
+            private Properties mPropertiesAconfigTest;
             @Override
             @UnsupportedAppUsage
             public boolean disabledRo() {
@@ -275,11 +298,18 @@
             @Override
             @UnsupportedAppUsage
             public boolean disabledRw() {
-                return getValue(
-                    "aconfig_test",
-                    "com.android.aconfig.test.disabled_rw",
-                    false
-                );
+                if (mPropertiesAconfigTest == null) {
+                    mPropertiesAconfigTest =
+                        getProperties(
+                            "aconfig_test",
+                            "com.android.aconfig.test.disabled_rw"
+                        );
+                }
+                return mPropertiesAconfigTest
+                    .getBoolean(
+                        "com.android.aconfig.test.disabled_rw",
+                        false
+                    );
             }
             @Override
             @UnsupportedAppUsage
@@ -294,32 +324,36 @@
             @Override
             @UnsupportedAppUsage
             public boolean enabledRw() {
-                return getValue(
-                    "aconfig_test",
-                    "com.android.aconfig.test.enabled_rw",
-                    true
-                );
-            }
-            private boolean getValue(String nameSpace,
-                String flagName, boolean defaultValue) {
-                boolean value = defaultValue;
-                try {
-                    value = DeviceConfig.getBoolean(
-                        nameSpace,
-                        flagName,
-                        defaultValue
+                if (mPropertiesAconfigTest == null) {
+                    mPropertiesAconfigTest =
+                        getProperties(
+                            "aconfig_test",
+                            "com.android.aconfig.test.enabled_rw"
+                        );
+                }
+                return mPropertiesAconfigTest
+                    .getBoolean(
+                        "com.android.aconfig.test.enabled_rw",
+                        true
                     );
+            }
+            private Properties getProperties(
+                String namespace,
+                String flagName) {
+                Properties properties = null;
+                try {
+                    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;
             }
         }
         "#;
@@ -441,9 +475,45 @@
 
     #[test]
     fn test_format_java_method_name() {
-        let input = "____some_snake___name____";
         let expected = "someSnakeName";
+        let input = "____some_snake___name____";
         let formatted_name = format_java_method_name(input);
         assert_eq!(expected, formatted_name);
+
+        let input = "someSnakeName";
+        let formatted_name = format_java_method_name(input);
+        assert_eq!(expected, formatted_name);
+
+        let input = "SomeSnakeName";
+        let formatted_name = format_java_method_name(input);
+        assert_eq!(expected, formatted_name);
+
+        let input = "SomeSnakeName_";
+        let formatted_name = format_java_method_name(input);
+        assert_eq!(expected, formatted_name);
+
+        let input = "_SomeSnakeName";
+        let formatted_name = format_java_method_name(input);
+        assert_eq!(expected, formatted_name);
+    }
+
+    #[test]
+    fn test_format_property_name() {
+        let expected = "mPropertiesSomeSnakeName";
+        let input = "____some_snake___name____";
+        let formatted_name = format_property_name(input);
+        assert_eq!(expected, formatted_name);
+
+        let input = "someSnakeName";
+        let formatted_name = format_property_name(input);
+        assert_eq!(expected, formatted_name);
+
+        let input = "SomeSnakeName";
+        let formatted_name = format_property_name(input);
+        assert_eq!(expected, formatted_name);
+
+        let input = "SomeSnakeName_";
+        let formatted_name = format_property_name(input);
+        assert_eq!(expected, formatted_name);
     }
 }
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
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index d97611c..462c3bf 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -1908,8 +1908,11 @@
       for filename in ["kernel", "ramdisk", "vendor_ramdisk00"]:
         path = os.path.join(tmpdir, filename)
         if os.path.exists(path) and os.path.getsize(path):
+          print("Using {} as salt for avb footer of {}".format(
+              filename, partition_name))
           with open(path, "rb") as fp:
             salt = sha256(fp.read()).hexdigest()
+            break
     AppendAVBSigningArgs(cmd, partition_name, salt)
     args = info_dict.get("avb_" + partition_name + "_add_hash_footer_args")
     if args and args.strip():
@@ -2616,7 +2619,9 @@
     device = p.device
     if "/" in device:
       device = device[device.rfind("/")+1:]
-    limit = info_dict.get(device + "_size")
+    limit = info_dict.get(device + "_size", 0)
+    if isinstance(limit, str):
+      limit = int(limit, 0)
   if not fs_type or not limit:
     return