Merge "Register APKCERTS_FILE on PACKAGES variable for prebuilt_apex" into main
diff --git a/common/math.mk b/common/math.mk
index 829ceb5..0444631 100644
--- a/common/math.mk
+++ b/common/math.mk
@@ -89,6 +89,11 @@
 $(strip $(if $(call math_is_number_in_100,$(1)),true,$(call _math_ext_is_number,$(1))))
 endef
 
+# Returns true if $(1) is a positive or negative integer.
+define math_is_int
+$(call math_is_number,$(patsubst -%,%,$(1)))
+endef
+
 define math_is_zero
 $(strip \
   $(if $(word 2,$(1)),$(call math-error,Multiple words in a single argument: $(1))) \
@@ -100,6 +105,12 @@
 $(call math-expect-true,(call math_is_number,202412))
 $(call math-expect-false,(call math_is_number,foo))
 $(call math-expect-false,(call math_is_number,-1))
+$(call math-expect-true,(call math_is_int,50))
+$(call math-expect-true,(call math_is_int,-1))
+$(call math-expect-true,(call math_is_int,-528))
+$(call math-expect-true,(call math_is_int,-0))
+$(call math-expect-false,(call math_is_int,--1))
+$(call math-expect-false,(call math_is_int,-))
 $(call math-expect-error,(call math_is_number,1 2),Multiple words in a single argument: 1 2)
 $(call math-expect-error,(call math_is_number,no 2),Multiple words in a single argument: no 2)
 
diff --git a/core/Makefile b/core/Makefile
index 1f2a459..7b7258d 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -6048,7 +6048,7 @@
 	$(hide) echo "avb_vbmeta_vendor_rollback_index_location=$(BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX_LOCATION)" >> $@
 endif # BOARD_AVB_VBMETA_VENDOR_KEY_PATH
 ifneq (,$(strip $(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS)))
-	$(hide) echo "avb_custom_vbmeta_images_partition_list=$(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS)" >> $@
+	$(hide) echo "avb_custom_vbmeta_images_partition_list=$(sort $(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS))" >> $@
 	$(hide) $(foreach partition,$(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS),\
 	echo "avb_vbmeta_$(partition)=$(BOARD_AVB_VBMETA_$(call to-upper,$(partition)))" >> $@ ;\
 	echo "avb_vbmeta_$(partition)_args=$(BOARD_AVB_MAKE_VBMETA_$(call to-upper,$(partition))_IMAGE_ARGS)" >> $@ ;\
@@ -6119,6 +6119,7 @@
 ifneq ($(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST),)
 	$(hide) echo "partial_ota_update_partitions_list=$(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST)" >> $@
 endif
+	$(hide) sort -o $@ $@
 
 $(call declare-0p-target,$(INSTALLED_FASTBOOT_INFO_TARGET))
 
@@ -7602,6 +7603,12 @@
 	PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$(dir $(ZIP2ZIP)):$$PATH \
 	    $(IMG_FROM_TARGET_FILES) \
 	        --additional IMAGES/VerifiedBootParams.textproto:VerifiedBootParams.textproto \
+			$(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+					$(if $(BOARD_$(call to-upper,$(partition))_IMAGE_NO_FLASHALL), \
+						--exclude IMAGES/$(partition).img \
+						--exclude IMAGES/$(partition).map \
+					) \
+			) \
 	        --build_super_image $(BUILD_SUPER_IMAGE) \
 	        $(BUILT_TARGET_FILES_PACKAGE) $@
 
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index b2c4fb5..223305e 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -176,6 +176,7 @@
 else ifneq (platform:services,$(lastword $(PRODUCT_SYSTEM_SERVER_JARS)))
   # If services is not the final jar in the dependency ordering, don't assume
   # it can be safely optimized in isolation, as there may be dependent jars.
+  # TODO(b/212737576): Remove this exception after integrating use of `$(system_server_trace_refs)`.
   SYSTEM_OPTIMIZE_JAVA ?= false
 else
   SYSTEM_OPTIMIZE_JAVA ?= true
@@ -188,6 +189,20 @@
 $(call add_soong_config_var,ANDROID,SYSTEM_OPTIMIZE_JAVA)
 $(call add_soong_config_var,ANDROID,FULL_SYSTEM_OPTIMIZE_JAVA)
 
+ifeq (true, $(SYSTEM_OPTIMIZE_JAVA))
+  # Create a list of (non-prefixed) system server jars that follow `services` in
+  # the classpath. This can be used when optimizing `services` to trace any
+  # downstream references that need keeping.
+  # Example: "foo:service1 platform:services bar:services2" -> "services2"
+  system_server_jars_dependent_on_services := $(shell \
+      echo "$(PRODUCT_SYSTEM_SERVER_JARS)" | \
+      awk '{found=0; for(i=1;i<=NF;i++){if($$i=="platform:services"){found=1; continue} if(found){split($$i,a,":"); print a[2]}}}' | \
+      xargs)
+  ifneq ($(strip $(system_server_jars_dependent_on_services)),)
+    $(call soong_config_set_string_list,ANDROID,system_server_trace_refs,$(system_server_jars_dependent_on_services))
+  endif
+endif
+
 # TODO(b/319697968): Remove this build flag support when metalava fully supports flagged api
 $(call soong_config_set,ANDROID,release_hidden_api_exportable_stubs,$(RELEASE_HIDDEN_API_EXPORTABLE_STUBS))
 
@@ -355,3 +370,11 @@
 
 # Flags used in GTVS_GTV prebuilt apps
 $(call soong_config_set_bool,GTVS_GTV,PRODUCT_USE_PREBUILT_GTVS_GTV,$(if $(findstring $(PRODUCT_USE_PREBUILT_GTVS_GTV),true yes),true,false))
+
+# Check modules to be built in "otatools-package".
+ifneq ($(wildcard vendor/google/tools),)
+  $(call soong_config_set_bool,otatools,use_vendor_google_tools,true)
+endif
+ifneq ($(wildcard bootable/deprecated-ota/applypatch),)
+  $(call soong_config_set_bool,otatools,use_bootable_deprecated_ota_applypatch,true)
+endif
diff --git a/core/config.mk b/core/config.mk
index fafdfe1..38f3f5b 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -330,6 +330,19 @@
 $(eval SOONG_CONFIG_TYPE_$(strip $1)_$(strip $2):=bool)
 endef
 
+# soong_config_set_int is the same as soong_config_set, but it will
+# also type the variable as an integer, so that when using select() expressions
+# in blueprint files they can use integer values instead of strings.
+# It will error out if a non-integer is supplied
+# $1 is the namespace. $2 is the variable name. $3 is the variable value.
+# Ex: $(call soong_config_set_bool,acme,COOL_FEATURE,34)
+define soong_config_set_int
+$(call soong_config_define_internal,$1,$2) \
+$(if $(call math_is_int,$3),,$(error soong_config_set_int called with non-integer value $(3)))
+$(eval SOONG_CONFIG_$(strip $1)_$(strip $2):=$(strip $3))
+$(eval SOONG_CONFIG_TYPE_$(strip $1)_$(strip $2):=int)
+endef
+
 # soong_config_set_string_list is the same as soong_config_set, but it will
 # also type the variable as a list of strings, so that when using select() expressions
 # in blueprint files they can use list values instead of strings.
diff --git a/core/layoutlib_data.mk b/core/layoutlib_data.mk
index f228ef6..5dde50f 100644
--- a/core/layoutlib_data.mk
+++ b/core/layoutlib_data.mk
@@ -77,15 +77,23 @@
 LAYOUTLIB_RES := $(call intermediates-dir-for,PACKAGING,layoutlib-res,HOST,COMMON)
 LAYOUTLIB_RES_FILES := $(shell find frameworks/base/core/res/res -type f -not -path 'frameworks/base/core/res/res/values-m[nc]c*' | sort)
 EMULATED_OVERLAYS_FILES := $(shell find frameworks/base/packages/overlays/*/res/ | sort)
-DEVICE_OVERLAYS_FILES := $(shell find device/generic/goldfish/phone/overlay/frameworks/base/packages/overlays/*/AndroidOverlay/res/ | sort)
-$(LAYOUTLIB_RES)/layoutlib-res.zip: $(SOONG_ZIP) $(HOST_OUT_EXECUTABLES)/aapt2 $(LAYOUTLIB_RES_FILES) $(EMULATED_OVERLAYS_FILES) $(DEVICE_OVERLAYS_FILES)
+LAYOUTLIB_SUPPORTED_DEVICES := raviole/oriole raviole/raven bluejay/bluejay pantah/panther pantah/cheetah lynx/lynx felix/felix shusky/shiba shusky/husky akita/akita caimito/tokay caimito/caiman caimito/komodo comet/comet tangorpro/tangorpro
+LAYOUTLIB_DEVICE_OVERLAYS_FILES := $(addsuffix /overlay/frameworks/base/core/res/res/values/*, $(addprefix device/google/, $(LAYOUTLIB_SUPPORTED_DEVICES)))
+LAYOUTLIB_DEVICE_OVERLAYS_FILES := $(shell find $(LAYOUTLIB_DEVICE_OVERLAYS_FILES) | sort)
+$(LAYOUTLIB_RES)/layoutlib-res.zip: $(SOONG_ZIP) $(HOST_OUT_EXECUTABLES)/aapt2 $(LAYOUTLIB_RES_FILES) $(EMULATED_OVERLAYS_FILES) $(LAYOUTLIB_DEVICE_OVERLAYS_FILES) frameworks/layoutlib/overlay_codenames.txt
 	rm -rf $@
 	echo $(LAYOUTLIB_RES_FILES) > $(LAYOUTLIB_RES)/filelist_res.txt
 	$(SOONG_ZIP) -C frameworks/base/core/res -l $(LAYOUTLIB_RES)/filelist_res.txt -o $(LAYOUTLIB_RES)/temp_res.zip
 	echo $(EMULATED_OVERLAYS_FILES) > $(LAYOUTLIB_RES)/filelist_emulated_overlays.txt
 	$(SOONG_ZIP) -C frameworks/base/packages -l $(LAYOUTLIB_RES)/filelist_emulated_overlays.txt -o $(LAYOUTLIB_RES)/temp_emulated_overlays.zip
-	echo $(DEVICE_OVERLAYS_FILES) > $(LAYOUTLIB_RES)/filelist_device_overlays.txt
-	$(SOONG_ZIP) -C device/generic/goldfish/phone/overlay/frameworks/base/packages -l $(LAYOUTLIB_RES)/filelist_device_overlays.txt -o $(LAYOUTLIB_RES)/temp_device_overlays.zip
+	for line in $$(cut -f 1 frameworks/layoutlib/overlay_codenames.txt); \
+	  do splitLine=($${line//:/ }) \
+	  origin_dir=device/google/*/$${splitLine[0]}/overlay/frameworks/base/core/res/res/values; \
+	  target_dir=$(LAYOUTLIB_RES)/overlays/$${splitLine[1]}/res/; \
+	  mkdir -p $$target_dir; \
+	  cp -r $$origin_dir $$target_dir; \
+	done
+	$(SOONG_ZIP) -C $(LAYOUTLIB_RES) -D $(LAYOUTLIB_RES)/overlays/ -o $(LAYOUTLIB_RES)/temp_device_overlays.zip
 	rm -rf $(LAYOUTLIB_RES)/data && unzip -q -d $(LAYOUTLIB_RES)/data $(LAYOUTLIB_RES)/temp_res.zip
 	unzip -q -d $(LAYOUTLIB_RES)/data $(LAYOUTLIB_RES)/temp_emulated_overlays.zip
 	unzip -q -d $(LAYOUTLIB_RES)/data $(LAYOUTLIB_RES)/temp_device_overlays.zip
@@ -163,14 +171,18 @@
 	  echo $(_path),,,,,,Y,$f,,, >> $@; \
 	)
 
-	$(foreach f,$(DEVICE_OVERLAYS_FILES), \
-	  $(eval _path := $(subst device/generic/goldfish/phone/overlay/frameworks/base/packages,data,$f)) \
-	  echo $(_path),,,,,,Y,$f,,, >> $@; \
-	)
+	for line in $$(cut -f 1 frameworks/layoutlib/overlay_codenames.txt); do \
+	  splitLine=($${line//:/ }); \
+	  for f in $(LAYOUTLIB_DEVICE_OVERLAYS_FILES); do \
+	    if [[ $$f == */$${splitLine[0]}/* ]]; then \
+	      echo data/overlays/$${splitLine[1]}/res/values/$$(basename $$f),,,,,,Y,$$f,,, >> $@; \
+	    fi \
+	  done \
+	done
 
 .PHONY: layoutlib-sbom
 layoutlib-sbom: $(LAYOUTLIB_SBOM)/layoutlib.spdx.json
-$(LAYOUTLIB_SBOM)/layoutlib.spdx.json: $(PRODUCT_OUT)/always_dirty_file.txt $(GEN_SBOM) $(LAYOUTLIB_SBOM)/sbom-metadata.csv $(_layoutlib_font_config_files) $(_layoutlib_fonts_files) $(LAYOUTLIB_BUILD_PROP)/layoutlib-build.prop $(_layoutlib_keyboard_files) $(_layoutlib_hyphen_files) $(LAYOUTLIB_RES_FILES) $(EMULATED_OVERLAYS_FILES) $(DEVICE_OVERLAYS_FILES)
+$(LAYOUTLIB_SBOM)/layoutlib.spdx.json: $(PRODUCT_OUT)/always_dirty_file.txt $(GEN_SBOM) $(LAYOUTLIB_SBOM)/sbom-metadata.csv $(_layoutlib_font_config_files) $(_layoutlib_fonts_files) $(LAYOUTLIB_BUILD_PROP)/layoutlib-build.prop $(_layoutlib_keyboard_files) $(_layoutlib_hyphen_files) $(LAYOUTLIB_RES_FILES) $(EMULATED_OVERLAYS_FILES) $(LAYOUTLIB_DEVICE_OVERLAYS_FILES) frameworks/layoutlib/overlay_codenames.txt
 	rm -rf $@
 	$(GEN_SBOM) --output_file $@ --metadata $(LAYOUTLIB_SBOM)/sbom-metadata.csv --build_version $(BUILD_FINGERPRINT_FROM_FILE) --product_mfr "$(PRODUCT_MANUFACTURER)" --module_name "layoutlib" --json
 
diff --git a/core/product_config.mk b/core/product_config.mk
index 019d711..13907f0 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -485,7 +485,7 @@
 
 # Show a warning wall of text if non-compliance-GSI products set this option.
 ifdef PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT
-  ifeq (,$(filter gsi_arm gsi_arm64 gsi_x86 gsi_x86_64 gsi_car_arm64 gsi_car_x86_64 gsi_tv_arm gsi_tv_arm64,$(PRODUCT_NAME)))
+  ifeq (,$(filter gsi_arm gsi_arm64 gsi_x86 gsi_x86_64 gsi_car_arm64 gsi_car_x86_64 gsi_tv_arm gsi_tv_arm64 clockwork_gsi_google_arm,$(PRODUCT_NAME)))
     $(warning PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT is set but \
       PRODUCT_NAME ($(PRODUCT_NAME)) doesn't look like a GSI for compliance \
       testing. This is a special configuration for compliance GSI, so do make \
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/target/product/generic/Android.bp b/target/product/generic/Android.bp
index c90c61c..0a32a55 100644
--- a/target/product/generic/Android.bp
+++ b/target/product/generic/Android.bp
@@ -124,6 +124,14 @@
         target: "/data/cache",
         name: "cache",
     },
+    {
+        target: "/odm/odm_dlkm/etc",
+        name: "odm_dlkm/etc",
+    },
+    {
+        target: "/vendor/vendor_dlkm/etc",
+        name: "vendor_dlkm/etc",
+    },
 ]
 
 extra_vendor_symlinks = [
@@ -382,6 +390,11 @@
         "android.hidl.allocator@1.0-service",
 
         ///////////////////////////////////////////
+        // media_system_ext
+        ///////////////////////////////////////////
+        "StatementService",
+
+        ///////////////////////////////////////////
         // window_extensions_base
         ///////////////////////////////////////////
         "androidx.window.extensions",
@@ -809,7 +822,6 @@
                 "Shell", // base_system
                 "SimAppDialog", // handheld_system
                 "SoundPicker", // not installed by anyone
-                "StatementService", // media_system
                 "Stk", // generic_system
                 "Tag", // generic_system
                 "TeleService", // handheld_system
diff --git a/target/product/media_system.mk b/target/product/media_system.mk
index af3857e..4df7151 100644
--- a/target/product/media_system.mk
+++ b/target/product/media_system.mk
@@ -35,7 +35,6 @@
     libwebviewchromium_plat_support \
     make_f2fs \
     requestsync \
-    StatementService \
 
 PRODUCT_HOST_PACKAGES += \
     fsck.f2fs \
diff --git a/target/product/media_system_ext.mk b/target/product/media_system_ext.mk
index e79a7eb..455a253 100644
--- a/target/product/media_system_ext.mk
+++ b/target/product/media_system_ext.mk
@@ -20,5 +20,8 @@
 # base_system_ext.mk.
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base_system_ext.mk)
 
+PRODUCT_PACKAGES += \
+    StatementService \
+
 # Window Extensions
 $(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions_base.mk)
diff --git a/tools/aconfig/convert_finalized_flags/Android.bp b/tools/aconfig/convert_finalized_flags/Android.bp
index 5b39560..9ace805 100644
--- a/tools/aconfig/convert_finalized_flags/Android.bp
+++ b/tools/aconfig/convert_finalized_flags/Android.bp
@@ -50,7 +50,11 @@
     srcs: [
         "//prebuilts/sdk:finalized-api-flags",
     ],
+    tool_files: ["extended_flags_list_35.txt"],
     out: ["finalized_flags_record.json"],
     tools: ["convert_finalized_flags"],
-    cmd: "args=\"\" && for f in $(locations //prebuilts/sdk:finalized-api-flags); do args=\"$$args --flag_file_path $$f\"; done && $(location convert_finalized_flags) $$args > $(out)",
+    cmd: "args=\"\" && " +
+        "for f in $(locations //prebuilts/sdk:finalized-api-flags); " +
+        " do args=\"$$args --flag_file_path $$f\"; done && " +
+        "$(location convert_finalized_flags) $$args  --extended-flag-file-path $(location extended_flags_list_35.txt) > $(out)",
 }
diff --git a/tools/aconfig/convert_finalized_flags/extended_flags_list_35.txt b/tools/aconfig/convert_finalized_flags/extended_flags_list_35.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/aconfig/convert_finalized_flags/extended_flags_list_35.txt
diff --git a/tools/aconfig/convert_finalized_flags/src/lib.rs b/tools/aconfig/convert_finalized_flags/src/lib.rs
index 10faa39..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 {
@@ -39,6 +41,9 @@
 #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
 pub struct ApiLevel(pub i32);
 
+/// API level of the extended flags file of version 35
+pub const EXTENDED_FLAGS_35_APILEVEL: ApiLevel = ApiLevel(35);
+
 /// Contains all flags finalized for a given API level.
 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Default)]
 pub struct FinalizedFlagMap(HashMap<ApiLevel, HashSet<FinalizedFlag>>);
@@ -78,6 +83,26 @@
     }
 }
 
+#[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".
 /// Returns error for "X.1".
 fn str_to_api_level(numeric_string: &str) -> Result<ApiLevel> {
@@ -117,30 +142,49 @@
             continue;
         };
 
-        let file = fs::File::open(flag_file)?;
-        let reader = io::BufReader::new(file);
+        let file = fs::File::open(&flag_file)?;
 
-        for qualified_flag_name in reader.lines() {
-            // Split the qualified flag name into package and flag name:
-            // com.my.package.name.my_flag_name -> ['com.my.package.name', 'my_flag_name'].
-            let mut flag: Vec<String> =
-                qualified_flag_name?.rsplitn(2, '.').map(|s| s.to_string()).collect();
-
-            if flag.len() != 2 {
-                continue;
-            }
-
-            let package_name = flag.pop().ok_or(anyhow!("Missing flag package."))?;
-            let flag_name = flag.pop().ok_or(anyhow!("Missing flag name."))?;
-
-            // Only add the flag if it wasn't added in a prior file.
-            data_map.insert_if_new(api_level, FinalizedFlag { flag_name, package_name });
-        }
+        io::BufReader::new(file).lines().for_each(|flag| {
+            let flag =
+                flag.unwrap_or_else(|_| panic!("Failed to read line from file {}", flag_file));
+            let finalized_flag = build_finalized_flag(&flag)
+                .unwrap_or_else(|_| panic!("cannot build finalized flag {}", flag));
+            data_map.insert_if_new(api_level, finalized_flag);
+        });
     }
 
     Ok(data_map)
 }
 
+/// Read the qualified flag names into a FinalizedFlag set
+pub fn read_extend_file_to_map_using_path(extened_file: String) -> Result<HashSet<FinalizedFlag>> {
+    let (_, file_name) =
+        extened_file.rsplit_once('/').ok_or(anyhow!("Invalid file: '{}'", extened_file))?;
+    if file_name != EXTENDED_FLAGS_LIST_35 {
+        return Err(anyhow!("Provided incorrect file, must be {}", EXTENDED_FLAGS_LIST_35));
+    }
+    let file = fs::File::open(extened_file)?;
+    let extended_flags = io::BufReader::new(file)
+        .lines()
+        .map(|flag| {
+            let flag = flag.expect("Failed to read line from extended file");
+            build_finalized_flag(&flag)
+                .unwrap_or_else(|_| panic!("cannot build finalized flag {}", flag))
+        })
+        .collect::<HashSet<FinalizedFlag>>();
+    Ok(extended_flags)
+}
+
+fn build_finalized_flag(qualified_flag_name: &String) -> Result<FinalizedFlag> {
+    // Split the qualified flag name into package and flag name:
+    // com.my.package.name.my_flag_name -> ('com.my.package.name', 'my_flag_name')
+    let (package_name, flag_name) = qualified_flag_name
+        .rsplit_once('.')
+        .ok_or(anyhow!("Invalid qualified flag name format: '{}'", qualified_flag_name))?;
+
+    Ok(FinalizedFlag { flag_name: flag_name.to_string(), package_name: package_name.to_string() })
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -392,4 +436,128 @@
         assert_eq!(map.get_finalized_level(&flags[0]).unwrap(), l35);
         assert_eq!(map.get_finalized_level(&flags[1]).unwrap(), l36);
     }
+
+    #[test]
+    fn test_read_flag_from_extended_file() {
+        let flags = create_test_flags();
+
+        // Create the file <temp_dir>/35/extended_flags_list_35.txt
+        let temp_dir = tempdir().unwrap();
+        let mut file_path = temp_dir.path().to_path_buf();
+        file_path.push("35");
+        fs::create_dir_all(&file_path).unwrap();
+        file_path.push(EXTENDED_FLAGS_LIST_35);
+        let mut file = File::create(&file_path).unwrap();
+
+        // Write all flags to the file.
+        add_flags_to_file(&mut file, &[flags[0].clone(), flags[1].clone()]);
+
+        let flags_set =
+            read_extend_file_to_map_using_path(file_path.to_string_lossy().to_string()).unwrap();
+        assert_eq!(flags_set.len(), 2);
+        assert!(flags_set.contains(&flags[0]));
+        assert!(flags_set.contains(&flags[1]));
+    }
+
+    #[test]
+    fn test_read_flag_from_wrong_extended_file_err() {
+        let flags = create_test_flags();
+
+        // Create the file <temp_dir>/35/extended_flags_list.txt
+        let temp_dir = tempdir().unwrap();
+        let mut file_path = temp_dir.path().to_path_buf();
+        file_path.push("35");
+        fs::create_dir_all(&file_path).unwrap();
+        file_path.push("extended_flags_list.txt");
+        let mut file = File::create(&file_path).unwrap();
+
+        // Write all flags to the file.
+        add_flags_to_file(&mut file, &[flags[0].clone(), flags[1].clone()]);
+
+        let err = read_extend_file_to_map_using_path(file_path.to_string_lossy().to_string())
+            .unwrap_err();
+        assert_eq!(
+            format!("{:?}", err),
+            "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());
+    }
 }
diff --git a/tools/aconfig/convert_finalized_flags/src/main.rs b/tools/aconfig/convert_finalized_flags/src/main.rs
index 38300f6..605e964 100644
--- a/tools/aconfig/convert_finalized_flags/src/main.rs
+++ b/tools/aconfig/convert_finalized_flags/src/main.rs
@@ -23,7 +23,9 @@
 use anyhow::Result;
 use clap::Parser;
 
-use convert_finalized_flags::read_files_to_map_using_path;
+use convert_finalized_flags::{
+    read_extend_file_to_map_using_path, read_files_to_map_using_path, EXTENDED_FLAGS_35_APILEVEL,
+};
 
 const ABOUT_TEXT: &str = "Tool for processing finalized-flags.txt files.
 
@@ -45,11 +47,18 @@
     /// Flags files.
     #[arg(long = "flag_file_path")]
     flag_file_path: Vec<String>,
+
+    #[arg(long)]
+    extended_flag_file_path: String,
 }
 
 fn main() -> Result<()> {
     let cli = Cli::parse();
-    let finalized_flags_map = read_files_to_map_using_path(cli.flag_file_path)?;
+    let mut finalized_flags_map = read_files_to_map_using_path(cli.flag_file_path)?;
+    let extended_flag_set = read_extend_file_to_map_using_path(cli.extended_flag_file_path)?;
+    for flag in extended_flag_set {
+        finalized_flags_map.insert_if_new(EXTENDED_FLAGS_35_APILEVEL, flag);
+    }
 
     let json_str = serde_json::to_string(&finalized_flags_map)?;
     println!("{}", json_str);
diff --git a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
index d323c20..25cba9c 100644
--- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
+++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
@@ -282,7 +282,8 @@
               callable.parameters().joinTo(this, separator = "") { it.type().internalName() }
               append(")")
             }
-            val symbol = Symbol.createMethod(callable.containingClass().qualifiedName(), callableSignature)
+            val symbol =
+                Symbol.createMethod(callable.containingClass().qualifiedName(), callableSignature)
             output.add(Pair(symbol, flag))
           }
         }
@@ -291,7 +292,7 @@
           return item.modifiers
               .findAnnotation("android.annotation.FlaggedApi")
               ?.findAttribute("value")
-              ?.value
+              ?.legacyValue
               ?.let { Flag(it.value() as String) }
         }
       }
@@ -468,8 +469,7 @@
         val classFlagValue =
             flaggedSymbolsInSource
                 .find { it.first.toPrettyString() == symbol.clazz }
-                ?.let { flags.getValue(it.second) }
-                ?: true
+                ?.let { flags.getValue(it.second) } ?: true
         return classFlagValue
       }
     }
diff --git a/tools/otatools_package/Android.bp b/tools/otatools_package/Android.bp
new file mode 100644
index 0000000..f9d79d6
--- /dev/null
+++ b/tools/otatools_package/Android.bp
@@ -0,0 +1,213 @@
+// Copyright (C) 2025 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 {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_genrule_host {
+    name: "otatools_package_dep_jars",
+    tools: ["soong_zip"],
+    compile_multilib: "first",
+    cmd: "mkdir -p $(genDir)/framework && " +
+        "cp $(in) $(genDir)/framework && " +
+        "$(location soong_zip) -o $(out) -C $(genDir) -D $(genDir)/framework",
+    srcs: [
+        ":apksigner",
+        ":boot_signer",
+        ":signapk",
+        ":verity_signer",
+    ],
+    out: ["otatools_package_dep_jars.zip"],
+}
+
+cc_genrule {
+    name: "otatools_package_dep_libs",
+    host_supported: true,
+    device_supported: false,
+    compile_multilib: "first",
+    tools: ["soong_zip"],
+    cmd: "mkdir -p $(genDir)/$$CC_MULTILIB &&" +
+        "cp $(in) $(genDir)/$$CC_MULTILIB && " +
+        "$(location soong_zip) -o $(out) -C $(genDir) -D $(genDir)/$$CC_MULTILIB",
+    srcs: [
+        ":libbase",
+        ":libbrillo",
+        ":libbrillo-stream",
+        ":libc++",
+        "//external/libchrome:libchrome",
+        ":libconscrypt_openjdk_jni",
+        ":libcrypto",
+        ":libcrypto_utils",
+        ":libcutils",
+        ":libevent",
+        ":libext2_blkid",
+        ":libext2_com_err",
+        ":libext2_e2p",
+        ":libext2_quota",
+        ":libext2_uuid",
+        ":libext2fs",
+        ":libext4_utils",
+        ":libfec",
+        ":libhidl-gen-utils",
+        ":libhidlmetadata",
+        ":libicui18n",
+        ":libicuuc",
+        ":liblog",
+        ":liblp",
+        ":liblz4",
+        ":libpcre2",
+        ":libprocessgroup",
+        ":libprotobuf-cpp-lite",
+        ":libselinux",
+        ":libsparse",
+        ":libsqlite",
+        ":libsquashfs_utils",
+        ":libssl",
+        ":libz",
+        ":libziparchive",
+    ],
+    out: ["otatools_package_dep_libs.zip"],
+}
+
+cc_genrule {
+    name: "otatools_package_dep_bins",
+    host_supported: true,
+    device_supported: false,
+    compile_multilib: "first",
+    tools: [
+        "apksigner",
+        "boot_signer",
+        "merge_zips",
+        "signapk",
+        "verity_signer",
+    ],
+    cmd: "mkdir -p $(genDir)/bin && " +
+        "cp $(in) $(genDir)/bin && " +
+        "cp $(location apksigner) $(location boot_signer) $(location merge_zips) $(location signapk) $(location verity_signer) $(genDir)/bin && " +
+        "$(location :soong_zip) -o $(out) -C $(genDir) -D $(genDir)/bin",
+    srcs: [
+        ":aapt2",
+        ":add_img_to_target_files",
+        ":apex_compression_tool",
+        ":apexd_host",
+        ":apexer",
+        ":append2simg",
+        ":avbtool",
+        ":blk_alloc_to_base_fs",
+        ":brillo_update_payload",
+        ":brotli",
+        ":bsdiff",
+        ":build_image",
+        ":build_super_image",
+        ":build_verity_metadata",
+        ":build_verity_tree",
+        ":care_map_generator",
+        ":check_ota_package_signature",
+        ":check_target_files_signatures",
+        ":check_target_files_vintf",
+        ":checkvintf",
+        ":create_brick_ota",
+        ":deapexer",
+        ":debugfs_static",
+        ":delta_generator",
+        ":e2fsck",
+        ":e2fsdroid",
+        ":fc_sort",
+        ":fec",
+        ":fs_config",
+        ":fsck.erofs",
+        ":fsck.f2fs",
+        ":generate_verity_key",
+        ":host_init_verifier",
+        ":img2simg",
+        ":img_from_target_files",
+        ":initrd_bootconfig",
+        ":lpmake",
+        ":lpunpack",
+        ":lz4",
+        ":make_f2fs",
+        ":make_f2fs_casefold",
+        ":merge_ota",
+        ":merge_target_files",
+        "//device/generic/goldfish:mk_combined_img",
+        ":mkbootfs",
+        ":mkbootimg",
+        ":mke2fs",
+        ":mkf2fsuserimg",
+        ":mkfs.erofs",
+        ":mksquashfs",
+        ":mksquashfsimage",
+        ":mkuserimg_mke2fs",
+        ":ota_extractor",
+        ":ota_from_target_files",
+        ":repack_bootimg",
+        ":resize2fs",
+        ":secilc",
+        ":sefcontext_compile",
+        ":sgdisk",
+        ":shflags",
+        ":sign_apex",
+        ":sign_target_files_apks",
+        ":sign_virt_apex",
+        ":simg2img",
+        ":sload_f2fs",
+        ":soong_zip",
+        ":toybox",
+        ":tune2fs",
+        ":unpack_bootimg",
+        ":update_device",
+        ":validate_target_files",
+        ":verity_verifier",
+        ":zip2zip",
+        ":zipalign",
+        ":zucchini",
+    ] + select(soong_config_variable("otatools", "use_vendor_google_tools"), {
+        true: [":build_mixed_kernels_ramdisk_host"],
+        default: [],
+    }) + select(soong_config_variable("otatools", "use_bootable_deprecated_ota_applypatch"), {
+        true: [
+            ":imgdiff",
+            ":update_host_simulator",
+        ],
+        default: [],
+    }),
+    out: ["otatools_package_dep_bins.zip"],
+}
+
+java_genrule_host {
+    name: "otatools_package",
+    tools: ["merge_zips"],
+    compile_multilib: "first",
+    cmd: "$(location merge_zips) $(out) $(in)",
+    srcs: [
+        ":otatools_package_cert_files",
+        ":otatools_package_dep_bins",
+        ":otatools_package_dep_jars",
+        ":otatools_package_dep_libs",
+        ":otatools_package_releasetools",
+    ],
+    // TODO: Rename as "otatools.zip" when the rest files are ready.
+    out: ["otatools_temp.zip"],
+    dist: {
+        targets: [
+            "otatools-package-temp",
+        ],
+    },
+}
+
+otatools_package_cert_files {
+    name: "otatools_package_cert_files",
+}
diff --git a/tools/perf/benchmarks b/tools/perf/benchmarks
index 8cb26c8..38715ea 100755
--- a/tools/perf/benchmarks
+++ b/tools/perf/benchmarks
@@ -202,6 +202,16 @@
     return Change(label="Remove out", change=remove_out, undo=lambda: None)
 
 
+def CleanNinja():
+    """Remove the out directory, and then run lunch to initialize soong"""
+    def clean_ninja():
+        returncode = subprocess.call("rm out/*.ninja out/soong/*.ninja", shell=True)
+        if returncode != 0:
+            report_error(f"Build failed: {' '.join(cmd)}")
+            raise FatalError()
+    return Change(label="Remove ninja files", change=clean_ninja, undo=lambda: None)
+
+
 def NoChange():
     """No change to the source tree."""
     return Change(label="No change", change=lambda: None, undo=lambda: None)
@@ -416,7 +426,7 @@
         """Builds the modules.  Saves interesting log files to log_dir.  Raises FatalError
         if the build fails.
         """
-        sys.stderr.write(f"STARTING BUILD {benchmark.build_description()}\n")
+        sys.stderr.write(f"STARTING BUILD {benchmark.build_description()} Logs to: {build_log_dir}\n")
 
         before_ns = time.perf_counter_ns()
         if not self._options.DryRun():
@@ -713,6 +723,13 @@
                       preroll=1,
                       postroll=3,
                       ),
+            Benchmark(id="full_analysis",
+                      title="Full Analysis",
+                      change=CleanNinja(),
+                      modules=["nothing"],
+                      preroll=1,
+                      postroll=3,
+                      ),
             Benchmark(id="modify_stdio",
                       title="Modify stdio.cpp",
                       change=Modify("bionic/libc/stdio/stdio.cpp", Comment("//")),
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index 3467152..2232385 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -650,3 +650,12 @@
         unit_test: true,
     },
 }
+
+genrule {
+    name: "otatools_package_releasetools",
+    tools: ["soong_zip"],
+    srcs: ["**/*"],
+    cmd: "find build/make/tools/releasetools -name '*.pyc' -prune -o \\( -type f -o -type l \\) -print | sort > $(genDir)/files.txt && " +
+        "$(location soong_zip) -o $(out) -C build/make/tools -l $(genDir)/files.txt",
+    out: ["otatools_package_releasetools.zip"],
+}
diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py
index b7a5ad8..1862577 100755
--- a/tools/releasetools/img_from_target_files.py
+++ b/tools/releasetools/img_from_target_files.py
@@ -35,6 +35,10 @@
       `filespec` arg in zip2zip's help message). The option can be repeated to
       include multiple entries.
 
+  --exclude <filespec>
+      Don't include these files. If the file is in --additional and --exclude,
+      the file will not be included.
+
 """
 
 from __future__ import print_function
@@ -56,6 +60,7 @@
 OPTIONS = common.OPTIONS
 
 OPTIONS.additional_entries = []
+OPTIONS.excluded_entries = []
 OPTIONS.bootable_only = False
 OPTIONS.put_super = None
 OPTIONS.put_bootloader = None
@@ -245,6 +250,9 @@
   # Any additional entries provided by caller.
   entries += OPTIONS.additional_entries
 
+  # Remove any excluded entries
+  entries = [e for e in entries if e not in OPTIONS.excluded_entries]
+
   CopyZipEntries(input_file, output_file, entries)
 
   if rebuild_super:
@@ -258,6 +266,8 @@
       OPTIONS.bootable_only = True
     elif o == '--additional':
       OPTIONS.additional_entries.append(a)
+    elif o == '--exclude':
+      OPTIONS.excluded_entries.append(a)
     elif o == '--build_super_image':
       OPTIONS.build_super_image = a
     else:
@@ -268,6 +278,7 @@
                              extra_opts='z',
                              extra_long_opts=[
                                  'additional=',
+                                 'exclude=',
                                  'bootable_zip',
                                  'build_super_image=',
                              ],