Merge "Add bins and libs into the otatools.zip" into main
diff --git a/core/Makefile b/core/Makefile
index 3584994..dd79dd2 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -7187,6 +7187,12 @@
 $(call declare-1p-target,$(DEXPREOPT_CONFIG_ZIP),)
 
 # -----------------------------------------------------------------
+# Zips of the symbols directory per test suites
+#
+
+$(foreach suite,$(ALL_COMPATIBILITY_SUITES),$(eval $(call create-suite-symbols-map,$(suite))))
+
+# -----------------------------------------------------------------
 # A zip of the symbols directory.  Keep the full paths to make it
 # more obvious where these files came from.
 # Also produces a textproto containing mappings from elf IDs to symbols
@@ -7204,29 +7210,37 @@
 # The path to a file containing mappings from elf IDs to filenames.
 SYMBOLS_MAPPING := $(PRODUCT_OUT)/$(name)-symbols-mapping.textproto
 .KATI_READONLY := SYMBOLS_ZIP SYMBOLS_MAPPING
-# For apps_only build we'll establish the dependency later in build/make/core/main.mk.
+
 ifeq (,$(TARGET_BUILD_UNBUNDLED))
-$(SYMBOLS_ZIP): $(INTERNAL_ALLIMAGES_FILES) $(updater_dep)
+  _symbols_zip_modules := $(call product-installed-modules,$(INTERNAL_PRODUCT))
+  $(SYMBOLS_ZIP): $(updater_dep)
+else
+  _symbols_zip_modules := $(unbundled_build_modules)
 endif
-$(SYMBOLS_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,symbols)/filelist
-$(SYMBOLS_ZIP): PRIVATE_MAPPING_PACKAGING_DIR := $(call intermediates-dir-for,PACKAGING,elf_symbol_mapping)
-$(SYMBOLS_ZIP): $(SOONG_ZIP) $(SYMBOLS_MAP)
+
+_symbols_zip_modules_symbols_files := $(foreach m,$(_symbols_zip_modules),$(ALL_MODULES.$(m).SYMBOLIC_OUTPUT_PATH))
+_symbols_zip_modules_mapping_files := $(foreach m,$(_symbols_zip_modules),$(ALL_MODULES.$(m).ELF_SYMBOL_MAPPING_PATH))
+
+$(SYMBOLS_ZIP): PRIVATE_SYMBOLS_MODULES_FILES := $(_symbols_zip_modules_symbols_files)
+$(SYMBOLS_ZIP): PRIVATE_SYMBOLS_MODULES_MAPPING_FILES := $(_symbols_zip_modules_mapping_files)
+$(SYMBOLS_ZIP): $(SOONG_ZIP) $(SYMBOLS_MAP) $(_symbols_zip_modules_symbols_files) $(_symbols_zip_modules_mapping_files)
 	@echo "Package symbols: $@"
-	$(hide) rm -rf $@ $(PRIVATE_LIST_FILE)
-	$(hide) mkdir -p $(TARGET_OUT_UNSTRIPPED) $(dir $(PRIVATE_LIST_FILE)) $(PRIVATE_MAPPING_PACKAGING_DIR)
-	# Find all of the files in the symbols directory and zip them into the symbols zip.
-	$(hide) find -L $(TARGET_OUT_UNSTRIPPED) -type f | sort >$(PRIVATE_LIST_FILE)
-	$(hide) $(SOONG_ZIP) --ignore_missing_files -d -o $@ -C $(OUT_DIR)/.. -l $(PRIVATE_LIST_FILE)
-	# Find all of the files in the symbols mapping directory and merge them into the symbols mapping textproto.
-	$(hide) find -L $(PRIVATE_MAPPING_PACKAGING_DIR) -type f | sort >$(PRIVATE_LIST_FILE)
-	$(hide) $(SYMBOLS_MAP) -merge $(SYMBOLS_MAPPING) -ignore_missing_files @$(PRIVATE_LIST_FILE)
+	$(hide) rm -rf $@ $@.symbols_list $@.mapping_list
+	# Find all installed files in the symbols directory and zip them into the symbols zip.
+	echo "$(PRIVATE_SYMBOLS_MODULES_FILES)" | tr " " "\n" | sort > $@.symbols_list
+	$(hide) $(SOONG_ZIP) -d -o $@ -l $@.symbols_list
+	# Find all installed files in the symbols mapping directory and merge them into the symbols mapping textproto.
+	echo "$(PRIVATE_SYMBOLS_MODULES_MAPPING_FILES)" | tr " " "\n" | sort > $@.mapping_list
+	$(hide) $(SYMBOLS_MAP) -merge $(SYMBOLS_MAPPING) @$@.mapping_list
 $(SYMBOLS_ZIP): .KATI_IMPLICIT_OUTPUTS := $(SYMBOLS_MAPPING)
 
 $(call declare-1p-container,$(SYMBOLS_ZIP),)
 ifeq (,$(TARGET_BUILD_UNBUNDLED))
-$(call declare-container-license-deps,$(SYMBOLS_ZIP),$(INTERNAL_ALLIMAGES_FILES) $(updater_dep),$(PRODUCT_OUT)/:/)
+$(call declare-container-license-deps,$(SYMBOLS_ZIP),$(PRIVATE_SYMBOLS_MODULES_FILES) $(updater_dep),$(PRODUCT_OUT)/:/)
 endif
 
+_symbols_zip_modules_symbols_files :=
+_symbols_zip_modules_mapping_files :=
 # -----------------------------------------------------------------
 # A zip of the coverage directory.
 #
diff --git a/core/definitions.mk b/core/definitions.mk
index 60034cd..ea151fa 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -3422,9 +3422,9 @@
 # a hash mapping to the mapping directory.
 # $(1): unstripped intermediates file
 # $(2): path in symbols directory
+# $(3): path in elf_symbol_mapping packaging directory
 define copy-unstripped-elf-file-with-mapping
-$(call _copy-symbols-file-with-mapping,$(1),$(2),\
-  elf,$(patsubst $(TARGET_OUT_UNSTRIPPED)/%,$(call intermediates-dir-for,PACKAGING,elf_symbol_mapping)/%,$(2).textproto))
+$(call _copy-symbols-file-with-mapping,$(1),$(2),elf,$(3))
 endef
 
 # Copy an R8 dictionary to the packaging directory while also extracting
@@ -3689,6 +3689,32 @@
     $(sort $(foreach suite,$(LOCAL_COMPATIBILITY_SUITE),$(my_compat_dist_config_$(suite))))))
 endef
 
+# Define symbols.zip and symbols-mapping.textproto build rule per test suite
+#
+# $(1): Name of the test suite to create the zip and mapping build rules
+define create-suite-symbols-map
+_suite_symbols_zip := $$(subst -tests-,-tests_-,$$(PRODUCT_OUT)/$(1)-symbols.zip)
+_suite_symbols_mapping := $$(subst -tests-,-tests_-,$$(PRODUCT_OUT)/$(1)-symbols-mapping.textproto)
+_suite_modules_symbols_files := $$(foreach m,$$(COMPATIBILITY.$(1).MODULES),$$(ALL_MODULES.$$(m).SYMBOLIC_OUTPUT_PATH))
+_suite_modules_mapping_files := $$(foreach m,$$(COMPATIBILITY.$(1).MODULES),$$(ALL_MODULES.$$(m).ELF_SYMBOL_MAPPING_PATH))
+
+$$(_suite_symbols_zip): PRIVATE_SUITE_SYMBOLS_MAPPING := $$(_suite_symbols_mapping)
+$$(_suite_symbols_zip): PRIVATE_SUITE_MODULES_SYMBOLS_FILES := $$(_suite_modules_symbols_files)
+$$(_suite_symbols_zip): PRIVATE_SUITE_MODULES_MAPPING_FILES := $$(_suite_modules_mapping_files)
+$$(_suite_symbols_zip): $$(SOONG_ZIP) $$(SYMBOLS_MAP) $$(_suite_modules_symbols_files) $$(_suite_modules_mapping_files)
+	@echo "Package $(1) symbols: $$@"
+	$(hide) rm -rf $$@ $$@.symbols_list $$@.mapping_list
+	echo "$$(PRIVATE_SUITE_MODULES_SYMBOLS_FILES)" | tr " " "\n" | sort > $$@.symbols_list
+	$(hide) $$(SOONG_ZIP) -d -o $$@ -l $$@.symbols_list
+	echo "$$(PRIVATE_SUITE_MODULES_MAPPING_FILES)" | tr " " "\n" | sort > $$@.mapping_list
+	$(hide) $$(SYMBOLS_MAP) -merge $$(PRIVATE_SUITE_SYMBOLS_MAPPING) @$$@.mapping_list
+$$(_suite_symbols_zip): .KATI_IMPLICIT_OUTPUTS := $$(_suite_symbols_mapping)
+
+.PHONY: $(1)
+$(1): $$(_suite_symbols_zip) $$(_suite_symbols_mapping)
+$$(call dist-for-goals-with-filenametag,$(1), $$(_suite_symbols_zip) $$(_suite_symbols_mapping))
+endef
+
 ###########################################################
 ## Path Cleaning
 ###########################################################
diff --git a/core/dynamic_binary.mk b/core/dynamic_binary.mk
index 0d2cd7f..878989d 100644
--- a/core/dynamic_binary.mk
+++ b/core/dynamic_binary.mk
@@ -55,7 +55,12 @@
 endif
 symbolic_input := $(inject_module)
 symbolic_output := $(my_unstripped_path)/$(my_installed_module_stem)
-$(eval $(call copy-unstripped-elf-file-with-mapping,$(symbolic_input),$(symbolic_output)))
+elf_mapping_path := $(patsubst $(TARGET_OUT_UNSTRIPPED)/%,$(call intermediates-dir-for,PACKAGING,elf_symbol_mapping)/%,$(symbolic_output).textproto)
+
+ALL_MODULES.$(my_register_name).SYMBOLIC_OUTPUT_PATH := $(symbolic_output)
+ALL_MODULES.$(my_register_name).ELF_SYMBOL_MAPPING_PATH := $(elf_mapping_path)
+
+$(eval $(call copy-unstripped-elf-file-with-mapping,$(symbolic_input),$(symbolic_output),$(elf_mapping_path)))
 
 ###########################################################
 ## Store breakpad symbols
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index ab9227f..62b5d5b 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -142,7 +142,21 @@
 # install symbol files of JNI libraries
 my_jni_lib_symbols_copy_files := $(foreach f,$(LOCAL_SOONG_JNI_LIBS_SYMBOLS),\
   $(call word-colon,1,$(f)):$(patsubst $(PRODUCT_OUT)/%,$(TARGET_OUT_UNSTRIPPED)/%,$(call word-colon,2,$(f))))
-$(LOCAL_BUILT_MODULE): | $(call copy-many-files, $(my_jni_lib_symbols_copy_files))
+
+$(foreach f, $(my_jni_lib_symbols_copy_files), \
+  $(eval $(call copy-unstripped-elf-file-with-mapping, \
+    $(call word-colon,1,$(f)), \
+    $(call word-colon,2,$(f)), \
+    $(patsubst $(TARGET_OUT_UNSTRIPPED)/%,$(call intermediates-dir-for,PACKAGING,elf_symbol_mapping)/%,$(call word-colon,2,$(f)).textproto)\
+  ))\
+)
+
+symbolic_outputs := $(foreach f,$(my_jni_lib_symbols_copy_files),$(call word-colon,2,$(f)))
+symbolic_mappings := $(foreach f,$(symbolic_outputs),$(patsubst $(TARGET_OUT_UNSTRIPPED)/%,$(call intermediates-dir-for,PACKAGING,elf_symbol_mapping)/%,$(f).textproto))
+ALL_MODULES.$(my_register_name).SYMBOLIC_OUTPUT_PATH := $(symbolic_outputs)
+ALL_MODULES.$(my_register_name).ELF_SYMBOL_MAPPING_PATH := $(symbolic_mappings)
+
+$(LOCAL_BUILT_MODULE): | $(symbolic_outputs)
 
 # embedded JNI will already have been handled by soong
 my_embed_jni :=
diff --git a/core/soong_cc_rust_prebuilt.mk b/core/soong_cc_rust_prebuilt.mk
index da60832..9ea24f7 100644
--- a/core/soong_cc_rust_prebuilt.mk
+++ b/core/soong_cc_rust_prebuilt.mk
@@ -190,7 +190,12 @@
       # drop /root as /root is mounted as /
       my_unstripped_path := $(patsubst $(TARGET_OUT_UNSTRIPPED)/root/%,$(TARGET_OUT_UNSTRIPPED)/%, $(my_unstripped_path))
       symbolic_output := $(my_unstripped_path)/$(my_installed_module_stem)
-      $(eval $(call copy-unstripped-elf-file-with-mapping,$(LOCAL_SOONG_UNSTRIPPED_BINARY),$(symbolic_output)))
+      elf_symbol_mapping_path := $(patsubst $(TARGET_OUT_UNSTRIPPED)/%,$(call intermediates-dir-for,PACKAGING,elf_symbol_mapping)/%,$(symbolic_output).textproto)
+
+      ALL_MODULES.$(my_register_name).SYMBOLIC_OUTPUT_PATH := $(symbolic_output)
+      ALL_MODULES.$(my_register_name).ELF_SYMBOL_MAPPING_PATH := $(elf_symbol_mapping_path)
+
+      $(eval $(call copy-unstripped-elf-file-with-mapping,$(LOCAL_SOONG_UNSTRIPPED_BINARY),$(symbolic_output),$(elf_symbol_mapping_path)))
       $(LOCAL_BUILT_MODULE): | $(symbolic_output)
 
       ifeq ($(BREAKPAD_GENERATE_SYMBOLS),true)
diff --git a/core/soong_config.mk b/core/soong_config.mk
index f5c5238..b774648 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -570,6 +570,10 @@
 
   $(call add_json_str, ReleaseToolsExtensionDir, $(firstword $(TARGET_RELEASETOOLS_EXTENSIONS) $($(TARGET_DEVICE_DIR)/../common)))
 
+  $(call add_json_list, BoardPartialOtaUpdatePartitionsList, $(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST))
+  $(call add_json_str, BoardFlashBlockSize, $(BOARD_FLASH_BLOCK_SIZE))
+  $(call add_json_bool, BootloaderInUpdatePackage, $(BOARD_BOOTLOADER_IN_UPDATE_PACKAGE))
+
   # Fastboot
   $(call add_json_str, BoardFastbootInfoFile, $(TARGET_BOARD_FASTBOOT_INFO_FILE))
 
diff --git a/tools/aconfig/convert_finalized_flags/src/lib.rs b/tools/aconfig/convert_finalized_flags/src/lib.rs
index d79c509..335a31b 100644
--- a/tools/aconfig/convert_finalized_flags/src/lib.rs
+++ b/tools/aconfig/convert_finalized_flags/src/lib.rs
@@ -26,6 +26,8 @@
 use std::fs;
 use std::io::{self, BufRead};
 
+const SDK_INT_MULTIPLIER: u32 = 100_000;
+
 /// Just the fully qualified flag name (package_name.flag_name).
 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
 pub struct FinalizedFlag {
@@ -81,6 +83,24 @@
     }
 }
 
+#[allow(dead_code)] // TODO: b/378936061: Use with SDK_INT_FULL check.
+fn parse_full_version(version: String) -> Result<u32> {
+    let (major, minor) = if let Some(decimal_index) = version.find('.') {
+        (version[..decimal_index].parse::<u32>()?, version[decimal_index + 1..].parse::<u32>()?)
+    } else {
+        (version.parse::<u32>()?, 0)
+    };
+
+    if major >= 21474 {
+        return Err(anyhow!("Major version too large, must be less than 21474."));
+    }
+    if minor >= SDK_INT_MULTIPLIER {
+        return Err(anyhow!("Minor version too large, must be less than {}.", SDK_INT_MULTIPLIER));
+    }
+
+    Ok(major * SDK_INT_MULTIPLIER + minor)
+}
+
 const EXTENDED_FLAGS_LIST_35: &str = "extended_flags_list_35.txt";
 
 /// Converts a string to an int. Will parse to int even if the string is "X.0".
@@ -461,4 +481,83 @@
             "Provided incorrect file, must be extended_flags_list_35.txt"
         );
     }
+
+    #[test]
+    fn test_parse_full_version_correct_input_major_dot_minor() {
+        let version = parse_full_version("12.34".to_string());
+
+        assert!(version.is_ok());
+        assert_eq!(version.unwrap(), 1_200_034);
+    }
+
+    #[test]
+    fn test_parse_full_version_correct_input_omit_dot_minor() {
+        let version = parse_full_version("1234".to_string());
+
+        assert!(version.is_ok());
+        assert_eq!(version.unwrap(), 123_400_000);
+    }
+
+    #[test]
+    fn test_parse_full_version_incorrect_input_empty_string() {
+        let version = parse_full_version("".to_string());
+
+        assert!(version.is_err());
+    }
+
+    #[test]
+    fn test_parse_full_version_incorrect_input_no_numbers_in_string() {
+        let version = parse_full_version("hello".to_string());
+
+        assert!(version.is_err());
+    }
+
+    #[test]
+    fn test_parse_full_version_incorrect_input_unexpected_patch_version() {
+        let version = parse_full_version("1.2.3".to_string());
+
+        assert!(version.is_err());
+    }
+
+    #[test]
+    fn test_parse_full_version_incorrect_input_leading_dot_missing_major_version() {
+        let version = parse_full_version(".1234".to_string());
+
+        assert!(version.is_err());
+    }
+
+    #[test]
+    fn test_parse_full_version_incorrect_input_trailing_dot_missing_minor_version() {
+        let version = parse_full_version("1234.".to_string());
+
+        assert!(version.is_err());
+    }
+
+    #[test]
+    fn test_parse_full_version_incorrect_input_negative_major_version() {
+        let version = parse_full_version("-12.34".to_string());
+
+        assert!(version.is_err());
+    }
+
+    #[test]
+    fn test_parse_full_version_incorrect_input_negative_minor_version() {
+        let version = parse_full_version("12.-34".to_string());
+
+        assert!(version.is_err());
+    }
+
+    #[test]
+    fn test_parse_full_version_incorrect_input_major_version_too_large() {
+        let version = parse_full_version("40000.1".to_string());
+
+        assert!(version.is_err());
+    }
+
+    #[test]
+    fn test_parse_full_version_incorrect_input_minor_version_too_large() {
+        let version = parse_full_version("3.99999999".to_string());
+
+        assert!(version.is_err());
+    }
 }