Merge "Move sysprop assignments to separate mk file" into main
diff --git a/core/Makefile b/core/Makefile
index 00577ed..712719a 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -3406,12 +3406,29 @@
 
 FULL_SYSTEMIMAGE_DEPS += $(INTERNAL_ROOT_FILES) $(INSTALLED_FILES_FILE_ROOT)
 
-define write-file-lines
-$(1):
+# Returns a list of all the zip files from EXTRA_INSTALL_ZIPS whose install destination is
+# under $(1)
+define relevant-extra-install-zips
+$(strip $(foreach p,$(EXTRA_INSTALL_ZIPS), \
+  $(if $(filter $(1)/%,$(call word-colon,1,$(p))/), \
+    $(call word-colon,2,$(p)))))
+endef
+
+# Writes a text file that contains all of the files that will be inside a partition.
+# All the file paths will be relative to the partition's staging directory.
+# It will also take into account files inside zips listed in EXTRA_INSTALL_ZIPS.
+#
+# Arguments:
+#   $(1): Output file
+#   $(2): The partition's staging directory
+#   $(3): Files to include in the partition
+define write-partition-file-list
+$(1): $$(HOST_OUT_EXECUTABLES)/extra_install_zips_file_list $(call relevant-extra-install-zips,$(2))
 	@echo Writing $$@
 	rm -f $$@
 	echo -n > $$@
-	$$(foreach f,$(2),echo "$$(f)" >> $$@$$(newline))
+	$$(foreach f,$(subst $(2)/,,$(filter $(2)/%,$(3))),echo "$$(f)" >> $$@$$(newline))
+	$$(HOST_OUT_EXECUTABLES)/extra_install_zips_file_list $(2) $$(EXTRA_INSTALL_ZIPS) >> $$@
 endef
 
 # -----------------------------------------------------------------
@@ -3477,7 +3494,7 @@
                exit 1 )
 endef
 
-$(eval $(call write-file-lines,$(systemimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT)/,,$(filter $(TARGET_OUT)/%,$(FULL_SYSTEMIMAGE_DEPS)))))
+$(eval $(call write-partition-file-list,$(systemimage_intermediates)/file_list.txt,$(TARGET_OUT),$(FULL_SYSTEMIMAGE_DEPS)))
 # Used by soong sandwich to request the staging dir be built
 $(systemimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT)/%,$(FULL_SYSTEMIMAGE_DEPS))
 	touch $@
@@ -3594,7 +3611,7 @@
     $(INTERNAL_USERIMAGES_DEPS) \
     $(INTERNAL_USERDATAIMAGE_FILES)
 
-$(eval $(call write-file-lines,$(userdataimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_DATA)/,,$(filter $(TARGET_OUT_DATA)/%,$(INSTALLED_USERDATAIMAGE_TARGET_DEPS)))))
+$(eval $(call write-partition-file-list,$(userdataimage_intermediates)/file_list.txt,$(TARGET_OUT_DATA),$(INSTALLED_USERDATAIMAGE_TARGET_DEPS)))
 # Used by soong sandwich to request the staging dir be built
 $(userdataimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_DATA)/%,$(INSTALLED_USERDATAIMAGE_TARGET_DEPS))
 	touch $@
@@ -3650,7 +3667,7 @@
   $(call assert-max-image-size,$(INSTALLED_CACHEIMAGE_TARGET),$(BOARD_CACHEIMAGE_PARTITION_SIZE))
 endef
 
-$(eval $(call write-file-lines,$(cacheimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_CACHE)/,,$(filter $(TARGET_OUT_CACHE)/%,$(INTERNAL_CACHEIMAGE_FILES)))))
+$(eval $(call write-partition-file-list,$(cacheimage_intermediates)/file_list.txt,$(TARGET_OUT_CACHE),$(INTERNAL_CACHEIMAGE_FILES)))
 # Used by soong sandwich to request the staging dir be built
 $(cacheimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_CACHE)/%,$(INTERNAL_CACHEIMAGE_FILES))
 	touch $@
@@ -3737,7 +3754,7 @@
   $(call assert-max-image-size,$(INSTALLED_SYSTEMOTHERIMAGE_TARGET),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))
 endef
 
-$(eval $(call write-file-lines,$(systemotherimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_SYSTEM_OTHER)/,,$(filter $(TARGET_OUT_SYSTEM_OTHER)/%,$(INTERNAL_SYSTEMOTHERIMAGE_FILES)))))
+$(eval $(call write-partition-file-list,$(systemotherimage_intermediates)/file_list.txt,$(TARGET_OUT_SYSTEM_OTHER),$(INTERNAL_SYSTEMOTHERIMAGE_FILES)))
 # Used by soong sandwich to request the staging dir be built
 $(systemotherimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_SYSTEM_OTHER)/%,$(INTERNAL_SYSTEMOTHERIMAGE_FILES))
 	touch $@
@@ -3843,7 +3860,7 @@
   $(call assert-max-image-size,$(INSTALLED_VENDORIMAGE_TARGET) $(RECOVERY_FROM_BOOT_PATCH),$(BOARD_VENDORIMAGE_PARTITION_SIZE))
 endef
 
-$(eval $(call write-file-lines,$(vendorimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_VENDOR)/,,$(filter $(TARGET_OUT_VENDOR)/%,$(INTERNAL_VENDORIMAGE_FILES)))))
+$(eval $(call write-partition-file-list,$(vendorimage_intermediates)/file_list.txt,$(TARGET_OUT_VENDOR),$(INTERNAL_VENDORIMAGE_FILES)))
 # Used by soong sandwich to request the staging dir be built
 $(vendorimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_VENDOR)/%,$(INTERNAL_VENDORIMAGE_FILES))
 	touch $@
@@ -3916,7 +3933,7 @@
   $(call assert-max-image-size,$(INSTALLED_PRODUCTIMAGE_TARGET),$(BOARD_PRODUCTIMAGE_PARTITION_SIZE))
 endef
 
-$(eval $(call write-file-lines,$(productimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_PRODUCT)/,,$(filter $(TARGET_OUT_PRODUCT)/%,$(INTERNAL_PRODUCTIMAGE_FILES)))))
+$(eval $(call write-partition-file-list,$(productimage_intermediates)/file_list.txt,$(TARGET_OUT_PRODUCT),$(INTERNAL_PRODUCTIMAGE_FILES)))
 # Used by soong sandwich to request the staging dir be built
 $(productimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_PRODUCT)/%,$(INTERNAL_PRODUCTIMAGE_FILES))
 	touch $@
@@ -3986,7 +4003,7 @@
   $(call assert-max-image-size,$(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET),$(BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE))
 endef
 
-$(eval $(call write-file-lines,$(system_extimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_SYSTEM_EXT)/,,$(filter $(TARGET_OUT_SYSTEM_EXT)/%,$(INTERNAL_SYSTEM_EXTIMAGE_FILES)))))
+$(eval $(call write-partition-file-list,$(system_extimage_intermediates)/file_list.txt,$(TARGET_OUT_SYSTEM_EXT),$(INTERNAL_SYSTEM_EXTIMAGE_FILES)))
 # Used by soong sandwich to request the staging dir be built
 $(system_extimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_SYSTEM_EXT)/%,$(INTERNAL_SYSTEM_EXTIMAGE_FILES))
 	touch $@
@@ -4075,7 +4092,7 @@
   $(call assert-max-image-size,$(INSTALLED_ODMIMAGE_TARGET),$(BOARD_ODMIMAGE_PARTITION_SIZE))
 endef
 
-$(eval $(call write-file-lines,$(odmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_ODM)/,,$(filter $(TARGET_OUT_ODM)/%,$(INTERNAL_ODMIMAGE_FILES)))))
+$(eval $(call write-partition-file-list,$(odmimage_intermediates)/file_list.txt,$(TARGET_OUT_ODM),$(INTERNAL_ODMIMAGE_FILES)))
 # Used by soong sandwich to request the staging dir be built
 $(odmimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_ODM)/%,$(INTERNAL_ODMIMAGE_FILES))
 	touch $@
@@ -4144,7 +4161,7 @@
   $(call assert-max-image-size,$(INSTALLED_VENDOR_DLKMIMAGE_TARGET),$(BOARD_VENDOR_DLKMIMAGE_PARTITION_SIZE))
 endef
 
-$(eval $(call write-file-lines,$(vendor_dlkmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_VENDOR_DLKM)/,,$(filter $(TARGET_OUT_VENDOR_DLKM)/%,$(INTERNAL_VENDOR_DLKMIMAGE_FILES)))))
+$(eval $(call write-partition-file-list,$(vendor_dlkmimage_intermediates)/file_list.txt,$(TARGET_OUT_VENDOR_DLKM),$(INTERNAL_VENDOR_DLKMIMAGE_FILES)))
 # Used by soong sandwich to request the staging dir be built
 $(vendor_dlkmimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_VENDOR_DLKM)/%,$(INTERNAL_VENDOR_DLKMIMAGE_FILES))
 	touch $@
@@ -4213,7 +4230,7 @@
   $(call assert-max-image-size,$(INSTALLED_ODM_DLKMIMAGE_TARGET),$(BOARD_ODM_DLKMIMAGE_PARTITION_SIZE))
 endef
 
-$(eval $(call write-file-lines,$(odm_dlkmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_ODM_DLKM)/,,$(filter $(TARGET_OUT_ODM_DLKM)/%,$(INTERNAL_ODM_DLKMIMAGE_FILES)))))
+$(eval $(call write-partition-file-list,$(odm_dlkmimage_intermediates)/file_list.txt,$(TARGET_OUT_ODM_DLKM),$(INTERNAL_ODM_DLKMIMAGE_FILES)))
 # Used by soong sandwich to request the staging dir be built
 $(odm_dlkmimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_ODM_DLKM)/%,$(INTERNAL_ODM_DLKMIMAGE_FILES))
 	touch $@
@@ -4284,7 +4301,7 @@
   $(call assert-max-image-size,$(INSTALLED_SYSTEM_DLKMIMAGE_TARGET),$(BOARD_SYSTEM_DLKMIMAGE_PARTITION_SIZE))
 endef
 
-$(eval $(call write-file-lines,$(system_dlkmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_SYSTEM_DLKM)/,,$(filter $(TARGET_OUT_SYSTEM_DLKM)/%,$(INTERNAL_SYSTEM_DLKMIMAGE_FILES)))))
+$(eval $(call write-partition-file-list,$(system_dlkmimage_intermediates)/file_list.txt,$(TARGET_OUT_SYSTEM_DLKM),$(INTERNAL_SYSTEM_DLKMIMAGE_FILES)))
 # Used by soong sandwich to request the staging dir be built
 $(system_dlkmimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_SYSTEM_DLKM)/%,$(INTERNAL_SYSTEM_DLKMIMAGE_FILES))
 	touch $@
diff --git a/core/base_rules.mk b/core/base_rules.mk
index b594193..9c7e906 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -716,6 +716,14 @@
   test_config := $(wildcard $(LOCAL_PATH)/AndroidTest.xml)
 endif
 
+ifeq ($(EXCLUDE_MCTS),true)
+  ifneq (,$(test_config))
+    ifneq (,$(filter mcts-%,$(LOCAL_COMPATIBILITY_SUITE)))
+      LOCAL_COMPATIBILITY_SUITE := $(filter-out cts,$(LOCAL_COMPATIBILITY_SUITE))
+    endif
+  endif
+endif
+
 ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
 
 # If we are building a native test or benchmark and its stem variants are not defined,
diff --git a/core/main.mk b/core/main.mk
index 62fa53d..d700fcb 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -276,7 +276,7 @@
 # Include all of the makefiles in the system
 #
 
-subdir_makefiles := $(SOONG_OUT_DIR)/installs-$(TARGET_PRODUCT).mk $(SOONG_ANDROID_MK)
+subdir_makefiles := $(SOONG_ANDROID_MK)
 # Android.mk files are only used on Linux builds, Mac only supports Android.bp
 ifeq ($(HOST_OS),linux)
   subdir_makefiles += $(file <$(OUT_DIR)/.module_paths/Android.mk.list)
@@ -287,6 +287,8 @@
 
 $(foreach mk,$(subdir_makefiles),$(info [$(call inc_and_print,subdir_makefiles_inc)/$(subdir_makefiles_total)] including $(mk) ...)$(eval include $(mk)))
 
+include $(SOONG_OUT_DIR)/installs-$(TARGET_PRODUCT).mk
+
 # For an unbundled image, we can skip blueprint_tools because unbundled image
 # aims to remove a large number framework projects from the manifest, the
 # sources or dependencies for these tools may be missing from the tree.
diff --git a/core/release_config.mk b/core/release_config.mk
index bb51980..97c8dd3 100644
--- a/core/release_config.mk
+++ b/core/release_config.mk
@@ -120,7 +120,8 @@
         # Disable the build flag in release-config.
         _args += --guard=false
     endif
-    $(KATI_shell_no_rerun $(OUT_DIR)/release-config $(_args) >$(OUT_DIR)/release-config.out && touch -t 200001010000 $(OUT_DIR)/release-config.out)
+    _flags_file:=$(OUT_DIR)/soong/release-config/release_config-$(TARGET_PRODUCT)-$(TARGET_RELEASE).mk
+    $(KATI_shell_no_rerun $(OUT_DIR)/release-config $(_args) >$(OUT_DIR)/release-config.out 2>&1 && touch -t 200001010000 $(OUT_DIR)/release-config.out $(_flags_file))
     $(if $(filter-out 0,$(.SHELLSTATUS)),$(error release-config failed to run))
     # This will also set _all_release_configs for us.
     $(eval include $(OUT_DIR)/soong/release-config/release_config-$(TARGET_PRODUCT)-$(TARGET_RELEASE).mk)
diff --git a/tools/aconfig/aconfig_device_paths/Android.bp b/tools/aconfig/aconfig_device_paths/Android.bp
index 21aa9a9..2c771e0 100644
--- a/tools/aconfig/aconfig_device_paths/Android.bp
+++ b/tools/aconfig/aconfig_device_paths/Android.bp
@@ -36,3 +36,16 @@
     host_supported: true,
     defaults: ["libaconfig_device_paths.defaults"],
 }
+
+genrule {
+    name: "libaconfig_java_device_paths_src",
+    srcs: ["src/DevicePathsTemplate.java"],
+    out: ["DevicePaths.java"],
+    tool_files: ["partition_aconfig_flags_paths.txt"],
+    cmd: "sed -e '/TEMPLATE/{r$(location partition_aconfig_flags_paths.txt)' -e 'd}' $(in) > $(out)"
+}
+
+java_library {
+    name: "aconfig_device_paths_java",
+    srcs: [":libaconfig_java_device_paths_src"],
+}
diff --git a/tools/aconfig/aconfig_device_paths/partition_aconfig_flags_paths.txt b/tools/aconfig/aconfig_device_paths/partition_aconfig_flags_paths.txt
index 3d2deb2..140cd21 100644
--- a/tools/aconfig/aconfig_device_paths/partition_aconfig_flags_paths.txt
+++ b/tools/aconfig/aconfig_device_paths/partition_aconfig_flags_paths.txt
@@ -1,6 +1,4 @@
-[
-    "/system/etc/aconfig_flags.pb",
-    "/system_ext/etc/aconfig_flags.pb",
-    "/product/etc/aconfig_flags.pb",
-    "/vendor/etc/aconfig_flags.pb",
-]
+"/system/etc/aconfig_flags.pb",
+"/system_ext/etc/aconfig_flags.pb",
+"/product/etc/aconfig_flags.pb",
+"/vendor/etc/aconfig_flags.pb",
diff --git a/tools/aconfig/aconfig_device_paths/src/DevicePathsTemplate.java b/tools/aconfig/aconfig_device_paths/src/DevicePathsTemplate.java
new file mode 100644
index 0000000..f27b9bd
--- /dev/null
+++ b/tools/aconfig/aconfig_device_paths/src/DevicePathsTemplate.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.aconfig;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @hide
+ */
+public class DevicePaths {
+    static final String[] PATHS = {
+        TEMPLATE
+    };
+
+    private static final String APEX_DIR = "/apex";
+    private static final String APEX_ACONFIG_PATH_SUFFIX = "/etc/aconfig_flags.pb";
+
+
+    /**
+     * Returns the list of all on-device aconfig protos paths.
+     * @hide
+     */
+    public List<String> parsedFlagsProtoPaths() {
+        ArrayList<String> paths = new ArrayList(Arrays.asList(PATHS));
+
+        File apexDirectory = new File(APEX_DIR);
+        if (!apexDirectory.isDirectory()) {
+            return paths;
+        }
+
+        File[] subdirs = apexDirectory.listFiles();
+        if (subdirs == null) {
+            return paths;
+        }
+
+        for (File prefix : subdirs) {
+            // For each mainline modules, there are two directories, one <modulepackage>/,
+            // and one <modulepackage>@<versioncode>/. Just read the former.
+            if (prefix.getAbsolutePath().contains("@")) {
+                continue;
+            }
+
+            File protoPath = new File(prefix + APEX_ACONFIG_PATH_SUFFIX);
+            if (!protoPath.exists()) {
+                continue;
+            }
+
+            paths.add(protoPath.getAbsolutePath());
+        }
+        return paths;
+    }
+}
diff --git a/tools/aconfig/aconfig_device_paths/src/lib.rs b/tools/aconfig/aconfig_device_paths/src/lib.rs
index 7bb62f4..c5a6bff 100644
--- a/tools/aconfig/aconfig_device_paths/src/lib.rs
+++ b/tools/aconfig/aconfig_device_paths/src/lib.rs
@@ -23,7 +23,7 @@
 
 /// Determine all paths that contain an aconfig protobuf file.
 pub fn parsed_flags_proto_paths() -> Result<Vec<PathBuf>> {
-    let mut result: Vec<PathBuf> = include!("../partition_aconfig_flags_paths.txt")
+    let mut result: Vec<PathBuf> = [include_str!("../partition_aconfig_flags_paths.txt")]
         .map(|s| PathBuf::from(s.to_string()))
         .to_vec();
     for dir in fs::read_dir("/apex")? {
diff --git a/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp b/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp
index 548078f..7af024b 100644
--- a/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp
+++ b/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp
@@ -7,6 +7,29 @@
 
 namespace aconfig_storage {
 
+Result<std::vector<FlagValueSummary>> list_flags(
+    const std::string& package_map,
+    const std::string& flag_map,
+    const std::string& flag_val) {
+  auto flag_list_cxx = list_flags_cxx(rust::Str(package_map.c_str()),
+                                      rust::Str(flag_map.c_str()),
+                                      rust::Str(flag_val.c_str()));
+  if (flag_list_cxx.query_success) {
+    auto flag_list = std::vector<FlagValueSummary>();
+    for (const auto& flag_cxx : flag_list_cxx.flags) {
+      auto flag = FlagValueSummary();
+      flag.package_name = std::string(flag_cxx.package_name);
+      flag.flag_name = std::string(flag_cxx.flag_name);
+      flag.flag_value = std::string(flag_cxx.flag_value);
+      flag.value_type = std::string(flag_cxx.value_type);
+      flag_list.push_back(flag);
+    }
+    return flag_list;
+  } else {
+    return Error() << flag_list_cxx.error_message;
+  }
+}
+
 Result<std::vector<FlagValueAndInfoSummary>> list_flags_with_info(
     const std::string& package_map,
     const std::string& flag_map,
diff --git a/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp
index 5044a4d..9f3cdb0 100644
--- a/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp
+++ b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp
@@ -6,6 +6,23 @@
 
 namespace aconfig_storage {
 
+/// Flag value summary for a flag
+struct FlagValueSummary {
+  std::string package_name;
+  std::string flag_name;
+  std::string flag_value;
+  std::string value_type;
+};
+
+/// List all flag values
+/// \input package_map: package map file
+/// \input flag_map: flag map file
+/// \input flag_val: flag value file
+android::base::Result<std::vector<FlagValueSummary>> list_flags(
+    const std::string& package_map,
+    const std::string& flag_map,
+    const std::string& flag_val);
+
 /// Flag value and info summary for a flag
 struct FlagValueAndInfoSummary {
   std::string package_name;
diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs
index 80602bb..26e9c1a 100644
--- a/tools/aconfig/aconfig_storage_file/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_file/src/lib.rs
@@ -382,6 +382,14 @@
 // Exported rust data structure and methods, c++ code will be generated
 #[cxx::bridge]
 mod ffi {
+    /// flag value summary cxx return
+    pub struct FlagValueSummaryCXX {
+        pub package_name: String,
+        pub flag_name: String,
+        pub flag_value: String,
+        pub value_type: String,
+    }
+
     /// flag value and info summary cxx return
     pub struct FlagValueAndInfoSummaryCXX {
         pub package_name: String,
@@ -394,6 +402,13 @@
     }
 
     /// list flag result cxx return
+    pub struct ListFlagValueResultCXX {
+        pub query_success: bool,
+        pub error_message: String,
+        pub flags: Vec<FlagValueSummaryCXX>,
+    }
+
+    /// list flag with info result cxx return
     pub struct ListFlagValueAndInfoResultCXX {
         pub query_success: bool,
         pub error_message: String,
@@ -402,6 +417,12 @@
 
     // Rust export to c++
     extern "Rust" {
+        pub fn list_flags_cxx(
+            package_map: &str,
+            flag_map: &str,
+            flag_val: &str,
+        ) -> ListFlagValueResultCXX;
+
         pub fn list_flags_with_info_cxx(
             package_map: &str,
             flag_map: &str,
@@ -411,6 +432,18 @@
     }
 }
 
+/// implement flag value summary cxx return type
+impl ffi::FlagValueSummaryCXX {
+    pub(crate) fn new(summary: FlagValueSummary) -> Self {
+        Self {
+            package_name: summary.package_name,
+            flag_name: summary.flag_name,
+            flag_value: summary.flag_value,
+            value_type: format!("{:?}", summary.value_type),
+        }
+    }
+}
+
 /// implement flag value and info summary cxx return type
 impl ffi::FlagValueAndInfoSummaryCXX {
     pub(crate) fn new(summary: FlagValueAndInfoSummary) -> Self {
@@ -426,6 +459,26 @@
     }
 }
 
+/// implement list flag cxx interlop
+pub fn list_flags_cxx(
+    package_map: &str,
+    flag_map: &str,
+    flag_val: &str,
+) -> ffi::ListFlagValueResultCXX {
+    match list_flags(package_map, flag_map, flag_val) {
+        Ok(summary) => ffi::ListFlagValueResultCXX {
+            query_success: true,
+            error_message: String::new(),
+            flags: summary.into_iter().map(ffi::FlagValueSummaryCXX::new).collect(),
+        },
+        Err(errmsg) => ffi::ListFlagValueResultCXX {
+            query_success: false,
+            error_message: format!("{:?}", errmsg),
+            flags: Vec::new(),
+        },
+    }
+}
+
 /// implement list flag with info cxx interlop
 pub fn list_flags_with_info_cxx(
     package_map: &str,
diff --git a/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp b/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp
index eccbca5..ebd1dd8 100644
--- a/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp
+++ b/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp
@@ -24,15 +24,25 @@
 using namespace android::base;
 using namespace aconfig_storage;
 
+void verify_value(const FlagValueSummary& flag,
+                  const std::string& package_name,
+                  const std::string& flag_name,
+                  const std::string& flag_val,
+                  const std::string& value_type) {
+  ASSERT_EQ(flag.package_name, package_name);
+  ASSERT_EQ(flag.flag_name, flag_name);
+  ASSERT_EQ(flag.flag_value, flag_val);
+  ASSERT_EQ(flag.value_type, value_type);
+}
 
-void verify_flag(const FlagValueAndInfoSummary& flag,
-                 const std::string& package_name,
-                 const std::string& flag_name,
-                 const std::string& flag_val,
-                 const std::string& value_type,
-                 bool is_readwrite,
-                 bool has_server_override,
-                 bool has_local_override) {
+void verify_value_info(const FlagValueAndInfoSummary& flag,
+                       const std::string& package_name,
+                       const std::string& flag_name,
+                       const std::string& flag_val,
+                       const std::string& value_type,
+                       bool is_readwrite,
+                       bool has_server_override,
+                       bool has_local_override) {
   ASSERT_EQ(flag.package_name, package_name);
   ASSERT_EQ(flag.flag_name, flag_name);
   ASSERT_EQ(flag.flag_value, flag_val);
@@ -42,6 +52,35 @@
   ASSERT_EQ(flag.has_local_override, has_local_override);
 }
 
+TEST(AconfigStorageFileTest, test_list_flag) {
+  auto const test_dir = GetExecutableDirectory();
+  auto const package_map = test_dir + "/package.map";
+  auto const flag_map = test_dir + "/flag.map";
+  auto const flag_val = test_dir + "/flag.val";
+  auto flag_list_result = aconfig_storage::list_flags(
+      package_map, flag_map, flag_val);
+  ASSERT_TRUE(flag_list_result.ok());
+
+  auto const& flag_list = *flag_list_result;
+  ASSERT_EQ(flag_list.size(), 8);
+  verify_value(flag_list[0], "com.android.aconfig.storage.test_1", "disabled_rw",
+               "false", "ReadWriteBoolean");
+  verify_value(flag_list[1], "com.android.aconfig.storage.test_1", "enabled_ro",
+               "true", "ReadOnlyBoolean");
+  verify_value(flag_list[2], "com.android.aconfig.storage.test_1", "enabled_rw",
+               "true", "ReadWriteBoolean");
+  verify_value(flag_list[3], "com.android.aconfig.storage.test_2", "disabled_rw",
+               "false", "ReadWriteBoolean");
+  verify_value(flag_list[4], "com.android.aconfig.storage.test_2", "enabled_fixed_ro",
+               "true", "FixedReadOnlyBoolean");
+  verify_value(flag_list[5], "com.android.aconfig.storage.test_2", "enabled_ro",
+               "true", "ReadOnlyBoolean");
+  verify_value(flag_list[6], "com.android.aconfig.storage.test_4", "enabled_fixed_ro",
+               "true", "FixedReadOnlyBoolean");
+  verify_value(flag_list[7], "com.android.aconfig.storage.test_4", "enabled_rw",
+               "true", "ReadWriteBoolean");
+}
+
 TEST(AconfigStorageFileTest, test_list_flag_with_info) {
   auto const test_dir = GetExecutableDirectory();
   auto const package_map = test_dir + "/package.map";
@@ -54,20 +93,20 @@
 
   auto const& flag_list = *flag_list_result;
   ASSERT_EQ(flag_list.size(), 8);
-  verify_flag(flag_list[0], "com.android.aconfig.storage.test_1", "disabled_rw",
-              "false", "ReadWriteBoolean", true, false, false);
-  verify_flag(flag_list[1], "com.android.aconfig.storage.test_1", "enabled_ro",
-              "true", "ReadOnlyBoolean", false, false, false);
-  verify_flag(flag_list[2], "com.android.aconfig.storage.test_1", "enabled_rw",
-              "true", "ReadWriteBoolean", true, false, false);
-  verify_flag(flag_list[3], "com.android.aconfig.storage.test_2", "disabled_rw",
-              "false", "ReadWriteBoolean", true, false, false);
-  verify_flag(flag_list[4], "com.android.aconfig.storage.test_2", "enabled_fixed_ro",
-              "true", "FixedReadOnlyBoolean", false, false, false);
-  verify_flag(flag_list[5], "com.android.aconfig.storage.test_2", "enabled_ro",
-              "true", "ReadOnlyBoolean", false, false, false);
-  verify_flag(flag_list[6], "com.android.aconfig.storage.test_4", "enabled_fixed_ro",
-              "true", "FixedReadOnlyBoolean", false, false, false);
-  verify_flag(flag_list[7], "com.android.aconfig.storage.test_4", "enabled_rw",
-              "true", "ReadWriteBoolean", true, false, false);
+  verify_value_info(flag_list[0], "com.android.aconfig.storage.test_1", "disabled_rw",
+                    "false", "ReadWriteBoolean", true, false, false);
+  verify_value_info(flag_list[1], "com.android.aconfig.storage.test_1", "enabled_ro",
+                    "true", "ReadOnlyBoolean", false, false, false);
+  verify_value_info(flag_list[2], "com.android.aconfig.storage.test_1", "enabled_rw",
+                    "true", "ReadWriteBoolean", true, false, false);
+  verify_value_info(flag_list[3], "com.android.aconfig.storage.test_2", "disabled_rw",
+                    "false", "ReadWriteBoolean", true, false, false);
+  verify_value_info(flag_list[4], "com.android.aconfig.storage.test_2", "enabled_fixed_ro",
+                    "true", "FixedReadOnlyBoolean", false, false, false);
+  verify_value_info(flag_list[5], "com.android.aconfig.storage.test_2", "enabled_ro",
+                    "true", "ReadOnlyBoolean", false, false, false);
+  verify_value_info(flag_list[6], "com.android.aconfig.storage.test_4", "enabled_fixed_ro",
+                    "true", "FixedReadOnlyBoolean", false, false, false);
+  verify_value_info(flag_list[7], "com.android.aconfig.storage.test_4", "enabled_rw",
+                    "true", "ReadWriteBoolean", true, false, false);
 }
diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py
index 048a497..81b53dc 100644
--- a/tools/releasetools/ota_utils.py
+++ b/tools/releasetools/ota_utils.py
@@ -1111,9 +1111,10 @@
       relative_path = path.removeprefix(input_dir).removeprefix("/")
       if not Fnmatch(relative_path, UNZIP_PATTERN):
         continue
-      if filename.endswith(".prop") or filename == "prop.default" or "/etc/vintf/" in relative_path:
-        target_path = os.path.join(
-            output_dir, relative_path)
-        os.makedirs(os.path.dirname(target_path), exist_ok=True)
-        shutil.copy(path, target_path)
+      target_path = os.path.join(
+          output_dir, relative_path)
+      if os.path.exists(target_path):
+        continue
+      os.makedirs(os.path.dirname(target_path), exist_ok=True)
+      shutil.copy(path, target_path)
   return output_dir