Merge "Add config for FULL_SYSTEM_OPTIMIZE_JAVA" into main
diff --git a/common/math.mk b/common/math.mk
index 0271ea8..ecee474 100644
--- a/common/math.mk
+++ b/common/math.mk
@@ -25,6 +25,7 @@
                       61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
                       81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
 __MATH_NUMBERS := 0 $(__MATH_POS_NUMBERS)
+__MATH_ONE_NUMBERS := 0 1 2 3 4 5 6 7 8 9
 
 math-error = $(call pretty-error,$(1))
 math-expect :=
@@ -36,6 +37,10 @@
 #  make -f ${ANDROID_BUILD_TOP}/build/make/common/math.mk RUN_MATH_TESTS=true
 #  $(get_build_var CKATI) -f ${ANDROID_BUILD_TOP}//build/make/common/math.mk RUN_MATH_TESTS=true
 ifdef RUN_MATH_TESTS
+  ifndef empty
+    empty :=
+    space := $(empty) $(empty)
+  endif
   MATH_TEST_FAILURE :=
   MATH_TEST_ERROR :=
   math-error = $(if $(MATH_TEST_ERROR),,$(eval MATH_TEST_ERROR:=$(1)))
@@ -61,13 +66,29 @@
 endif
 
 # Returns true if $(1) is a non-negative integer <= 100, otherwise returns nothing.
-define math_is_number
+define math_is_number_in_100
 $(strip \
   $(if $(1),,$(call math-error,Argument missing)) \
   $(if $(word 2,$(1)),$(call math-error,Multiple words in a single argument: $(1))) \
   $(if $(filter $(1),$(__MATH_NUMBERS)),true))
 endef
 
+# Same with math_is_number_in_100, but no limit.
+define _math_ext_is_number
+$(strip \
+  $(if $(1),,$(call math-error,Argument missing)) \
+  $(if $(word 2,$(1)),$(call math-error,Multiple words in a single argument: $(1))) \
+  $(eval should_empty:=$(1)) \
+  $(foreach num,$(__MATH_ONE_NUMBERS),\
+    $(eval should_empty:=$(subst $(num),$(empty),$(should_empty)))) \
+  $(if $(should_empty),,true))
+endef
+
+# Returns true if $(1) is a non-negative integer.
+define math_is_number
+$(strip $(if $(call math_is_number_in_100,$(1)),true,$(call _math_ext_is_number,$(1))))
+endef
+
 define math_is_zero
 $(strip \
   $(if $(word 2,$(1)),$(call math-error,Multiple words in a single argument: $(1))) \
@@ -76,6 +97,7 @@
 
 $(call math-expect-true,(call math_is_number,0))
 $(call math-expect-true,(call math_is_number,2))
+$(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-error,(call math_is_number,1 2),Multiple words in a single argument: 1 2)
@@ -88,7 +110,7 @@
 $(call math-expect-error,(call math_is_zero,no 2),Multiple words in a single argument: no 2)
 
 define _math_check_valid
-$(if $(call math_is_number,$(1)),,$(call math-error,Only non-negative integers <= 100 are supported (not $(1))))
+$(if $(call math_is_number_in_100,$(1)),,$(call math-error,Only non-negative integers <= 100 are supported (not $(1))))
 endef
 
 $(call math-expect,(call _math_check_valid,0))
@@ -113,18 +135,81 @@
 $(call math-expect,(call int_range_list,2,1),)
 $(call math-expect-error,(call int_range_list,1,101),Only non-negative integers <= 100 are supported (not 101))
 
+# Split an integer into a list of digits
+define _math_number_to_list
+$(strip \
+  $(if $(call _math_ext_is_number,$(1)),,\
+    $(call math-error,Only non-negative integers are supported (not $(1)))) \
+  $(eval num_list:=$(1)) \
+  $(foreach num,$(__MATH_ONE_NUMBERS),\
+    $(eval num_list:=$(subst $(num),$(space)$(num),$(num_list)))) \
+  $(if $(filter $(words $(num_list)),$(__MATH_ONE_NUMBERS)),,\
+    $(call math-error,Only non-negative integers with less than 9 digits are supported (not $(1)))) \
+  $(if $(filter 0,$(word 1,$(num_list))),\
+    $(call math-error,Only non-negative integers without leading zeros are supported (not $(1)))) \
+  $(num_list))
+endef
+
+$(call math-expect,(call _math_number_to_list,123),1 2 3)
+$(call math-expect-error,(call _math_number_to_list,123 456),Multiple words in a single argument: 123 456)
+$(call math-expect-error,(call _math_number_to_list,-123),Only non-negative integers are supported (not -123))
+$(call math-expect-error,(call _math_number_to_list,002),Only non-negative integers without leading zeros are supported (not 002))
+$(call math-expect-error,(call _math_number_to_list,1234567890),Only non-negative integers with less than 9 digits are supported (not 1234567890))
+
+# Compare 1-digit integer $(1) and $(2).
+# Returns 1 if $(1) > $(2), -1 if $(1) < $(2), nothing if equals.
+define _math_1digit_comp
+$(strip \
+  $(if $(filter $(1),$(2)),,\
+    $(if $(filter $(1),$(firstword $(filter $(1) $(2),$(__MATH_ONE_NUMBERS)))),-1,1)))
+endef
+
+$(call math-expect,(call _math_1digit_comp,1,1))
+$(call math-expect,(call _math_1digit_comp,0,9),-1)
+$(call math-expect,(call _math_1digit_comp,3,1),1)
+
+# Compare the same $(3)-digit-length integers $(1) and $(2) that are split into a list of digits.
+# Returns 1 if $(1) > $(2), -1 if $(1) < $(2), nothing if equals.
+define _math_list_comp
+$(strip \
+  $(eval ans:=) \
+  $(foreach num,$(call int_range_list,1,$(3)),\
+    $(if $(ans),,$(eval ans:=$(call _math_1digit_comp,$(word $(num),$(1)),$(word $(num),$(2)))))) \
+  $(ans))
+endef
+
+# Compare any two non-negative integers $(1) and $(2).
+# Returns 1 if $(1) > $(2), -1 if $(1) < $(2), nothing if equals.
+define _math_ext_comp
+$(strip \
+  $(eval num_list1:=$(call _math_number_to_list,$(1))) \
+  $(eval len1:=$(words $(num_list1))) \
+  $(eval num_list2:=$(call _math_number_to_list,$(2))) \
+  $(eval len2:=$(words $(num_list2))) \
+  $(eval comp:=$(call _math_1digit_comp,$(len1),$(len2))) \
+  $(if $(comp),$(comp),$(call _math_list_comp,$(num_list1),$(num_list2),$(len1))))
+endef
+
+$(call math-expect,(call _math_ext_comp,5,10),-1)
+$(call math-expect,(call _math_ext_comp,12345,12345))
+$(call math-expect,(call _math_ext_comp,500,5),1)
+$(call math-expect,(call _math_ext_comp,202404,202504),-1)
 
 # Returns the greater of $1 or $2.
-# If $1 or $2 is not a positive integer <= 100, then an error is generated.
+# If $1 or $2 is not a positive integer, then an error is generated.
 define math_max
-$(strip $(call _math_check_valid,$(1)) $(call _math_check_valid,$(2)) \
-  $(lastword $(filter $(1) $(2),$(__MATH_NUMBERS))))
+$(strip \
+  $(if $(filter truetrue,$(call math_is_number_in_100,$(1))$(call math_is_number_in_100,$(2))),\
+    $(lastword $(filter $(1) $(2),$(__MATH_NUMBERS))),\
+    $(if $(filter 1,$(call _math_ext_comp,$(1),$(2))),$(1),$(2))))
 endef
 
 # Returns the lesser of $1 or $2.
 define math_min
-$(strip $(call _math_check_valid,$(1)) $(call _math_check_valid,$(2)) \
-  $(firstword $(filter $(1) $(2),$(__MATH_NUMBERS))))
+$(strip \
+  $(if $(filter truetrue,$(call math_is_number_in_100,$(1))$(call math_is_number_in_100,$(2))),\
+    $(firstword $(filter $(1) $(2),$(__MATH_NUMBERS))),\
+    $(if $(filter -1,$(call _math_ext_comp,$(1),$(2))),$(1),$(2))))
 endef
 
 $(call math-expect-error,(call math_max),Argument missing)
@@ -142,6 +227,15 @@
 $(call math-expect,(call math_min,7,32),7)
 $(call math-expect,(call math_min,32,7),7)
 
+$(call math-expect,(call math_max,32759,7),32759)
+$(call math-expect,(call math_max,7,32759),32759)
+$(call math-expect,(call math_max,202404,202505),202505)
+$(call math-expect,(call math_max,202404,202404),202404)
+$(call math-expect,(call math_min,8908527,32),32)
+$(call math-expect,(call math_min,32,8908527),32)
+$(call math-expect,(call math_min,202404,202505),202404)
+$(call math-expect,(call math_min,202404,202404),202404)
+
 define math_gt_or_eq
 $(if $(filter $(1),$(call math_max,$(1),$(2))),true)
 endef
@@ -150,6 +244,10 @@
 $(if $(call math_gt_or_eq,$(2),$(1)),,true)
 endef
 
+define math_lt_or_eq
+$(if $(call math_gt_or_eq,$(2),$(1)),true)
+endef
+
 define math_lt
 $(if $(call math_gt_or_eq,$(1),$(2)),,true)
 endef
@@ -160,10 +258,17 @@
 $(call math-expect-true,(call math_gt, 4, 3))
 $(call math-expect-false,(call math_gt, 5, 5))
 $(call math-expect-false,(call math_gt, 6, 7))
+$(call math-expect-true,(call math_lt_or_eq, 11, 11))
+$(call math-expect-false,(call math_lt_or_eq, 25, 15))
+$(call math-expect-true,(call math_lt_or_eq, 9, 16))
 $(call math-expect-false,(call math_lt, 1, 0))
 $(call math-expect-false,(call math_lt, 8, 8))
 $(call math-expect-true,(call math_lt, 10, 11))
 
+$(call math-expect-true,(call math_gt_or_eq, 2573904, 2573900))
+$(call math-expect-true,(call math_gt_or_eq, 12345, 12345))
+$(call math-expect-false,(call math_gt_or_eq, 56, 2780))
+
 # $1 is the variable name to increment
 define inc_and_print
 $(strip $(eval $(1) := $($(1)) .)$(words $($(1))))
@@ -192,6 +297,7 @@
 $(call math-expect,(call numbers_less_than,3,0 2 1 3),0 2 1)
 $(call math-expect,(call numbers_less_than,4,0 2 1 3),0 2 1 3)
 $(call math-expect,(call numbers_less_than,3,0 2 1 3 2),0 2 1 2)
+$(call math-expect,(call numbers_less_than,100,0 1000 50 101 100),0 50)
 
 # Returns the words in $2 that are numbers and are greater or equal to $1
 define numbers_greater_or_equal_to
diff --git a/core/Makefile b/core/Makefile
index d371fb8..18f2c39 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -793,9 +793,25 @@
 .PHONY: apkcerts-list
 apkcerts-list: $(APKCERTS_FILE)
 
+intermediates := $(call intermediates-dir-for,PACKAGING,apexkeys)
+APEX_KEYS_FILE := $(intermediates)/apexkeys.txt
+
+all_apex_keys_files := $(sort $(foreach m,$(call product-installed-modules,$(INTERNAL_PRODUCT)),$(ALL_MODULES.$(m).APEX_KEYS_FILE)))
+$(APEX_KEYS_FILE): $(all_apex_keys_files)
+	@mkdir -p $(dir $@)
+	@rm -f $@
+	$(hide) touch $@
+	$(hide) $(foreach file,$^,cat $(file) >> $@ $(newline))
+all_apex_keys_files :=
+
+$(call declare-0p-target,$(APEX_KEYS_FILE))
+
+.PHONY: apexkeys.txt
+apexkeys.txt: $(APEX_KEYS_FILE)
+
 ifneq (,$(TARGET_BUILD_APPS))
   $(call dist-for-goals, apps_only, $(APKCERTS_FILE):apkcerts.txt)
-  $(call dist-for-goals, apps_only, $(SOONG_APEX_KEYS_FILE):apexkeys.txt)
+  $(call dist-for-goals, apps_only, $(APEX_KEYS_FILE):apexkeys.txt)
 endif
 
 
@@ -871,6 +887,9 @@
 $(call declare-1p-target,$(MK2BP_REMAINING_CSV))
 $(call dist-for-goals,droidcore-unbundled,$(MK2BP_REMAINING_CSV))
 
+.PHONY: mk2bp_remaining
+mk2bp_remaining: $(MK2BP_REMAINING_HTML) $(MK2BP_REMAINING_CSV)
+
 # -----------------------------------------------------------------
 # Modules use -Wno-error, or added default -Wall -Werror
 WALL_WERROR := $(PRODUCT_OUT)/wall_werror.txt
@@ -1148,13 +1167,16 @@
 .PHONY: bootimage_16k
 
 BUILT_BOOT_OTA_PACKAGE_16K := $(PRODUCT_OUT)/boot_ota_16k.zip
-$(BUILT_BOOT_OTA_PACKAGE_16K): $(OTA_FROM_RAW_IMG) $(BUILT_BOOTIMAGE_16K_TARGET) $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8
+$(BUILT_BOOT_OTA_PACKAGE_16K): $(OTA_FROM_RAW_IMG) $(BUILT_BOOTIMAGE_16K_TARGET) $(INSTALLED_BOOTIMAGE_TARGET) $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8
 	$(OTA_FROM_RAW_IMG) --package_key $(DEFAULT_SYSTEM_DEV_CERTIFICATE) \
                       --max_timestamp `cat $(BUILD_DATETIME_FILE)` \
                       --path $(HOST_OUT) \
                       --partition_name boot \
                       --output $@ \
-                      $(BUILT_BOOTIMAGE_16K_TARGET)
+                      $(if $(BOARD_16K_OTA_USE_INCREMENTAL),\
+                        $(INSTALLED_BOOTIMAGE_TARGET):$(BUILT_BOOTIMAGE_16K_TARGET),\
+                        $(BUILT_BOOTIMAGE_16K_TARGET)\
+                      )
 
 boototapackage_16k: $(BUILT_BOOT_OTA_PACKAGE_16K)
 .PHONY: boototapackage_16k
@@ -1284,11 +1306,8 @@
 INTERNAL_BOOTIMAGE_ARGS := \
 	$(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET))
 
-# TODO(b/229701033): clean up BOARD_BUILD_GKI_BOOT_IMAGE_WITHOUT_RAMDISK.
-ifneq ($(BOARD_BUILD_GKI_BOOT_IMAGE_WITHOUT_RAMDISK),true)
-  ifneq ($(BUILDING_INIT_BOOT_IMAGE),true)
-    INTERNAL_BOOTIMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET)
-  endif
+ifneq ($(BUILDING_INIT_BOOT_IMAGE),true)
+  INTERNAL_BOOTIMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET)
 endif
 
 ifndef BUILDING_VENDOR_BOOT_IMAGE
@@ -1484,13 +1503,16 @@
 
 ifneq ($(BOARD_KERNEL_PATH_16K),)
 BUILT_BOOT_OTA_PACKAGE_4K := $(PRODUCT_OUT)/boot_ota_4k.zip
-$(BUILT_BOOT_OTA_PACKAGE_4K): $(OTA_FROM_RAW_IMG) $(INSTALLED_BOOTIMAGE_TARGET) $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8
+$(BUILT_BOOT_OTA_PACKAGE_4K): $(OTA_FROM_RAW_IMG) $(INSTALLED_BOOTIMAGE_TARGET) $(BUILT_BOOTIMAGE_16K_TARGET) $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8
 	$(OTA_FROM_RAW_IMG) --package_key $(DEFAULT_SYSTEM_DEV_CERTIFICATE) \
                       --max_timestamp `cat $(BUILD_DATETIME_FILE)` \
                       --path $(HOST_OUT) \
                       --partition_name boot \
                       --output $@ \
-                      $(INSTALLED_BOOTIMAGE_TARGET)
+                      $(if $(BOARD_16K_OTA_USE_INCREMENTAL),\
+                        $(BUILT_BOOTIMAGE_16K_TARGET):$(INSTALLED_BOOTIMAGE_TARGET),\
+                        $(INSTALLED_BOOTIMAGE_TARGET)\
+                      )
 
 boototapackage_4k: $(BUILT_BOOT_OTA_PACKAGE_4K)
 .PHONY: boototapackage_4k
@@ -2323,8 +2345,6 @@
 )
 $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)),\
     $(hide) echo "recovery_as_boot=true" >> $(1))
-$(if $(filter true,$(BOARD_BUILD_GKI_BOOT_IMAGE_WITHOUT_RAMDISK)),\
-    $(hide) echo "gki_boot_image_without_ramdisk=true" >> $(1))
 $(hide) echo "root_dir=$(TARGET_ROOT_OUT)" >> $(1)
 $(if $(filter true,$(PRODUCT_USE_DYNAMIC_PARTITION_SIZE)),\
     $(hide) echo "use_dynamic_partition_size=true" >> $(1))
@@ -6336,7 +6356,7 @@
 	    $(INSTALLED_MISC_INFO_TARGET) \
 	    $(INSTALLED_FASTBOOT_INFO_TARGET) \
 	    $(APKCERTS_FILE) \
-	    $(SOONG_APEX_KEYS_FILE) \
+	    $(APEX_KEYS_FILE) \
 	    $(SOONG_ZIP) \
 	    $(HOST_OUT_EXECUTABLES)/fs_config \
 	    $(HOST_OUT_EXECUTABLES)/map_file_generator \
@@ -6547,7 +6567,7 @@
 	@# build them.
 	$(hide) mkdir -p $(zip_root)/META
 	$(hide) cp $(APKCERTS_FILE) $(zip_root)/META/apkcerts.txt
-	$(hide) cp $(SOONG_APEX_KEYS_FILE) $(zip_root)/META/apexkeys.txt
+	$(hide) cp $(APEX_KEYS_FILE) $(zip_root)/META/apexkeys.txt
 ifneq ($(tool_extension),)
 	$(hide) cp $(PRIVATE_TOOL_EXTENSION) $(zip_root)/META/
 endif
@@ -6810,7 +6830,7 @@
             $(INSTALLED_MISC_INFO_TARGET) \
             $(INSTALLED_FASTBOOT_INFO_TARGET) \
             $(APKCERTS_FILE) \
-            $(SOONG_APEX_KEYS_FILE) \
+            $(APEX_KEYS_FILE) \
             $(HOST_OUT_EXECUTABLES)/fs_config \
             $(HOST_OUT_EXECUTABLES)/map_file_generator \
             $(ADD_IMG_TO_TARGET_FILES) \
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index c8c3389..c74aa49 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -31,6 +31,7 @@
 $(call add_soong_config_var,ANDROID,TARGET_ENABLE_MEDIADRM_64)
 $(call add_soong_config_var,ANDROID,BOARD_USES_ODMIMAGE)
 $(call add_soong_config_var,ANDROID,BOARD_USES_RECOVERY_AS_BOOT)
+$(call add_soong_config_var,ANDROID,CHECK_DEV_TYPE_VIOLATIONS)
 $(call add_soong_config_var,ANDROID,PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT)
 
 # Default behavior for the tree wrt building modules or using prebuilts. This
diff --git a/core/art_config.mk b/core/art_config.mk
index 1ea05db..f47a8e2 100644
--- a/core/art_config.mk
+++ b/core/art_config.mk
@@ -44,3 +44,17 @@
 endif
 
 ADDITIONAL_PRODUCT_PROPERTIES += ro.dalvik.vm.enable_uffd_gc=$(ENABLE_UFFD_GC)
+
+# Create APEX_BOOT_JARS_EXCLUDED which is a list of jars to be removed from
+# ApexBoorJars when built from mainline prebuilts.
+# soong variables indicate whether the prebuilt is enabled:
+# - $(m)_module/source_build for art and TOGGLEABLE_PREBUILT_MODULES
+# - ANDROID/module_build_from_source for other mainline modules
+APEX_BOOT_JARS_EXCLUDED :=
+$(foreach pair, $(PRODUCT_APEX_BOOT_JARS_FOR_SOURCE_BUILD_ONLY),\
+  $(eval m := $(subst com.android.,,$(call word-colon,1,$(pair)))) \
+  $(if $(call soong_config_get,$(m)_module,source_build), \
+    $(if $(filter true,$(call soong_config_get,$(m)_module,source_build)),, \
+      $(eval APEX_BOOT_JARS_EXCLUDED += $(pair))), \
+    $(if $(filter true,$(call soong_config_get,ANDROID,module_build_from_source)),, \
+      $(eval APEX_BOOT_JARS_EXCLUDED += $(pair)))))
diff --git a/core/artifact_path_requirements.mk b/core/artifact_path_requirements.mk
index 566b9f7..c949cc4 100644
--- a/core/artifact_path_requirements.mk
+++ b/core/artifact_path_requirements.mk
@@ -4,6 +4,7 @@
 # Fakes don't get installed, and NDK stubs aren't installed to device.
 static_allowed_patterns := $(TARGET_OUT_FAKE)/% $(SOONG_OUT_DIR)/ndk/%
 # RROs become REQUIRED by the source module, but are always placed on the vendor partition.
+static_allowed_patterns += %__auto_generated_characteristics_rro.apk
 static_allowed_patterns += %__auto_generated_rro_product.apk
 static_allowed_patterns += %__auto_generated_rro_vendor.apk
 # Auto-included targets are not considered
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 3313b5f..8236dc9 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -124,11 +124,6 @@
 include $(BUILD_SYSTEM)/local_systemsdk.mk
 include $(BUILD_SYSTEM)/local_current_sdk.mk
 
-my_module_tags := $(LOCAL_MODULE_TAGS)
-ifeq ($(my_host_cross),true)
-  my_module_tags :=
-endif
-
 # Ninja has an implicit dependency on the command being run, and kati will
 # regenerate the ninja manifest if any read makefile changes, so there is no
 # need to have dependencies on makefiles.
@@ -148,46 +143,13 @@
 ## Validate and define fallbacks for input LOCAL_* variables.
 ###########################################################
 
-## Dump a .csv file of all modules and their tags
-#ifneq ($(tag-list-first-time),false)
-#$(shell rm -f tag-list.csv)
-#tag-list-first-time := false
-#endif
-#$(shell echo $(lastword $(filter-out config/% out/%,$(MAKEFILE_LIST))),$(LOCAL_MODULE),$(strip $(LOCAL_MODULE_CLASS)),$(subst $(space),$(comma),$(sort $(my_module_tags))) >> tag-list.csv)
-
 LOCAL_UNINSTALLABLE_MODULE := $(strip $(LOCAL_UNINSTALLABLE_MODULE))
-my_module_tags := $(sort $(my_module_tags))
-ifeq (,$(my_module_tags))
-  my_module_tags := optional
-endif
-
-# User tags are not allowed anymore.  Fail early because it will not be installed
-# like it used to be.
-ifneq ($(filter $(my_module_tags),user),)
-  $(warning *** Module name: $(LOCAL_MODULE))
-  $(warning *** Makefile location: $(LOCAL_MODULE_MAKEFILE))
-  $(warning * )
-  $(warning * Module is attempting to use the 'user' tag.  This)
-  $(warning * used to cause the module to be installed automatically.)
-  $(warning * Now, the module must be listed in the PRODUCT_PACKAGES)
-  $(warning * section of a product makefile to have it installed.)
-  $(warning * )
-  $(error user tag detected on module.)
-endif
-
-my_bad_module_tags := $(filter eng debug,$(my_module_tags))
-ifdef my_bad_module_tags
-  ifeq (true,$(LOCAL_UNINSTALLABLE_MODULE))
-    $(call pretty-warning,LOCAL_MODULE_TAGS := $(my_bad_module_tags) does not do anything for uninstallable modules)
-  endif
-  $(call pretty-error,LOCAL_MODULE_TAGS := $(my_bad_module_tags) is obsolete. See $(CHANGES_URL)#LOCAL_MODULE_TAGS)
-endif
 
 # Only the tags mentioned in this test are expected to be set by module
 # makefiles. Anything else is either a typo or a source of unexpected
 # behaviors.
-ifneq ($(filter-out tests optional samples,$(my_module_tags)),)
-$(call pretty-error,unusual tags: $(filter-out tests optional samples,$(my_module_tags)))
+ifneq ($(filter-out tests optional samples,$(LOCAL_MODULE_TAGS)),)
+$(call pretty-error,unusual tags: $(filter-out tests optional samples,$(LOCAL_MODULE_TAGS)))
 endif
 
 LOCAL_MODULE_CLASS := $(strip $(LOCAL_MODULE_CLASS))
@@ -240,7 +202,7 @@
 else
   # The definition of should-install-to-system will be different depending
   # on which goal (e.g., sdk or just droid) is being built.
-  partition_tag := $(if $(call should-install-to-system,$(my_module_tags)),,_DATA)
+  partition_tag := $(if $(call should-install-to-system,$(LOCAL_MODULE_TAGS)),,_DATA)
   actual_partition_tag := $(if $(partition_tag),data,system)
 endif
 endif
@@ -252,7 +214,7 @@
     LOCAL_COMPATIBILITY_SUITE := null-suite
   endif
   ifneq ($(filter APPS, $(LOCAL_MODULE_CLASS)),)
-    ifneq ($(filter $(my_module_tags),tests),)
+    ifneq ($(filter $(LOCAL_MODULE_TAGS),tests),)
       LOCAL_COMPATIBILITY_SUITE := null-suite
     endif
   endif
@@ -947,7 +909,7 @@
 ALL_MODULES.$(my_register_name).PATH := \
     $(ALL_MODULES.$(my_register_name).PATH) $(LOCAL_PATH)
 ALL_MODULES.$(my_register_name).TAGS := \
-    $(ALL_MODULES.$(my_register_name).TAGS) $(my_module_tags)
+    $(ALL_MODULES.$(my_register_name).TAGS) $(LOCAL_MODULE_TAGS)
 ALL_MODULES.$(my_register_name).CHECKED := \
     $(ALL_MODULES.$(my_register_name).CHECKED) $(my_checked_module)
 ALL_MODULES.$(my_register_name).BUILT := \
@@ -1180,6 +1142,7 @@
 ALL_MODULES.$(my_register_name).TEST_MAINLINE_MODULES := $(LOCAL_TEST_MAINLINE_MODULES)
 ifndef LOCAL_IS_HOST_MODULE
 ALL_MODULES.$(my_register_name).FILE_CONTEXTS := $(LOCAL_FILE_CONTEXTS)
+ALL_MODULES.$(my_register_name).APEX_KEYS_FILE := $(LOCAL_APEX_KEY_PATH)
 endif
 ifdef LOCAL_IS_UNIT_TEST
 ALL_MODULES.$(my_register_name).IS_UNIT_TEST := $(LOCAL_IS_UNIT_TEST)
@@ -1193,11 +1156,9 @@
 
 ##########################################################
 # Track module-level dependencies.
-# Use $(LOCAL_MODULE) instead of $(my_register_name) to ignore module's bitness.
 # (b/204397180) Unlock RECORD_ALL_DEPS was acknowledged reasonable for better Atest performance.
-ALL_DEPS.MODULES += $(LOCAL_MODULE)
-ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS := $(sort \
-  $(ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS) \
+ALL_MODULES.$(my_register_name).ALL_DEPS := \
+  $(ALL_MODULES.$(my_register_name).ALL_DEPS) \
   $(LOCAL_STATIC_LIBRARIES) \
   $(LOCAL_WHOLE_STATIC_LIBRARIES) \
   $(LOCAL_SHARED_LIBRARIES) \
@@ -1207,21 +1168,7 @@
   $(LOCAL_HEADER_LIBRARIES) \
   $(LOCAL_STATIC_JAVA_LIBRARIES) \
   $(LOCAL_JAVA_LIBRARIES) \
-  $(LOCAL_JNI_SHARED_LIBRARIES))
-
-license_files := $(call find-parent-file,$(LOCAL_PATH),MODULE_LICENSE*)
-ALL_DEPS.$(LOCAL_MODULE).LICENSE := $(sort $(ALL_DEPS.$(LOCAL_MODULE).LICENSE) $(license_files))
-
-###########################################################
-## Take care of my_module_tags
-###########################################################
-
-# Keep track of all the tags we've seen.
-ALL_MODULE_TAGS := $(sort $(ALL_MODULE_TAGS) $(my_module_tags))
-
-# Add this module name to the tag list of each specified tag.
-$(foreach tag,$(filter-out optional,$(my_module_tags)),\
-    $(eval ALL_MODULE_NAME_TAGS.$(tag) := $$(ALL_MODULE_NAME_TAGS.$(tag)) $(my_register_name)))
+  $(LOCAL_JNI_SHARED_LIBRARIES)
 
 ###########################################################
 ## umbrella targets used to verify builds
@@ -1249,7 +1196,7 @@
 
 ifdef j_or_n
 $(j_or_n) $(h_or_t) $(j_or_n)-$(h_or_hc_or_t) : $(my_checked_module)
-ifneq (,$(filter $(my_module_tags),tests))
+ifneq (,$(filter $(LOCAL_MODULE_TAGS),tests))
 $(j_or_n)-$(h_or_t)-tests $(j_or_n)-tests $(h_or_t)-tests : $(my_checked_module)
 endif
 $(LOCAL_MODULE)-$(h_or_hc_or_t) : $(my_all_targets)
diff --git a/core/binary.mk b/core/binary.mk
index e2e5be4..4c68ba7 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -354,17 +354,15 @@
 # MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
 # all code is position independent, and then those warnings get promoted to
 # errors.
-ifneq ($(LOCAL_NO_PIC),true)
-  ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
-    my_cflags += -fPIE
-    ifndef BUILD_HOST_static
-      ifneq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
-        my_ldflags += -pie
-      endif
+ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
+  my_cflags += -fPIE
+  ifndef BUILD_HOST_static
+    ifneq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
+      my_ldflags += -pie
     endif
-  else
-    my_cflags += -fPIC
   endif
+else
+  my_cflags += -fPIC
 endif
 
 ifdef LOCAL_IS_HOST_MODULE
@@ -1437,17 +1435,6 @@
       $(call intermediates-dir-for, \
         STATIC_LIBRARIES,$(lib),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/$(lib)$(a_suffix))
 
-# We don't care about installed static libraries, since the
-# libraries have already been linked into the module at that point.
-# We do, however, care about the NOTICE files for any static
-# libraries that we use. (see notice_files.mk)
-installed_static_library_notice_file_targets := \
-    $(foreach lib,$(my_static_libraries) $(my_whole_static_libraries), \
-      NOTICE-$(if $(LOCAL_IS_HOST_MODULE),HOST$(if $(my_host_cross),_CROSS,),TARGET)-STATIC_LIBRARIES-$(lib))
-
-$(notice_target): | $(installed_static_library_notice_file_targets)
-$(LOCAL_INSTALLED_MODULE): | $(notice_target)
-
 # Default is -fno-rtti.
 ifeq ($(strip $(LOCAL_RTTI_FLAG)),)
 LOCAL_RTTI_FLAG := -fno-rtti
diff --git a/core/board_config.mk b/core/board_config.mk
index b7ca3a4..537fb73 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -202,7 +202,7 @@
 
 # Conditional to building on linux, as dex2oat currently does not work on darwin.
 ifeq ($(HOST_OS),linux)
-  WITH_DEXPREOPT := true
+  WITH_DEXPREOPT ?= true
 endif
 
 # ###############################################################
@@ -989,6 +989,21 @@
 endif
 
 ###########################################
+# BOARD_API_LEVEL for vendor API surface
+ifdef RELEASE_BOARD_API_LEVEL
+  ifdef BOARD_API_LEVEL
+    $(error BOARD_API_LEVEL must not set manully. The build system automatically sets this value.)
+  endif
+  BOARD_API_LEVEL := $(RELEASE_BOARD_API_LEVEL)
+  .KATI_READONLY := BOARD_API_LEVEL
+
+  ifdef RELEASE_BOARD_API_LEVEL_FROZEN
+    BOARD_API_LEVEL_FROZEN := true
+    .KATI_READONLY := BOARD_API_LEVEL_FROZEN
+  endif
+endif
+
+###########################################
 # Handle BUILD_BROKEN_USES_BUILD_*
 
 $(foreach m,$(DEFAULT_WARNING_BUILD_MODULE_TYPES),\
diff --git a/core/cc_prebuilt_internal.mk b/core/cc_prebuilt_internal.mk
index 2de4115..000159a 100644
--- a/core/cc_prebuilt_internal.mk
+++ b/core/cc_prebuilt_internal.mk
@@ -56,9 +56,6 @@
   ifeq ($(filter SHARED_LIBRARIES EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
     $(call pretty-error,Can strip/pack only shared libraries or executables)
   endif
-  ifneq ($(LOCAL_PREBUILT_STRIP_COMMENTS),)
-    $(call pretty-error,Cannot strip/pack scripts)
-  endif
   # Set the arch-specific variables to set up the strip rules
   LOCAL_STRIP_MODULE_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH) := $(my_strip_module)
   include $(BUILD_SYSTEM)/dynamic_binary.mk
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 409e559..b73e9b4 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -5,7 +5,6 @@
 # '',true
 LOCAL_2ND_ARCH_VAR_PREFIX:=
 LOCAL_32_BIT_ONLY:=
-LOCAL_AAPT2_ONLY:=
 LOCAL_AAPT_FLAGS:=
 LOCAL_AAPT_INCLUDE_ALL_RESOURCES:=
 LOCAL_AAPT_NAMESPACES:=
@@ -13,14 +12,11 @@
 LOCAL_ADDITIONAL_CERTIFICATES:=
 LOCAL_ADDITIONAL_CHECKED_MODULE:=
 LOCAL_ADDITIONAL_DEPENDENCIES:=
-LOCAL_ADDITIONAL_HTML_DIR:=
-LOCAL_ADDITIONAL_JAVA_DIR:=
 LOCAL_AIDL_INCLUDES:=
 LOCAL_ALLOW_UNDEFINED_SYMBOLS:=
 LOCAL_ANNOTATION_PROCESSORS:=
 LOCAL_ANNOTATION_PROCESSOR_CLASSES:=
-LOCAL_APIDIFF_NEWAPI:=
-LOCAL_APIDIFF_OLDAPI:=
+LOCAL_APEX_KEY_PATH:=
 LOCAL_APK_LIBRARIES:=
 LOCAL_APK_SET_INSTALL_FILE:=
 LOCAL_APKCERTS_FILE:=
@@ -53,8 +49,6 @@
 LOCAL_CPPFLAGS:=
 LOCAL_CPP_STD:=
 LOCAL_C_STD:=
-LOCAL_CTS_TEST_PACKAGE:=
-LOCAL_CTS_TEST_RUNNER:=
 LOCAL_CXX:=
 LOCAL_CXX_STL := default
 LOCAL_DEX_PREOPT_APP_IMAGE:=
@@ -73,21 +67,11 @@
 LOCAL_DPI_VARIANTS:=
 LOCAL_DROIDDOC_ANNOTATIONS_ZIP :=
 LOCAL_DROIDDOC_API_VERSIONS_XML :=
-LOCAL_DROIDDOC_ASSET_DIR:=
-LOCAL_DROIDDOC_CUSTOM_ASSET_DIR:=
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=
 LOCAL_DROIDDOC_DOC_ZIP :=
-LOCAL_DROIDDOC_HTML_DIR:=
 LOCAL_DROIDDOC_METADATA_ZIP:=
-LOCAL_DROIDDOC_OPTIONS:=
-LOCAL_DROIDDOC_SOURCE_PATH:=
-LOCAL_DROIDDOC_STUB_OUT_DIR:=
 LOCAL_DROIDDOC_STUBS_SRCJAR :=
-LOCAL_DROIDDOC_TEMPLATE_DIR:=
-LOCAL_DROIDDOC_USE_STANDARD_DOCLET:=
 LOCAL_DX_FLAGS:=
 LOCAL_DYLIB_LIBRARIES:=
-LOCAL_EMMA_COVERAGE_FILTER:=
 LOCAL_EMMA_INSTRUMENT:=
 LOCAL_ENFORCE_USES_LIBRARIES:=
 LOCAL_ERROR_PRONE_FLAGS:=
@@ -128,7 +112,6 @@
 LOCAL_INSTALLED_MODULE:=
 LOCAL_INSTALLED_MODULE_STEM:=
 LOCAL_INSTRUMENTATION_FOR:=
-LOCAL_INTERMEDIATE_SOURCE_DIR:=
 LOCAL_INTERMEDIATE_SOURCES:=
 LOCAL_INTERMEDIATE_TARGETS:=
 LOCAL_IS_FUZZ_TARGET:=
@@ -136,15 +119,8 @@
 LOCAL_IS_RUNTIME_RESOURCE_OVERLAY:=
 LOCAL_IS_UNIT_TEST:=
 LOCAL_TEST_OPTIONS_TAGS:=
-LOCAL_JACK_CLASSPATH:=
 LOCAL_JACK_COVERAGE_EXCLUDE_FILTER:=
 LOCAL_JACK_COVERAGE_INCLUDE_FILTER:=
-# '' (ie disabled), disabled, full, incremental, javac_frontend
-LOCAL_JACK_ENABLED:=$(DEFAULT_JACK_ENABLED)
-LOCAL_JACK_FLAGS:=
-LOCAL_JACK_PLUGIN:=
-LOCAL_JACK_PLUGIN_PATH:=
-LOCAL_JACK_PROGUARD_FLAGS:=
 LOCAL_JAR_EXCLUDE_FILES:=
 LOCAL_JAR_EXCLUDE_PACKAGES:=
 LOCAL_JARJAR_RULES:=
@@ -157,7 +133,6 @@
 LOCAL_JAVA_LIBRARIES:=
 LOCAL_JAVA_RESOURCE_DIRS:=
 LOCAL_JAVA_RESOURCE_FILES:=
-LOCAL_JETIFIER_ENABLED:=
 LOCAL_JNI_SHARED_LIBRARIES:=
 LOCAL_JNI_SHARED_LIBRARIES_ABI:=
 LOCAL_CERTIFICATE_LINEAGE:=
@@ -199,10 +174,8 @@
 LOCAL_NDK_VERSION:=current
 LOCAL_NO_CRT:=
 LOCAL_NO_DEFAULT_COMPILER_FLAGS:=
-LOCAL_NO_FPIE :=
 LOCAL_NO_LIBCRT_BUILTINS:=
 LOCAL_NO_NOTICE_FILE:=
-LOCAL_NO_PIC:=
 LOCAL_NOSANITIZE:=
 LOCAL_NO_STANDARD_LIBRARIES:=
 LOCAL_NO_STATIC_ANALYZER:=
@@ -228,7 +201,6 @@
 LOCAL_PREBUILT_MODULE_FILE:=
 LOCAL_PREBUILT_OBJ_FILES:=
 LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES:=
-LOCAL_PREBUILT_STRIP_COMMENTS:=
 LOCAL_USE_EMBEDDED_DEX:=
 LOCAL_USE_EMBEDDED_NATIVE_LIBS:=
 LOCAL_PRESUBMIT_DISABLED:=
@@ -264,7 +236,6 @@
 LOCAL_RES_LIBRARIES:=
 LOCAL_RESOURCE_DIR:=
 LOCAL_RLIB_LIBRARIES:=
-LOCAL_RMTYPEDEFS:=
 LOCAL_ROTATION_MIN_SDK_VERSION:=
 LOCAL_RUNTIME_LIBRARIES:=
 LOCAL_RRO_THEME:=
@@ -338,16 +309,10 @@
 LOCAL_VENDOR_MODULE:=
 LOCAL_VINTF_FRAGMENTS:=
 LOCAL_VNDK_DEPEND_ON_CORE_VARIANT:=
-LOCAL_VTSC_FLAGS:=
-LOCAL_VTS_INCLUDES:=
-LOCAL_VTS_MODE:=
 LOCAL_WARNINGS_ENABLE:=
 LOCAL_WHOLE_STATIC_LIBRARIES:=
 LOCAL_YACCFLAGS:=
 LOCAL_CHECK_ELF_FILES:=
-# TODO: deprecate, it does nothing
-OVERRIDE_BUILT_MODULE_PATH:=
-
 # arch specific variables
 LOCAL_ASFLAGS_$(TARGET_ARCH):=
 LOCAL_CFLAGS_$(TARGET_ARCH):=
diff --git a/core/config.mk b/core/config.mk
index dd780eb..eefd268 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -427,10 +427,10 @@
 endif
 .KATI_READONLY := TARGET_MAX_PAGE_SIZE_SUPPORTED
 
-# Only arm64 arch supports TARGET_MAX_PAGE_SIZE_SUPPORTED greater than 4096.
+# Only arm64 and x86_64 archs supports TARGET_MAX_PAGE_SIZE_SUPPORTED greater than 4096.
 ifneq ($(TARGET_MAX_PAGE_SIZE_SUPPORTED),4096)
-  ifneq ($(TARGET_ARCH),arm64)
-    $(error TARGET_MAX_PAGE_SIZE_SUPPORTED=$(TARGET_MAX_PAGE_SIZE_SUPPORTED) is greater than 4096. Only supported in arm64 arch)
+  ifeq (,$(filter arm64 x86_64,$(TARGET_ARCH)))
+    $(error TARGET_MAX_PAGE_SIZE_SUPPORTED=$(TARGET_MAX_PAGE_SIZE_SUPPORTED) is greater than 4096. Only supported in arm64 and x86_64 archs)
   endif
 endif
 
@@ -813,7 +813,11 @@
 requirements :=
 
 # Set default value of KEEP_VNDK.
-KEEP_VNDK ?= true
+ifeq ($(RELEASE_DEPRECATE_VNDK),true)
+  KEEP_VNDK ?= false
+else
+  KEEP_VNDK ?= true
+endif
 
 # BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED can be true only if early-mount of
 # partitions is supported. But the early-mount must be supported for full
diff --git a/core/definitions.mk b/core/definitions.mk
index ebc6c6e..7a6c064 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -48,20 +48,6 @@
 # set of installed targets.
 ALL_DEFAULT_INSTALLED_MODULES:=
 
-# The list of tags that have been defined by
-# LOCAL_MODULE_TAGS.  Each word in this variable maps
-# to a corresponding ALL_MODULE_TAGS.<tagname> variable
-# that contains all of the INSTALLED_MODULEs with that tag.
-ALL_MODULE_TAGS:=
-
-# Similar to ALL_MODULE_TAGS, but contains the short names
-# of all targets for a particular tag.  The top-level variable
-# won't have the list of tags;  ust ALL_MODULE_TAGS to get
-# the list of all known tags.  (This means that this variable
-# will always be empty; it's just here as a placeholder for
-# its sub-variables.)
-ALL_MODULE_NAME_TAGS:=
-
 # Full path to all asm, C, C++, lex and yacc generated C files.
 # These all have an order-only dependency on the copied headers
 ALL_C_CPP_ETC_OBJECTS:=
@@ -120,9 +106,6 @@
 # All modules already converted to Soong
 SOONG_ALREADY_CONV :=
 
-# ALL_DEPS.*.ALL_DEPS keys
-ALL_DEPS.MODULES :=
-
 ###########################################################
 ## Debugging; prints a variable list to stdout
 ###########################################################
@@ -1295,38 +1278,6 @@
 endef
 
 ###########################################################
-## MODULE_TAG set operations
-###########################################################
-
-# Given a list of tags, return the targets that specify
-# any of those tags.
-# $(1): tag list
-define modules-for-tag-list
-$(sort $(foreach tag,$(1),$(foreach m,$(ALL_MODULE_NAME_TAGS.$(tag)),$(ALL_MODULES.$(m).INSTALLED))))
-endef
-
-# Same as modules-for-tag-list, but operates on
-# ALL_MODULE_NAME_TAGS.
-# $(1): tag list
-define module-names-for-tag-list
-$(sort $(foreach tag,$(1),$(ALL_MODULE_NAME_TAGS.$(tag))))
-endef
-
-# Given an accept and reject list, find the matching
-# set of targets.  If a target has multiple tags and
-# any of them are rejected, the target is rejected.
-# Reject overrides accept.
-# $(1): list of tags to accept
-# $(2): list of tags to reject
-#TODO(dbort): do $(if $(strip $(1)),$(1),$(ALL_MODULE_TAGS))
-#TODO(jbq): as of 20100106 nobody uses the second parameter
-define get-tagged-modules
-$(filter-out \
-  $(call modules-for-tag-list,$(2)), \
-    $(call modules-for-tag-list,$(1)))
-endef
-
-###########################################################
 ## Append a leaf to a base path.  Properly deals with
 ## base paths ending in /.
 ##
@@ -3289,14 +3240,6 @@
 $(hide) cp -p "$<" "$@"
 endef
 
-# The same as copy-file-to-target, but strip out "# comment"-style
-# comments (for config files and such).
-define copy-file-to-target-strip-comments
-@mkdir -p $(dir $@)
-$(hide) rm -f $@
-$(hide) sed -e 's/#.*$$//' -e 's/[ \t]*$$//' -e '/^$$/d' < $< > $@
-endef
-
 # The same as copy-file-to-target, but don't preserve
 # the old modification time.
 define copy-file-to-new-target
@@ -3331,12 +3274,6 @@
 $(copy-file-to-target)
 endef
 
-# Copy a prebuilt file to a target location, stripping "# comment" comments.
-define transform-prebuilt-to-target-strip-comments
-@echo "$($(PRIVATE_PREFIX)DISPLAY) Prebuilt: $(PRIVATE_MODULE) ($@)"
-$(copy-file-to-target-strip-comments)
-endef
-
 # Copy a prebuilt file to a target location, but preserve symlinks rather than
 # dereference them.
 define copy-or-link-prebuilt-to-target
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index 6791125..37a389f 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -58,6 +58,7 @@
 # We can do this only if preopt is enabled and if the product uses libart config (which sets the
 # default properties for preopting).
 ifeq ($(WITH_DEXPREOPT), true)
+ifneq ($(WITH_DEXPREOPT_ART_BOOT_IMG_ONLY), true)
 ifeq ($(PRODUCT_USES_DEFAULT_ART_CONFIG), true)
 
 boot_zip := $(PRODUCT_OUT)/boot.zip
@@ -152,4 +153,5 @@
 
 endif  #ART_MODULE_BUILD_FROM_SOURCE || MODULE_BUILD_FROM_SOURCE
 endif  #PRODUCT_USES_DEFAULT_ART_CONFIG
+endif  #WITH_DEXPREOPT_ART_BOOT_IMG_ONLY
 endif  #WITH_DEXPREOPT
diff --git a/core/dex_preopt_config.mk b/core/dex_preopt_config.mk
index 6739459..10fbe8f 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -58,25 +58,10 @@
 
 # Conditional to building on linux, as dex2oat currently does not work on darwin.
 ifeq ($(HOST_OS),linux)
-  ifeq (eng,$(TARGET_BUILD_VARIANT))
-    # For an eng build only pre-opt the boot image and system server. This gives reasonable performance
-    # and still allows a simple workflow: building in frameworks/base and syncing.
-    WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY ?= true
-  endif
   # Add mini-debug-info to the boot classpath unless explicitly asked not to.
   ifneq (false,$(WITH_DEXPREOPT_DEBUG_INFO))
     PRODUCT_DEX_PREOPT_BOOT_FLAGS += --generate-mini-debug-info
   endif
-
-  # Non eng linux builds must have preopt enabled so that system server doesn't run as interpreter
-  # only. b/74209329
-  ifeq (,$(filter eng, $(TARGET_BUILD_VARIANT)))
-    ifneq (true,$(WITH_DEXPREOPT))
-      ifneq (true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY))
-        $(call pretty-error, DEXPREOPT must be enabled for user and userdebug builds)
-      endif
-    endif
-  endif
 endif
 
 # Get value of a property. It is first searched from PRODUCT_VENDOR_PROPERTIES
@@ -100,7 +85,7 @@
   $(call add_json_bool, DisablePreopt,                           $(call invert_bool,$(ENABLE_PREOPT)))
   $(call add_json_bool, DisablePreoptBootImages,                 $(call invert_bool,$(ENABLE_PREOPT_BOOT_IMAGES)))
   $(call add_json_list, DisablePreoptModules,                    $(DEXPREOPT_DISABLED_MODULES))
-  $(call add_json_bool, OnlyPreoptBootImageAndSystemServer,      $(filter true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY)))
+  $(call add_json_bool, OnlyPreoptArtBootImage            ,      $(filter true,$(WITH_DEXPREOPT_ART_BOOT_IMG_ONLY)))
   $(call add_json_bool, PreoptWithUpdatableBcp,                  $(filter true,$(DEX_PREOPT_WITH_UPDATABLE_BCP)))
   $(call add_json_bool, DontUncompressPrivAppsDex,               $(filter true,$(DONT_UNCOMPRESS_PRIV_APPS_DEXS)))
   $(call add_json_list, ModulesLoadedByPrivilegedModules,        $(PRODUCT_LOADED_BY_PRIVILEGED_MODULES))
@@ -109,7 +94,7 @@
   $(call add_json_bool, DisableGenerateProfile,                  $(filter false,$(WITH_DEX_PREOPT_GENERATE_PROFILE)))
   $(call add_json_str,  ProfileDir,                              $(PRODUCT_DEX_PREOPT_PROFILE_DIR))
   $(call add_json_list, BootJars,                                $(PRODUCT_BOOT_JARS))
-  $(call add_json_list, ApexBootJars,                            $(PRODUCT_APEX_BOOT_JARS))
+  $(call add_json_list, ApexBootJars,                            $(filter-out $(APEX_BOOT_JARS_EXCLUDED), $(PRODUCT_APEX_BOOT_JARS)))
   $(call add_json_list, ArtApexJars,                             $(filter $(PRODUCT_BOOT_JARS),$(ART_APEX_JARS)))
   $(call add_json_list, TestOnlyArtBootImageJars,                $(PRODUCT_TEST_ONLY_ART_BOOT_IMAGE_JARS))
   $(call add_json_list, SystemServerJars,                        $(PRODUCT_SYSTEM_SERVER_JARS))
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index 54a57d1..0155c67 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -60,17 +60,9 @@
   LOCAL_DEX_PREOPT :=
 endif
 
-# if WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY=true and module is not in boot class path skip
-# Also preopt system server jars since selinux prevents system server from loading anything from
-# /data. If we don't do this they will need to be extracted which is not favorable for RAM usage
-# or performance. If my_preopt_for_extracted_apk is true, we ignore the only preopt boot image
-# options.
-system_server_jars := $(foreach m,$(PRODUCT_SYSTEM_SERVER_JARS),$(call word-colon,2,$(m)))
 ifneq (true,$(my_preopt_for_extracted_apk))
-  ifeq (true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY))
-    ifeq ($(filter $(system_server_jars) $(DEXPREOPT_BOOT_JARS_MODULES),$(LOCAL_MODULE)),)
-      LOCAL_DEX_PREOPT :=
-    endif
+  ifeq (true,$(WITH_DEXPREOPT_ART_BOOT_IMG_ONLY))
+    LOCAL_DEX_PREOPT :=
   endif
 endif
 
@@ -226,7 +218,7 @@
 # as a failure to get manifest from an APK).
 ifneq (true,$(WITH_DEXPREOPT))
   LOCAL_ENFORCE_USES_LIBRARIES := false
-else ifeq (true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY))
+else ifeq (true,$(WITH_DEXPREOPT_ART_BOOT_IMG_ONLY))
   LOCAL_ENFORCE_USES_LIBRARIES := false
 endif
 
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 7ddbf32..cfb8a66 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -371,6 +371,8 @@
 TARGET_BUILD_TYPE := release
 endif
 
+include $(BUILD_SYSTEM)/product_validation_checks.mk
+
 # ---------------------------------------------------------------
 # figure out the output directories
 
diff --git a/core/host_java_library_common.mk b/core/host_java_library_common.mk
index 0e62f60..006e6ec 100644
--- a/core/host_java_library_common.mk
+++ b/core/host_java_library_common.mk
@@ -46,5 +46,4 @@
 endif
 endif
 
-LOCAL_INTERMEDIATE_SOURCE_DIR := $(intermediates.COMMON)/src
 LOCAL_JAVA_LIBRARIES := $(sort $(LOCAL_JAVA_LIBRARIES))
diff --git a/core/instrumentation_test_config_template.xml b/core/instrumentation_test_config_template.xml
index 379126c..9dfc001 100644
--- a/core/instrumentation_test_config_template.xml
+++ b/core/instrumentation_test_config_template.xml
@@ -24,7 +24,7 @@
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.{TEST_TYPE}" >
-        {EXTRA_TEST_RUNNER_CONFIGS}<option name="package" value="{PACKAGE}" />
+        <option name="package" value="{PACKAGE}" />
         <option name="runner" value="{RUNNER}" />
     </test>
 </configuration>
diff --git a/core/java.mk b/core/java.mk
index 842fcbf..5fbc916 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -83,8 +83,6 @@
     $(full_classes_stubs_jar) \
     $(java_source_list_file)
 
-LOCAL_INTERMEDIATE_SOURCE_DIR := $(intermediates.COMMON)/src
-
 ###########################################################
 ## AIDL: Compile .aidl files to .java
 ###########################################################
diff --git a/core/java_common.mk b/core/java_common.mk
index a5ed057..c1ccd1a 100644
--- a/core/java_common.mk
+++ b/core/java_common.mk
@@ -194,7 +194,7 @@
 ######################################
 ## PRIVATE java vars
 # LOCAL_SOURCE_FILES_ALL_GENERATED is set only if the module does not have static source files,
-# but generated source files in its LOCAL_INTERMEDIATE_SOURCE_DIR.
+# but generated source files.
 # You have to set up the dependency in some other way.
 need_compile_java := $(strip $(all_java_sources)$(LOCAL_SRCJARS)$(all_res_assets)$(java_resource_sources))$(LOCAL_STATIC_JAVA_LIBRARIES)$(filter true,$(LOCAL_SOURCE_FILES_ALL_GENERATED))
 ifdef need_compile_java
@@ -238,8 +238,6 @@
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JAVA_SOURCES := $(all_java_sources)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JAVA_SOURCE_LIST := $(java_source_list_file)
 
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RMTYPEDEFS := $(LOCAL_RMTYPEDEFS)
-
 # Quickly check class path vars.
 disallowed_deps := $(foreach sdk,$(TARGET_AVAILABLE_SDK_VERSIONS),$(call resolve-prebuilt-sdk-module,$(sdk)))
 disallowed_deps += $(foreach sdk,$(TARGET_AVAILABLE_SDK_VERSIONS),\
@@ -388,7 +386,7 @@
 endif # !LOCAL_IS_HOST_MODULE
 
 # (b/204397180) Record ALL_DEPS by default.
-ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS := $(ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS) $(full_java_bootclasspath_libs)
+ALL_MODULES.$(my_register_name).ALL_DEPS := $(ALL_MODULES.$(my_register_name).ALL_DEPS) $(full_java_bootclasspath_libs)
 
 # Export the SDK libs. The sdk library names listed in LOCAL_SDK_LIBRARIES are first exported.
 # Then sdk library names exported from dependencies are all re-exported.
@@ -492,20 +490,6 @@
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ALL_JAVA_HEADER_LIBRARIES := $(full_java_header_libs)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SHARED_JAVA_HEADER_LIBRARIES := $(full_shared_java_header_libs)
 
-ALL_MODULES.$(my_register_name).INTERMEDIATE_SOURCE_DIR := \
-    $(ALL_MODULES.$(my_register_name).INTERMEDIATE_SOURCE_DIR) $(LOCAL_INTERMEDIATE_SOURCE_DIR)
-
-
-##########################################################
-# Copy NOTICE files of transitive static dependencies
-# Don't do this in mm, since many of the targets won't exist.
-installed_static_library_notice_file_targets := \
-    $(foreach lib,$(LOCAL_STATIC_JAVA_LIBRARIES), \
-      NOTICE-$(if $(LOCAL_IS_HOST_MODULE),HOST$(if $(my_host_cross),_CROSS,),TARGET)-JAVA_LIBRARIES-$(lib))
-
-$(notice_target): | $(installed_static_library_notice_file_targets)
-$(LOCAL_INSTALLED_MODULE): | $(notice_target)
-
 ###########################################################
 # Verify that all libraries are safe to use
 ###########################################################
diff --git a/core/java_prebuilt_internal.mk b/core/java_prebuilt_internal.mk
index be733ff..46393ac 100644
--- a/core/java_prebuilt_internal.mk
+++ b/core/java_prebuilt_internal.mk
@@ -115,11 +115,6 @@
 ifneq ($(my_src_aar),)
 # This is .aar file, archive of classes.jar and Android resources.
 
-# run Jetifier if needed
-LOCAL_JETIFIER_INPUT_FILE := $(my_src_aar)
-include $(BUILD_SYSTEM)/jetifier.mk
-my_src_aar := $(LOCAL_JETIFIER_OUTPUT_FILE)
-
 my_src_jar := $(intermediates.COMMON)/aar/classes.jar
 my_src_proguard_options := $(intermediates.COMMON)/aar/proguard.txt
 my_src_android_manifest := $(intermediates.COMMON)/aar/AndroidManifest.xml
@@ -137,13 +132,6 @@
 $(eval $(call copy-one-file,$(my_src_android_manifest),$(my_prebuilt_android_manifest)))
 $(call add-dependency,$(LOCAL_BUILT_MODULE),$(my_prebuilt_android_manifest))
 
-else
-
-# run Jetifier if needed
-LOCAL_JETIFIER_INPUT_FILE := $(my_src_jar)
-include $(BUILD_SYSTEM)/jetifier.mk
-my_src_jar := $(LOCAL_JETIFIER_OUTPUT_FILE)
-
 endif
 
 $(common_classes_jar) : $(my_src_jar)
diff --git a/core/jetifier.mk b/core/jetifier.mk
deleted file mode 100644
index fff4230..0000000
--- a/core/jetifier.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Copyright (C) 2018 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.
-#
-
-# This file sets up the running of Jetifier
-
-# now add the rule to run jetifier
-ifeq ($(strip $(LOCAL_JETIFIER_ENABLED)),true)
-  my_jetifier_input_path := $(LOCAL_JETIFIER_INPUT_FILE)
-  my_files := $(intermediates.COMMON)/jetifier
-  my_jetifier_output_path := $(my_files)/jetified-$(notdir $(my_jetifier_input_path))
-
-$(my_jetifier_output_path) : $(my_jetifier_input_path) $(JETIFIER)
-	rm -rf $@
-	$(JETIFIER) -l error -o $@ -i $<
-
-  LOCAL_JETIFIER_OUTPUT_FILE := $(my_jetifier_output_path)
-  LOCAL_INTERMEDIATE_TARGETS += $(LOCAL_JETIFIER_OUTPUT_FILE)
-else
-  LOCAL_JETIFIER_OUTPUT_FILE := $(LOCAL_JETIFIER_INPUT_FILE)
-endif
-
diff --git a/core/layoutlib_data.mk b/core/layoutlib_data.mk
index 09e48f3..e45f7ef 100644
--- a/core/layoutlib_data.mk
+++ b/core/layoutlib_data.mk
@@ -86,6 +86,16 @@
 LAYOUTLIB_SBOM := $(call intermediates-dir-for,PACKAGING,layoutlib-sbom,HOST)
 _layoutlib_font_config_files := $(sort $(wildcard frameworks/base/data/fonts/*.xml))
 _layoutlib_fonts_files := $(filter $(TARGET_OUT)/fonts/%.ttf $(TARGET_OUT)/fonts/%.ttc $(TARGET_OUT)/fonts/%.otf, $(INTERNAL_SYSTEMIMAGE_FILES))
+_layoutlib_keyboard_files := $(sort $(wildcard frameworks/base/data/keyboards/*.kcm))
+
+# Find out files disted with layoutlib in Soong.
+### Filter out static libraries for Windows and files already handled in make.
+_layoutlib_filter_out_disted := $(addprefix layoutlib_native/,fonts/% keyboards/% build.prop res.zip windows/%.a)
+_layoutlib_files_disted_by_soong := \
+  $(strip \
+    $(foreach p,$(_all_dist_src_dst_pairs), \
+      $(if $(filter-out $(_layoutlib_filter_out_disted),$(filter layoutlib_native/% layoutlib.jar,$(call word-colon,2,$p))),$p)))
+
 $(LAYOUTLIB_SBOM)/sbom-metadata.csv:
 	rm -rf $@
 	echo installed_file,module_path,soong_module_type,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,build_output_path,static_libraries,whole_static_libraries,is_static_lib >> $@
@@ -102,6 +112,21 @@
 	  echo data/fonts/$(notdir $f),$(_module_path),$(_soong_module_type),,,,,$f,,, >> $@; \
 	)
 
+	$(foreach f,$(_layoutlib_keyboard_files), \
+	  echo data/keyboards/$(notdir $f),frameworks/base/data/keyboards,prebuilt_etc,,,,,$f,,, >> $@; \
+	)
+
+	$(foreach f,$(_layoutlib_files_disted_by_soong), \
+	  $(eval _prebuilt_module_file := $(call word-colon,1,$f)) \
+	  $(eval _dist_file := $(call word-colon,2,$f)) \
+	  $(eval _dist_file := $(patsubst data/windows/%,data/win/lib64/%,$(patsubst layoutlib_native/%,data/%,$(_dist_file)))) \
+	  $(eval _dist_file := $(subst layoutlib.jar,data/layoutlib.jar,$(_dist_file))) \
+	  $(eval _module_name := $(strip $(foreach m,$(ALL_MODULES),$(if $(filter $(_prebuilt_module_file),$(ALL_MODULES.$m.CHECKED)),$m)))) \
+	  $(eval _module_path := $(strip $(sort $(ALL_MODULES.$(_module_name).PATH)))) \
+	  $(eval _soong_module_type := $(strip $(sort $(ALL_MODULES.$(_module_name).SOONG_MODULE_TYPE)))) \
+	  echo $(patsubst layoutlib_native/%,%,$(_dist_file)),$(_module_path),$(_soong_module_type),,,,,$(_prebuilt_module_file),,, >> $@; \
+	)
+
 	$(foreach f,$(LAYOUTLIB_RES_FILES), \
 	  $(eval _path := $(subst frameworks/base/core/res,data,$f)) \
 	  echo $(_path),,,,,,Y,$f,,, >> $@; \
@@ -109,9 +134,9 @@
 
 .PHONY: layoutlib-sbom
 layoutlib-sbom: $(LAYOUTLIB_SBOM)/layoutlib.spdx.json
-$(LAYOUTLIB_SBOM)/layoutlib.spdx.json: $(PRODUCT_OUT)/always_dirty_file.txt $(LAYOUTLIB_SBOM)/sbom-metadata.csv $(_layoutlib_font_config_files) $(_layoutlib_fonts_files) $(LAYOUTLIB_BUILD_PROP)/layoutlib-build.prop $(LAYOUTLIB_RES_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_RES_FILES)
 	rm -rf $@
-	$(GEN_SBOM) --output_file $@ --metadata $(LAYOUTLIB_SBOM)/sbom-metadata.csv --build_version $(BUILD_FINGERPRINT_FROM_FILE) --product_mfr "$(PRODUCT_MANUFACTURER)" --json
+	$(GEN_SBOM) --output_file $@ --metadata $(LAYOUTLIB_SBOM)/sbom-metadata.csv --build_version $(BUILD_FINGERPRINT_FROM_FILE) --product_mfr "$(PRODUCT_MANUFACTURER)" --module_name "layoutlib" --json
 
 $(call dist-for-goals,layoutlib,$(LAYOUTLIB_SBOM)/layoutlib.spdx.json:layoutlib_native/sbom/layoutlib.spdx.json)
 
diff --git a/core/main.mk b/core/main.mk
index c345c96..348a964 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -182,6 +182,12 @@
 $(KATI_obsolete_var PRODUCT_FULL_TREBLE,\
 	Code should be written to work regardless of a device being Treble)
 
+# Set ro.llndk.api_level to show the maximum vendor API level that the LLNDK in
+# the system partition supports.
+ifdef RELEASE_BOARD_API_LEVEL
+ADDITIONAL_SYSTEM_PROPERTIES += ro.llndk.api_level=$(RELEASE_BOARD_API_LEVEL)
+endif
+
 # Sets ro.actionable_compatible_property.enabled to know on runtime whether the
 # allowed list of actionable compatible properties is enabled or not.
 ADDITIONAL_SYSTEM_PROPERTIES += ro.actionable_compatible_property.enabled=true
@@ -293,16 +299,22 @@
 
 # Vendors with GRF must define BOARD_SHIPPING_API_LEVEL for the vendor API level.
 # This must not be defined for the non-GRF devices.
+# The values of the GRF properties will be verified by post_process_props.py
 ifdef BOARD_SHIPPING_API_LEVEL
 ADDITIONAL_VENDOR_PROPERTIES += \
     ro.board.first_api_level=$(BOARD_SHIPPING_API_LEVEL)
+endif
 
-# To manually set the vendor API level of the vendor modules, BOARD_API_LEVEL can be used.
-# The values of the GRF properties will be verified by post_process_props.py
+# Build system set BOARD_API_LEVEL to show the api level of the vendor API surface.
+# This must not be altered outside of build system.
 ifdef BOARD_API_LEVEL
 ADDITIONAL_VENDOR_PROPERTIES += \
     ro.board.api_level=$(BOARD_API_LEVEL)
 endif
+# BOARD_API_LEVEL_FROZEN is true when the vendor API surface is frozen.
+ifdef BOARD_API_LEVEL_FROZEN
+ADDITIONAL_VENDOR_PROPERTIES += \
+    ro.board.api_frozen=$(BOARD_API_LEVEL_FROZEN)
 endif
 
 # Set build prop. This prop is read by ota_from_target_files when generating OTA,
@@ -335,15 +347,14 @@
     ro.build.ab_update=$(AB_OTA_UPDATER)
 endif
 
-# Set ro.product.vndk.version to know the VNDK version required by product
-# modules. It uses the version in PRODUCT_PRODUCT_VNDK_VERSION. If the value
-# is "current", use PLATFORM_VNDK_VERSION.
-ifdef PRODUCT_PRODUCT_VNDK_VERSION
-ifeq ($(KEEP_VNDK),true)
-ifeq ($(PRODUCT_PRODUCT_VNDK_VERSION),current)
+# Set ro.product.vndk.version to PLATFORM_VNDK_VERSION only if
+# KEEP_VNDK is true, PRODUCT_PRODUCT_VNDK_VERSION is current and
+# PLATFORM_VNDK_VERSION is less than or equal to 35.
+# ro.product.vndk.version must be removed for the other future builds.
+ifeq ($(KEEP_VNDK)|$(PRODUCT_PRODUCT_VNDK_VERSION),true|current)
+ifeq ($(call math_is_number,$(PLATFORM_VNDK_VERSION)),true)
+ifeq ($(call math_lt_or_eq,$(PLATFORM_VNDK_VERSION),35),true)
 ADDITIONAL_PRODUCT_PROPERTIES += ro.product.vndk.version=$(PLATFORM_VNDK_VERSION)
-else
-ADDITIONAL_PRODUCT_PROPERTIES += ro.product.vndk.version=$(PRODUCT_PRODUCT_VNDK_VERSION)
 endif
 endif
 endif
@@ -1266,6 +1277,11 @@
     $(if $(filter asan,$(tags_to_install)),$(call get-product-var,$(1),PRODUCT_PACKAGES_DEBUG_ASAN)) \
     $(if $(filter java_coverage,$(tags_to_install)),$(call get-product-var,$(1),PRODUCT_PACKAGES_DEBUG_JAVA_COVERAGE)) \
     $(if $(filter arm64,$(TARGET_ARCH) $(TARGET_2ND_ARCH)),$(call get-product-var,$(1),PRODUCT_PACKAGES_ARM64)) \
+    $(if $(PRODUCT_SHIPPING_API_LEVEL), \
+      $(if $(call math_gt_or_eq,29,$(PRODUCT_SHIPPING_API_LEVEL)),$(call get-product-var,$(1),PRODUCT_PACKAGES_SHIPPING_API_LEVEL_29)) \
+      $(if $(call math_gt_or_eq,33,$(PRODUCT_SHIPPING_API_LEVEL)),$(call get-product-var,$(1),PRODUCT_PACKAGES_SHIPPING_API_LEVEL_33)) \
+      $(if $(call math_gt_or_eq,34,$(PRODUCT_SHIPPING_API_LEVEL)),$(call get-product-var,$(1),PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34)) \
+    ) \
     $(call auto-included-modules) \
   ) \
   $(eval ### Filter out the overridden packages and executables before doing expansion) \
@@ -1412,28 +1428,7 @@
 # var to prevent Make from trying to make a sense of it.
 _unused := $(call copy-many-files, $(sort $(ALL_COMPATIBILITY_DIST_FILES)))
 
-# Don't include any GNU General Public License shared objects or static
-# libraries in SDK images.  GPL executables (not static/dynamic libraries)
-# are okay if they don't link against any closed source libraries (directly
-# or indirectly)
-
-# It's ok (and necessary) to build the host tools, but nothing that's
-# going to be installed on the target (including static libraries).
-
 ifdef is_sdk_build
-  target_gnu_MODULES := \
-              $(filter \
-                      $(TARGET_OUT_INTERMEDIATES)/% \
-                      $(TARGET_OUT)/% \
-                      $(TARGET_OUT_DATA)/%, \
-                              $(sort $(call get-tagged-modules,gnu)))
-  target_gnu_MODULES := $(filter-out $(TARGET_OUT_EXECUTABLES)/%,$(target_gnu_MODULES))
-  target_gnu_MODULES := $(filter-out %/libopenjdkjvmti.so,$(target_gnu_MODULES))
-  target_gnu_MODULES := $(filter-out %/libopenjdkjvmtid.so,$(target_gnu_MODULES))
-  $(info Removing from sdk:)$(foreach d,$(target_gnu_MODULES),$(info : $(d)))
-  modules_to_install := \
-              $(filter-out $(target_gnu_MODULES),$(modules_to_install))
-
   # Ensure every module listed in PRODUCT_PACKAGES* gets something installed
   # TODO: Should we do this for all builds and not just the sdk?
   dangling_modules :=
@@ -2021,13 +2016,6 @@
 .PHONY: check-elf-files
 check-elf-files:
 
-#xxx scrape this from ALL_MODULE_NAME_TAGS
-.PHONY: modules
-modules:
-	@echo "Available sub-modules:"
-	@echo "$(call module-names-for-tag-list,$(ALL_MODULE_TAGS))" | \
-	      tr -s ' ' '\n' | sort -u
-
 .PHONY: dump-files
 dump-files:
 	@echo "Target files for $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) ($(INTERNAL_PRODUCT)):"
@@ -2191,7 +2179,7 @@
 metadata_files := $(subst $(newline),$(space),$(file <$(metadata_list)))
 $(PRODUCT_OUT)/sbom-metadata.csv:
 	rm -f $@
-	echo installed_file,module_path,soong_module_type,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,build_output_path,static_libraries,whole_static_libraries,is_static_lib >> $@
+	echo 'installed_file,module_path,soong_module_type,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,build_output_path,static_libraries,whole_static_libraries,is_static_lib' >> $@
 	$(eval _all_static_libs :=)
 	$(foreach f,$(installed_files),\
 	  $(eval _module_name := $(ALL_INSTALLED_FILES.$f)) \
@@ -2219,7 +2207,7 @@
 	  $(eval _whole_static_libs := $(ALL_INSTALLED_FILES.$f.WHOLE_STATIC_LIBRARIES)) \
 	  $(foreach l,$(_static_libs),$(eval _all_static_libs += $l:$(strip $(sort $(ALL_MODULES.$l.PATH))):$(strip $(sort $(ALL_MODULES.$l.SOONG_MODULE_TYPE))):$(ALL_STATIC_LIBRARIES.$l.BUILT_FILE))) \
 	  $(foreach l,$(_whole_static_libs),$(eval _all_static_libs += $l:$(strip $(sort $(ALL_MODULES.$l.PATH))):$(strip $(sort $(ALL_MODULES.$l.SOONG_MODULE_TYPE))):$(ALL_STATIC_LIBRARIES.$l.BUILT_FILE))) \
-	  echo /$(_path_on_device),$(_module_path),$(_soong_module_type),$(_is_prebuilt_make_module),$(_product_copy_files),$(_kernel_module_copy_files),$(_is_platform_generated),$(_build_output_path),$(_static_libs),$(_whole_static_libs), >> $@; \
+	  echo '/$(_path_on_device),$(_module_path),$(_soong_module_type),$(_is_prebuilt_make_module),$(_product_copy_files),$(_kernel_module_copy_files),$(_is_platform_generated),$(_build_output_path),$(_static_libs),$(_whole_static_libs),' >> $@; \
 	)
 	$(foreach l,$(sort $(_all_static_libs)), \
 	  $(eval _lib_stem := $(call word-colon,1,$l)) \
@@ -2229,7 +2217,7 @@
 	  $(eval _static_libs := $(ALL_STATIC_LIBRARIES.$l.STATIC_LIBRARIES)) \
 	  $(eval _whole_static_libs := $(ALL_STATIC_LIBRARIES.$l.WHOLE_STATIC_LIBRARIES)) \
 	  $(eval _is_static_lib := Y) \
-	  echo $(_lib_stem).a,$(_module_path),$(_soong_module_type),,,,,$(_built_file),$(_static_libs),$(_whole_static_libs),$(_is_static_lib) >> $@; \
+	  echo '$(_lib_stem).a,$(_module_path),$(_soong_module_type),,,,,$(_built_file),$(_static_libs),$(_whole_static_libs),$(_is_static_lib)' >> $@; \
 	)
 
 # (TODO: b/272358583 find another way of always rebuilding sbom.spdx)
diff --git a/core/misc_prebuilt_internal.mk b/core/misc_prebuilt_internal.mk
index 921ea52..a562207 100644
--- a/core/misc_prebuilt_internal.mk
+++ b/core/misc_prebuilt_internal.mk
@@ -27,9 +27,6 @@
 
 ifneq ($(filter init%rc,$(notdir $(LOCAL_INSTALLED_MODULE)))$(filter %/etc/init,$(dir $(LOCAL_INSTALLED_MODULE))),)
   $(eval $(call copy-init-script-file-checked,$(my_prebuilt_src_file),$(LOCAL_BUILT_MODULE)))
-else ifneq ($(LOCAL_PREBUILT_STRIP_COMMENTS),)
-$(LOCAL_BUILT_MODULE) : $(my_prebuilt_src_file)
-	$(transform-prebuilt-to-target-strip-comments)
 else
 $(LOCAL_BUILT_MODULE) : $(my_prebuilt_src_file)
 	$(transform-prebuilt-to-target)
diff --git a/core/ninja_config.mk b/core/ninja_config.mk
index 2b5ceee..d4b7c6d 100644
--- a/core/ninja_config.mk
+++ b/core/ninja_config.mk
@@ -14,7 +14,6 @@
 	$(PARSE_TIME_MAKE_GOALS) \
 	$(dont_bother_goals) \
 	all \
-	ECLIPSE-% \
 	brillo_tests \
 	btnod \
 	build-art% \
diff --git a/core/notice_files.mk b/core/notice_files.mk
index a5852cc..7465cbf 100644
--- a/core/notice_files.mk
+++ b/core/notice_files.mk
@@ -1,36 +1,11 @@
 ###########################################################
 ## Track NOTICE files
 ###########################################################
-$(call record-module-type,NOTICE_FILE)
 
 ifneq ($(LOCAL_NOTICE_FILE),)
-notice_file:=$(strip $(LOCAL_NOTICE_FILE))
+  notice_file:=$(strip $(LOCAL_NOTICE_FILE))
 else
-notice_file:=$(strip $(wildcard $(LOCAL_PATH)/LICENSE $(LOCAL_PATH)/LICENCE $(LOCAL_PATH)/NOTICE))
-endif
-
-ifneq (,$(strip $(LOCAL_LICENSE_PACKAGE_NAME)))
-license_package_name:=$(strip $(LOCAL_LICENSE_PACKAGE_NAME))
-else
-license_package_name:=
-endif
-
-ifneq (,$(strip $(LOCAL_LICENSE_INSTALL_MAP)))
-install_map:=$(strip $(LOCAL_LICENSE_INSTALL_MAP))
-else
-install_map:=
-endif
-
-ifneq (,$(strip $(LOCAL_LICENSE_KINDS)))
-license_kinds:=$(strip $(LOCAL_LICENSE_KINDS))
-else
-license_kinds:=legacy_by_exception_only
-endif
-
-ifneq (,$(strip $(LOCAL_LICENSE_CONDITIONS)))
-license_conditions:=$(strip $(LOCAL_LICENSE_CONDITIONS))
-else
-license_conditions:=by_exception_only
+  notice_file:=$(strip $(wildcard $(LOCAL_PATH)/LICENSE $(LOCAL_PATH)/LICENCE $(LOCAL_PATH)/NOTICE))
 endif
 
 ifeq ($(LOCAL_MODULE_CLASS),GYP)
@@ -51,117 +26,118 @@
   notice_file :=
 endif
 
-ifeq ($(LOCAL_MODULE_CLASS),NOTICE_FILES)
-# If this is a NOTICE-only module, we don't include base_rule.mk,
-# so my_prefix is not set at this point.
-ifeq ($(LOCAL_IS_HOST_MODULE),true)
-  my_prefix := HOST_
-  LOCAL_HOST_PREFIX :=
+module_license_metadata := $(call local-meta-intermediates-dir)/$(my_register_name).meta_lic
+
+$(foreach target,$(ALL_MODULES.$(my_register_name).BUILT) $(ALL_MODULES.$(my_register_name).INSTALLED) $(foreach bi,$(LOCAL_SOONG_BUILT_INSTALLED),$(call word-colon,1,$(bi))),\
+  $(eval ALL_TARGETS.$(target).META_LIC := $(module_license_metadata)))
+
+$(foreach f,$(my_test_data) $(my_test_config),\
+  $(if $(strip $(ALL_TARGETS.$(call word-colon,1,$(f)).META_LIC)), \
+    $(call declare-copy-target-license-metadata,$(call word-colon,2,$(f)),$(call word-colon,1,$(f))), \
+    $(eval ALL_TARGETS.$(call word-colon,2,$(f)).META_LIC := $(module_license_metadata))))
+
+ALL_MODULES.$(my_register_name).META_LIC := $(strip $(ALL_MODULES.$(my_register_name).META_LIC) $(module_license_metadata))
+
+ifdef LOCAL_SOONG_LICENSE_METADATA
+  # Soong modules have already produced a license metadata file, copy it to where Make expects it.
+  $(eval $(call copy-one-license-metadata-file, $(LOCAL_SOONG_LICENSE_METADATA), $(module_license_metadata),$(ALL_MODULES.$(my_register_name).BUILT),$(ALL_MODUES.$(my_register_name).INSTALLED)))
 else
-  my_prefix := TARGET_
-endif
-endif
+  # Make modules don't have enough information to produce a license metadata rule until after fix-notice-deps
+  # has been called, store the necessary information until later.
 
-installed_notice_file :=
-
-is_container:=$(strip $(LOCAL_MODULE_IS_CONTAINER))
-ifeq (,$(is_container))
-ifneq (,$(strip $(filter %.zip %.tar %.tgz %.tar.gz %.apk %.img %.srcszip %.apex, $(LOCAL_BUILT_MODULE))))
-is_container:=true
-else
-is_container:=false
-endif
-else ifneq (,$(strip $(filter-out true false,$(is_container))))
-$(error Unrecognized value '$(is_container)' for LOCAL_MODULE_IS_CONTAINER)
-endif
-
-ifeq (true,$(is_container))
-# Include shared libraries' notices for "container" types, but not for binaries etc.
-notice_deps := \
-    $(strip \
-        $(foreach d, \
-            $(LOCAL_REQUIRED_MODULES) \
-            $(LOCAL_STATIC_LIBRARIES) \
-            $(LOCAL_WHOLE_STATIC_LIBRARIES) \
-            $(LOCAL_SHARED_LIBRARIES) \
-            $(LOCAL_DYLIB_LIBRARIES) \
-            $(LOCAL_RLIB_LIBRARIES) \
-            $(LOCAL_PROC_MACRO_LIBRARIES) \
-            $(LOCAL_HEADER_LIBRARIES) \
-            $(LOCAL_STATIC_JAVA_LIBRARIES) \
-            $(LOCAL_JAVA_LIBRARIES) \
-            $(LOCAL_JNI_SHARED_LIBRARIES) \
-            ,$(subst :,_,$(d)):static \
-        ) \
-    )
-else
-notice_deps := \
-    $(strip \
-        $(foreach d, \
-            $(LOCAL_REQUIRED_MODULES) \
-            $(LOCAL_STATIC_LIBRARIES) \
-            $(LOCAL_WHOLE_STATIC_LIBRARIES) \
-            $(LOCAL_RLIB_LIBRARIES) \
-            $(LOCAL_PROC_MACRO_LIBRARIES) \
-            $(LOCAL_HEADER_LIBRARIES) \
-            $(LOCAL_STATIC_JAVA_LIBRARIES) \
-            ,$(subst :,_,$(d)):static \
-        )$(foreach d, \
-            $(LOCAL_SHARED_LIBRARIES) \
-            $(LOCAL_DYLIB_LIBRARIES) \
-            $(LOCAL_JAVA_LIBRARIES) \
-            $(LOCAL_JNI_SHARED_LIBRARIES) \
-            ,$(subst :,_,$(d)):dynamic \
-        ) \
-    )
-endif
-ifeq ($(LOCAL_IS_HOST_MODULE),true)
-notice_deps := $(strip $(notice_deps) $(foreach d,$(LOCAL_HOST_REQUIRED_MODULES),$(subst :,_,$(d)):static))
-else
-notice_deps := $(strip $(notice_deps) $(foreach d,$(LOCAL_TARGET_REQUIRED_MODULES),$(subst :,_,$(d)):static))
-endif
-
-local_path := $(LOCAL_PATH)
-
-
-module_license_metadata :=
-
-ifdef my_register_name
-  module_license_metadata := $(call local-meta-intermediates-dir)/$(my_register_name).meta_lic
-
-  $(foreach target,$(ALL_MODULES.$(my_register_name).BUILT) $(ALL_MODULES.$(my_register_name).INSTALLED) $(foreach bi,$(LOCAL_SOONG_BUILT_INSTALLED),$(call word-colon,1,$(bi))),\
-    $(eval ALL_TARGETS.$(target).META_LIC := $(module_license_metadata)))
-
-  $(foreach f,$(my_test_data) $(my_test_config),\
-    $(if $(strip $(ALL_TARGETS.$(call word-colon,1,$(f)).META_LIC)), \
-      $(call declare-copy-target-license-metadata,$(call word-colon,2,$(f)),$(call word-colon,1,$(f))), \
-      $(eval ALL_TARGETS.$(call word-colon,2,$(f)).META_LIC := $(module_license_metadata))))
-
-  ALL_MODULES.$(my_register_name).META_LIC := $(strip $(ALL_MODULES.$(my_register_name).META_LIC) $(module_license_metadata))
-
-  ifdef LOCAL_SOONG_LICENSE_METADATA
-    # Soong modules have already produced a license metadata file, copy it to where Make expects it.
-    $(eval $(call copy-one-license-metadata-file, $(LOCAL_SOONG_LICENSE_METADATA), $(module_license_metadata),$(ALL_MODULES.$(my_register_name).BUILT),$(ALL_MODUES.$(my_register_name).INSTALLED)))
+  ifneq (,$(strip $(LOCAL_LICENSE_PACKAGE_NAME)))
+    license_package_name:=$(strip $(LOCAL_LICENSE_PACKAGE_NAME))
   else
-    # Make modules don't have enough information to produce a license metadata rule until after fix-notice-deps
-    # has been called, store the necessary information until later.
-    ALL_MODULES.$(my_register_name).DELAYED_META_LIC := $(strip $(ALL_MODULES.$(my_register_name).DELAYED_META_LIC) $(module_license_metadata))
-    ALL_MODULES.$(my_register_name).LICENSE_PACKAGE_NAME := $(strip $(license_package_name))
-    ALL_MODULES.$(my_register_name).MODULE_TYPE := $(strip $(ALL_MODULES.$(my_register_name).MODULE_TYPE) $(LOCAL_MODULE_TYPE))
-    ALL_MODULES.$(my_register_name).MODULE_CLASS := $(strip $(ALL_MODULES.$(my_register_name).MODULE_CLASS) $(LOCAL_MODULE_CLASS))
-    ALL_MODULES.$(my_register_name).LICENSE_KINDS := $(ALL_MODULES.$(my_register_name).LICENSE_KINDS) $(license_kinds)
-    ALL_MODULES.$(my_register_name).LICENSE_CONDITIONS := $(ALL_MODULES.$(my_register_name).LICENSE_CONDITIONS) $(license_conditions)
-    ALL_MODULES.$(my_register_name).LICENSE_INSTALL_MAP := $(ALL_MODULES.$(my_register_name).LICENSE_INSTALL_MAP) $(install_map)
-    ALL_MODULES.$(my_register_name).NOTICE_DEPS := $(ALL_MODULES.$(my_register_name).NOTICE_DEPS) $(notice_deps)
-    ALL_MODULES.$(my_register_name).IS_CONTAINER := $(strip $(filter-out false,$(ALL_MODULES.$(my_register_name).IS_CONTAINER) $(is_container)))
-    ALL_MODULES.$(my_register_name).PATH := $(strip $(ALL_MODULES.$(my_register_name).PATH) $(local_path))
+    license_package_name:=
   endif
+
+  ifneq (,$(strip $(LOCAL_LICENSE_INSTALL_MAP)))
+    install_map:=$(strip $(LOCAL_LICENSE_INSTALL_MAP))
+  else
+    install_map:=
+  endif
+
+  ifneq (,$(strip $(LOCAL_LICENSE_KINDS)))
+    license_kinds:=$(strip $(LOCAL_LICENSE_KINDS))
+  else
+    license_kinds:=legacy_by_exception_only
+  endif
+
+  ifneq (,$(strip $(LOCAL_LICENSE_CONDITIONS)))
+    license_conditions:=$(strip $(LOCAL_LICENSE_CONDITIONS))
+  else
+    license_conditions:=by_exception_only
+  endif
+
+  is_container:=$(strip $(LOCAL_MODULE_IS_CONTAINER))
+  ifeq (,$(is_container))
+    ifneq (,$(strip $(filter %.zip %.tar %.tgz %.tar.gz %.apk %.img %.srcszip %.apex, $(LOCAL_BUILT_MODULE))))
+      is_container:=true
+    else
+      is_container:=false
+    endif
+  else ifneq (,$(strip $(filter-out true false,$(is_container))))
+    $(error Unrecognized value '$(is_container)' for LOCAL_MODULE_IS_CONTAINER)
+  endif
+
+  ifeq (true,$(is_container))
+    # Include shared libraries' notices for "container" types, but not for binaries etc.
+    notice_deps := \
+        $(strip \
+            $(foreach d, \
+                $(LOCAL_REQUIRED_MODULES) \
+                $(LOCAL_STATIC_LIBRARIES) \
+                $(LOCAL_WHOLE_STATIC_LIBRARIES) \
+                $(LOCAL_SHARED_LIBRARIES) \
+                $(LOCAL_DYLIB_LIBRARIES) \
+                $(LOCAL_RLIB_LIBRARIES) \
+                $(LOCAL_PROC_MACRO_LIBRARIES) \
+                $(LOCAL_HEADER_LIBRARIES) \
+                $(LOCAL_STATIC_JAVA_LIBRARIES) \
+                $(LOCAL_JAVA_LIBRARIES) \
+                $(LOCAL_JNI_SHARED_LIBRARIES) \
+                ,$(subst :,_,$(d)):static \
+            ) \
+        )
+  else
+    notice_deps := \
+        $(strip \
+            $(foreach d, \
+                $(LOCAL_REQUIRED_MODULES) \
+                $(LOCAL_STATIC_LIBRARIES) \
+                $(LOCAL_WHOLE_STATIC_LIBRARIES) \
+                $(LOCAL_RLIB_LIBRARIES) \
+                $(LOCAL_PROC_MACRO_LIBRARIES) \
+                $(LOCAL_HEADER_LIBRARIES) \
+                $(LOCAL_STATIC_JAVA_LIBRARIES) \
+                ,$(subst :,_,$(d)):static \
+            )$(foreach d, \
+                $(LOCAL_SHARED_LIBRARIES) \
+                $(LOCAL_DYLIB_LIBRARIES) \
+                $(LOCAL_JAVA_LIBRARIES) \
+                $(LOCAL_JNI_SHARED_LIBRARIES) \
+                ,$(subst :,_,$(d)):dynamic \
+            ) \
+        )
+  endif
+  ifeq ($(LOCAL_IS_HOST_MODULE),true)
+    notice_deps := $(strip $(notice_deps) $(foreach d,$(LOCAL_HOST_REQUIRED_MODULES),$(subst :,_,$(d)):static))
+  else
+    notice_deps := $(strip $(notice_deps) $(foreach d,$(LOCAL_TARGET_REQUIRED_MODULES),$(subst :,_,$(d)):static))
+  endif
+
+  ALL_MODULES.$(my_register_name).DELAYED_META_LIC := $(strip $(ALL_MODULES.$(my_register_name).DELAYED_META_LIC) $(module_license_metadata))
+  ALL_MODULES.$(my_register_name).LICENSE_PACKAGE_NAME := $(strip $(license_package_name))
+  ALL_MODULES.$(my_register_name).MODULE_TYPE := $(strip $(ALL_MODULES.$(my_register_name).MODULE_TYPE) $(LOCAL_MODULE_TYPE))
+  ALL_MODULES.$(my_register_name).MODULE_CLASS := $(strip $(ALL_MODULES.$(my_register_name).MODULE_CLASS) $(LOCAL_MODULE_CLASS))
+  ALL_MODULES.$(my_register_name).LICENSE_KINDS := $(ALL_MODULES.$(my_register_name).LICENSE_KINDS) $(license_kinds)
+  ALL_MODULES.$(my_register_name).LICENSE_CONDITIONS := $(ALL_MODULES.$(my_register_name).LICENSE_CONDITIONS) $(license_conditions)
+  ALL_MODULES.$(my_register_name).LICENSE_INSTALL_MAP := $(ALL_MODULES.$(my_register_name).LICENSE_INSTALL_MAP) $(install_map)
+  ALL_MODULES.$(my_register_name).NOTICE_DEPS := $(ALL_MODULES.$(my_register_name).NOTICE_DEPS) $(notice_deps)
+  ALL_MODULES.$(my_register_name).IS_CONTAINER := $(strip $(filter-out false,$(ALL_MODULES.$(my_register_name).IS_CONTAINER) $(is_container)))
+  ALL_MODULES.$(my_register_name).PATH := $(strip $(ALL_MODULES.$(my_register_name).PATH) $(local_path))
 endif
 
 ifdef notice_file
-
-ifdef my_register_name
 ALL_MODULES.$(my_register_name).NOTICES := $(ALL_MODULES.$(my_register_name).NOTICES) $(notice_file)
-endif
-
 endif  # notice_file
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 ca65948..be5ec47 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -443,10 +443,19 @@
 # If set, determines whether the build system checks vendor seapp contexts violations.
 _product_single_value_vars += PRODUCT_CHECK_VENDOR_SEAPP_VIOLATIONS
 
+# If set, determines whether the build system checks dev type violations.
+_product_single_value_vars += PRODUCT_CHECK_DEV_TYPE_VIOLATIONS
+
 _product_list_vars += PRODUCT_AFDO_PROFILES
 
 _product_single_value_vars += PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API
 
+_product_list_vars += PRODUCT_RELEASE_CONFIG_MAPS
+
+_product_list_vars += PRODUCT_VALIDATION_CHECKS
+
+_product_single_value_vars += PRODUCT_BUILD_FROM_SOURCE_STUB
+
 .KATI_READONLY := _product_single_value_vars _product_list_vars
 _product_var_list :=$= $(_product_single_value_vars) $(_product_list_vars)
 
@@ -544,7 +553,7 @@
 # be cleaned up to not be product variables.
 _readonly_late_variables := \
   DEVICE_PACKAGE_OVERLAYS \
-  WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY \
+  WITH_DEXPREOPT_ART_BOOT_IMG_ONLY \
 
 # Modified internally in the build system
 _readonly_late_variables += \
diff --git a/core/product_config.mk b/core/product_config.mk
index b475d75..500735e 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -420,6 +420,8 @@
 PRODUCT_EXTRA_OTA_KEYS := $(sort $(PRODUCT_EXTRA_OTA_KEYS))
 PRODUCT_EXTRA_RECOVERY_KEYS := $(sort $(PRODUCT_EXTRA_RECOVERY_KEYS))
 
+PRODUCT_VALIDATION_CHECKS := $(sort $(PRODUCT_VALIDATION_CHECKS))
+
 # Resolve and setup per-module dex-preopt configs.
 DEXPREOPT_DISABLED_MODULES :=
 # If a module has multiple setups, the first takes precedence.
@@ -498,18 +500,6 @@
   endif
 endif
 
-ifdef PRODUCT_SHIPPING_API_LEVEL
-  ifneq (,$(call math_gt_or_eq,29,$(PRODUCT_SHIPPING_API_LEVEL)))
-    PRODUCT_PACKAGES += $(PRODUCT_PACKAGES_SHIPPING_API_LEVEL_29)
-  endif
-  ifneq (,$(call math_gt_or_eq,33,$(PRODUCT_SHIPPING_API_LEVEL)))
-    PRODUCT_PACKAGES += $(PRODUCT_PACKAGES_SHIPPING_API_LEVEL_33)
-  endif
-  ifneq (,$(call math_gt_or_eq,34,$(PRODUCT_SHIPPING_API_LEVEL)))
-    PRODUCT_PACKAGES += $(PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34)
-  endif
-endif
-
 # If build command defines OVERRIDE_PRODUCT_EXTRA_VNDK_VERSIONS,
 # override PRODUCT_EXTRA_VNDK_VERSIONS with it.
 ifdef OVERRIDE_PRODUCT_EXTRA_VNDK_VERSIONS
@@ -588,6 +578,15 @@
 endif
 .KATI_READONLY := CHECK_VENDOR_SEAPP_VIOLATIONS
 
+# Boolean variable determining if selinux labels of /dev are enforced
+CHECK_DEV_TYPE_VIOLATIONS := false
+ifneq ($(call math_gt,$(VSR_VENDOR_API_LEVEL),35),)
+  CHECK_DEV_TYPE_VIOLATIONS := true
+else ifneq ($(PRODUCT_CHECK_DEV_TYPE_VIOLATIONS),)
+  CHECK_DEV_TYPE_VIOLATIONS := $(PRODUCT_CHECK_DEV_TYPE_VIOLATIONS)
+endif
+.KATI_READONLY := CHECK_DEV_TYPE_VIOLATIONS
+
 define product-overrides-config
 $$(foreach rule,$$(PRODUCT_$(1)_OVERRIDES),\
     $$(if $$(filter 2,$$(words $$(subst :,$$(space),$$(rule)))),,\
diff --git a/core/product_validation_checks.mk b/core/product_validation_checks.mk
new file mode 100644
index 0000000..e0d976f
--- /dev/null
+++ b/core/product_validation_checks.mk
@@ -0,0 +1,72 @@
+# PRODUCT_VALIDATION_CHECKS allows you to enforce that your product config variables follow some
+# rules. To use it, add the paths to starlark configuration language (scl) files in
+# PRODUCT_VALIDATION_CHECKS. A validate_product_variables function in those files will be called
+# with a single "context" object.
+#
+# The context object currently 2 attributes:
+#   - product_variables: This has all the product variables. All the variables are either of type
+#                        string or list, more accurate typing (like bool) isn't known.
+#   - board_variables: This only has a small subset of the board variables, because there isn't a
+#                      known list of board variables. Feel free to expand the subset if you need a
+#                      new variable.
+#
+# You can then inspect (but not modify) these variables and fail() if they don't meet your
+# requirements. Example:
+#
+# In a product config file: PRODUCT_VALIDATION_CHECKS += //path/to/my_validations.scl
+# In my_validations.scl:
+# def validate_product_variables(ctx):
+#     for dir in ctx.board_variables.BOARD_SEPOLICY_DIRS:
+#         if not dir.startswith('system/sepolicy/'):
+#             fail('Only sepolicies in system/seplicy are allowed, found: ' + dir)
+
+ifdef PRODUCT_VALIDATION_CHECKS
+
+$(if $(filter-out //%.scl,$(PRODUCT_VALIDATION_CHECKS)), \
+	$(error All PRODUCT_VALIDATION_CHECKS files must start with // and end with .scl, exceptions: $(filter-out //%.scl,$(PRODUCT_VALIDATION_CHECKS))))
+
+known_board_variables := \
+  BOARD_VENDOR_SEPOLICY_DIRS BOARD_SEPOLICY_DIRS \
+  SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS \
+  SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS \
+  PRODUCT_PUBLIC_SEPOLICY_DIRS \
+  PRODUCT_PRIVATE_SEPOLICY_DIRS
+
+known_board_list_variables := \
+  BOARD_VENDOR_SEPOLICY_DIRS BOARD_SEPOLICY_DIRS \
+  SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS \
+  SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS \
+  PRODUCT_PUBLIC_SEPOLICY_DIRS \
+  PRODUCT_PRIVATE_SEPOLICY_DIRS
+
+escape_starlark_string=$(subst ",\",$(subst \,\\,$(1)))
+product_variable_starlark_value=$(if $(filter $(1),$(_product_list_vars) $(known_board_list_variables)),[$(foreach w,$($(1)),"$(call escape_starlark_string,$(w))", )],"$(call escape_starlark_string,$(1))")
+filename_to_starlark=$(subst -,_,$(subst /,_,$(subst .,_,$(1))))
+_c:=$(foreach f,$(PRODUCT_VALIDATION_CHECKS),$(newline)load("$(f)", validate_product_variables_$(call filename_to_starlark,$(f)) = "validate_product_variables"))
+# TODO: we should freeze the context because it contains mutable lists, so that validation checks can't affect each other
+_c+=$(newline)_ctx = struct(
+_c+=$(newline)product_variables = struct(
+_c+=$(foreach v,$(_product_var_list),$(newline)  $(v) = $(call product_variable_starlark_value,$(v)),)
+_c+=$(newline)),
+_c+=$(newline)board_variables = struct(
+_c+=$(foreach v,$(known_board_variables),$(newline)  $(v) = $(call product_variable_starlark_value,$(v)),)
+_c+=$(newline))
+_c+=$(newline))
+_c+=$(foreach f,$(PRODUCT_VALIDATION_CHECKS),$(newline)validate_product_variables_$(call filename_to_starlark,$(f))(_ctx))
+_c+=$(newline)variables_to_export_to_make = {}
+$(KATI_file_no_rerun >$(OUT_DIR)/product_validation_checks_entrypoint.scl,$(_c))
+filename_to_starlark:=
+escape_starlark_string:=
+product_variable_starlark_value:=
+known_board_variables :=
+known_board_list_variables :=
+
+# Exclude the entrypoint file as a dependency (by passing it as the 2nd argument) so that we don't
+# rerun kati every build. Even though we're using KATI_file_no_rerun, product config is run every
+# build, so the file will still be rewritten.
+#
+# We also need to pass --allow_external_entrypoint to rbcrun in case the OUT_DIR is set to something
+# outside of the source tree.
+$(call run-starlark,$(OUT_DIR)/product_validation_checks_entrypoint.scl,$(OUT_DIR)/product_validation_checks_entrypoint.scl,--allow_external_entrypoint)
+
+endif # ifdef PRODUCT_VALIDATION_CHECKS
diff --git a/core/proguard.flags b/core/proguard.flags
index 6dbee84..9cbba0f 100644
--- a/core/proguard.flags
+++ b/core/proguard.flags
@@ -61,3 +61,4 @@
 }
 
 -include proguard_basic_keeps.flags
+-include proguard/kotlin.flags
diff --git a/core/proguard/kotlin.flags b/core/proguard/kotlin.flags
new file mode 100644
index 0000000..70dbaa7
--- /dev/null
+++ b/core/proguard/kotlin.flags
@@ -0,0 +1,19 @@
+# Ignore missing Kotlin meta-annotations so that Java-only projects can depend
+# on projects that happen to be written in Kotlin but do not have a run-time
+# dependency on the Kotlin standard library. Note these annotations are RUNTIME
+# retention, but we won't need them available in Java-only projects.
+-dontwarn kotlin.Metadata
+-dontwarn kotlin.annotation.AnnotationRetention
+-dontwarn kotlin.annotation.AnnotationTarget
+-dontwarn kotlin.annotation.Retention
+-dontwarn kotlin.annotation.Target
+
+# Kotlin DebugMetadata has no value in release builds, these two rules, will
+# allow AppReduce to strip out DebutMetadata.
+-checkdiscard interface kotlin.coroutines.jvm.internal.DebugMetadata
+-assumenosideeffects class kotlin.coroutines.jvm.internal.DebugMetadataKt {
+  *** getDebugMetadataAnnotation(...);
+}
+-assumevalues class kotlin.coroutines.jvm.internal.DebugMetadataKt {
+  *** getDebugMetadataAnnotation(...) return null;
+}
diff --git a/core/rbe.mk b/core/rbe.mk
index 6754b0a..0f90ddd 100644
--- a/core/rbe.mk
+++ b/core/rbe.mk
@@ -64,7 +64,7 @@
     d8_exec_strategy := remote_local_fallback
   endif
 
-  platform := container-image=docker://gcr.io/androidbuild-re-dockerimage/android-build-remoteexec-image@sha256:582efb38f0c229ea39952fff9e132ccbe183e14869b39888010dacf56b360d62
+  platform := container-image=docker://gcr.io/androidbuild-re-dockerimage/android-build-remoteexec-image@sha256:1eb7f64b9e17102b970bd7a1af7daaebdb01c3fb777715899ef462d6c6d01a45
   cxx_platform := $(platform),Pool=$(cxx_pool)
   java_r8_d8_platform := $(platform),Pool=$(java_pool)
 
diff --git a/core/release_config.mk b/core/release_config.mk
index b72ee89..1fb5747 100644
--- a/core/release_config.mk
+++ b/core/release_config.mk
@@ -52,41 +52,72 @@
         ) \
     )
 
+# 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
+# $3 overridden release config.  Only applied for $(TARGET_RELEASE), not in depth.
 define declare-release-config
     $(if $(strip $(2)),,  \
         $(error declare-release-config: config $(strip $(1)) must have release config files) \
     )
     $(eval _all_release_configs := $(sort $(_all_release_configs) $(strip $(1))))
+    $(if $(strip $(3)), \
+      $(if $(filter $(_all_release_configs), $(strip $(3))),
+        $(if $(filter $(_all_release_configs.$(strip $(1)).OVERRIDES),$(strip $(3))),,
+          $(eval _all_release_configs.$(strip $(1)).OVERRIDES := $(_all_release_configs.$(strip $(1)).OVERRIDES) $(strip $(3)))), \
+        $(error No release config $(strip $(3))) \
+      ) \
+    )
     $(eval _all_release_configs.$(strip $(1)).DECLARED_IN := $(_included) $(_all_release_configs.$(strip $(1)).DECLARED_IN))
     $(eval _all_release_configs.$(strip $(1)).FILES := $(_all_release_configs.$(strip $(1)).FILES) $(strip $(2)))
 endef
 
-# Include the config map files
+# Include the config map files and populate _flag_declaration_files.
+_flag_declaration_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 :=
 
-# If TARGET_RELEASE is set, fail if there is no matching release config
-# If it isn't set, no release config files will be included and all flags
-# will get their default values.
-ifneq ($(TARGET_RELEASE),)
+ifeq ($(TARGET_RELEASE),)
+    # We allow some internal paths to explicitly set TARGET_RELEASE to the
+    # empty string.  For the most part, 'make' treats unset and empty string as
+    # the same.  But the following line differentiates, and will only assign
+    # if the variable was completely unset.
+    TARGET_RELEASE ?= was_unset
+    ifeq ($(TARGET_RELEASE),was_unset)
+        $(error No release config set for target; please set TARGET_RELEASE, or if building on the command line use 'lunch <target>-<release>-<build_type>', where release is one of: $(_all_release_configs))
+    endif
+    # Instead of leaving this string empty, we want to default to a valid
+    # setting.  Full builds coming through this path is a bug, but in case
+    # of such a bug, we want to at least get consistent, valid results.
+    TARGET_RELEASE = trunk_staging
+endif
+
 ifeq ($(filter $(_all_release_configs), $(TARGET_RELEASE)),)
     $(error No release config found for TARGET_RELEASE: $(TARGET_RELEASE). Available releases are: $(_all_release_configs))
-else
-    # Choose flag files
-    # Don't sort this, use it in the order they gave us.
-    flag_value_files := $(_all_release_configs.$(TARGET_RELEASE).FILES)
 endif
-else
-# Useful for finding scripts etc that aren't passing or setting TARGET_RELEASE
-ifneq ($(FAIL_IF_NO_RELEASE_CONFIG),)
-    $(error FAIL_IF_NO_RELEASE_CONFIG was set and TARGET_RELEASE was not)
-endif
+
+# 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 :=
-endif
+$(foreach r,$(_all_release_configs.$(TARGET_RELEASE).OVERRIDES) $(TARGET_RELEASE), \
+    $(foreach f,$(_all_release_configs.$(r).FILES), \
+      $(if $(filter $(f),$(flag_value_files)),,$(eval flag_value_files += $(f)))\
+    )\
+)
 
 # Unset variables so they can't use them
 define declare-release-config
@@ -121,36 +152,23 @@
 # that we chose from the config map above.  Then we run that, and load the
 # results of that into the make environment.
 
-# 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) \
-        ) \
-    )
-
+# _flag_declaration_files is the combined list of FLAG_DECLARATION_FILES set by
+# release_config_map.mk files above.
 
 # 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.
 filename_to_starlark=$(subst /,_,$(subst .,_,$(1)))
-_c:=load("//build/make/core/release_config.bzl", "release_config")
+_c:=load("//build/make/core/release_config.scl", "release_config")
 _c+=$(newline)def add(d, k, v):
 _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)
-$(file >$(OUT_DIR)/release_config_entrypoint.bzl,$(_c))
+$(file >$(OUT_DIR)/release_config_entrypoint.scl,$(_c))
 _c:=
 filename_to_starlark:=
 
@@ -160,5 +178,5 @@
 #
 # We also need to pass --allow_external_entrypoint to rbcrun in case the OUT_DIR is set to something
 # outside of the source tree.
-$(call run-starlark,$(OUT_DIR)/release_config_entrypoint.bzl,$(OUT_DIR)/release_config_entrypoint.bzl,--allow_external_entrypoint)
+$(call run-starlark,$(OUT_DIR)/release_config_entrypoint.scl,$(OUT_DIR)/release_config_entrypoint.scl,--allow_external_entrypoint)
 
diff --git a/core/release_config.bzl b/core/release_config.scl
similarity index 87%
rename from core/release_config.bzl
rename to core/release_config.scl
index 0c08858..662d155 100644
--- a/core/release_config.bzl
+++ b/core/release_config.scl
@@ -15,7 +15,7 @@
 Export build flags (with values) to make.
 """
 
-load("//build/bazel/utils:schema_validation.bzl", "validate")
+load("//build/bazel/utils:schema_validation.scl", "validate")
 
 # Partitions that get build system flag summaries
 _flag_partitions = [
@@ -55,6 +55,11 @@
             },
             "declared_in": {"type": "string"},
         },
+        "optional_keys": {
+            "appends": {
+                "type": "bool",
+            },
+        },
     },
 }
 
@@ -75,13 +80,14 @@
     },
 }
 
-def flag(name, partitions, default):
+def flag(name, partitions, default, *, appends = False):
     """Declare a flag.
 
     Args:
       name: name of the flag
       partitions: the partitions where this should be recorded.
       default: the default value of the flag.
+      appends: Whether new values should be append (not replace) the old.
 
     Returns:
       A dictionary containing the flag declaration.
@@ -105,6 +111,7 @@
         "name": name,
         "partitions": partitions,
         "default": default,
+        "appends": appends,
     }
 
 def value(name, value):
@@ -153,10 +160,12 @@
 
     # 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 = {}
@@ -170,13 +179,21 @@
             else:
                 partitions.setdefault(partition, []).append(flag["name"])
 
-    # Validate values
-    # TODO(joeo): Disallow duplicate values after we've split AOSP and vendor flags.
+    # Generate final values.
+    # Only declared flags may have a value.
     values = {}
     for value in all_values:
-        if value["name"] not in flag_names:
-            fail(value["set_in"] + ": Value set for undeclared build flag: " + value["name"])
-        values[value["name"]] = value
+        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
 
     # Collect values
     result = {
diff --git a/core/soong_cc_rust_prebuilt.mk b/core/soong_cc_rust_prebuilt.mk
index 05b4b6b..94e1115 100644
--- a/core/soong_cc_rust_prebuilt.mk
+++ b/core/soong_cc_rust_prebuilt.mk
@@ -129,8 +129,13 @@
   ifdef LOCAL_SHARED_LIBRARIES
     my_shared_libraries := $(LOCAL_SHARED_LIBRARIES)
     ifdef LOCAL_USE_VNDK
-      my_shared_libraries := $(foreach l,$(my_shared_libraries),\
-        $(if $(SPLIT_VENDOR.SHARED_LIBRARIES.$(l)),$(l).vendor,$(l)))
+      ifdef LOCAL_USE_VNDK_PRODUCT
+        my_shared_libraries := $(foreach l,$(my_shared_libraries),\
+          $(if $(SPLIT_PRODUCT.SHARED_LIBRARIES.$(l)),$(l).product,$(l)))
+      else
+        my_shared_libraries := $(foreach l,$(my_shared_libraries),\
+          $(if $(SPLIT_VENDOR.SHARED_LIBRARIES.$(l)),$(l).vendor,$(l)))
+      endif
     endif
     $(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)DEPENDENCIES_ON_SHARED_LIBRARIES += \
       $(my_register_name):$(LOCAL_INSTALLED_MODULE):$(subst $(space),$(comma),$(my_shared_libraries))
@@ -139,8 +144,13 @@
     my_dylibs := $(LOCAL_DYLIB_LIBRARIES)
     # Treat these as shared library dependencies for installation purposes.
     ifdef LOCAL_USE_VNDK
-      my_dylibs := $(foreach l,$(my_dylibs),\
-        $(if $(SPLIT_VENDOR.SHARED_LIBRARIES.$(l)),$(l).vendor,$(l)))
+      ifdef LOCAL_USE_VNDK_PRODUCT
+        my_dylibs := $(foreach l,$(my_dylibs),\
+          $(if $(SPLIT_PRODUCT.SHARED_LIBRARIES.$(l)),$(l).product,$(l)))
+      else
+        my_dylibs := $(foreach l,$(my_dylibs),\
+          $(if $(SPLIT_VENDOR.SHARED_LIBRARIES.$(l)),$(l).vendor,$(l)))
+      endif
     endif
     $(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)DEPENDENCIES_ON_SHARED_LIBRARIES += \
       $(my_register_name):$(LOCAL_INSTALLED_MODULE):$(subst $(space),$(comma),$(my_dylibs))
@@ -251,30 +261,6 @@
 
 $(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
 
-# We don't care about installed rlib/static libraries, since the libraries have
-# already been linked into the module at that point. We do, however, care
-# about the NOTICE files for any rlib/static libraries that we use.
-# (see notice_files.mk)
-#
-# Filter out some NDK libraries that are not being exported.
-my_static_libraries := \
-    $(filter-out ndk_libc++_static ndk_libc++abi ndk_libandroid_support ndk_libunwind \
-      ndk_libc++_static.native_bridge ndk_libc++abi.native_bridge \
-      ndk_libandroid_support.native_bridge ndk_libunwind.native_bridge, \
-      $(LOCAL_STATIC_LIBRARIES))
-installed_static_library_notice_file_targets := \
-    $(foreach lib,$(my_static_libraries) $(LOCAL_WHOLE_STATIC_LIBRARIES), \
-      NOTICE-$(if $(LOCAL_IS_HOST_MODULE),HOST$(if $(my_host_cross),_CROSS,),TARGET)-STATIC_LIBRARIES-$(lib))
-installed_static_library_notice_file_targets += \
-    $(foreach lib,$(LOCAL_RLIB_LIBRARIES), \
-      NOTICE-$(if $(LOCAL_IS_HOST_MODULE),HOST$(if $(my_host_cross),_CROSS,),TARGET)-RLIB_LIBRARIES-$(lib))
-installed_static_library_notice_file_targets += \
-    $(foreach lib,$(LOCAL_PROC_MACRO_LIBRARIES), \
-      NOTICE-$(if $(LOCAL_IS_HOST_MODULE),HOST$(if $(my_host_cross),_CROSS,),TARGET)-PROC_MACRO_LIBRARIES-$(lib))
-
-$(notice_target): | $(installed_static_library_notice_file_targets)
-$(LOCAL_INSTALLED_MODULE): | $(notice_target)
-
 # Reinstall shared library dependencies of fuzz targets to /data/fuzz/ (for
 # target) or /data/ (for host).
 ifdef LOCAL_IS_FUZZ_TARGET
diff --git a/core/soong_config.mk b/core/soong_config.mk
index be6a795..30acbba 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -164,11 +164,16 @@
 $(call add_json_list, ModulesLoadedByPrivilegedModules,  $(PRODUCT_LOADED_BY_PRIVILEGED_MODULES))
 
 $(call add_json_list, BootJars,                          $(PRODUCT_BOOT_JARS))
-$(call add_json_list, ApexBootJars,                      $(PRODUCT_APEX_BOOT_JARS))
+$(call add_json_list, ApexBootJars,                      $(filter-out $(APEX_BOOT_JARS_EXCLUDED), $(PRODUCT_APEX_BOOT_JARS)))
 
 $(call add_json_bool, VndkUseCoreVariant,                $(TARGET_VNDK_USE_CORE_VARIANT))
 $(call add_json_bool, VndkSnapshotBuildArtifacts,        $(VNDK_SNAPSHOT_BUILD_ARTIFACTS))
 
+$(call add_json_map,  BuildFlags)
+$(foreach flag,$(_ALL_RELEASE_FLAGS),\
+  $(call add_json_str,$(flag),$(_ALL_RELEASE_FLAGS.$(flag).VALUE)))
+$(call end_json_map)
+
 $(call add_json_bool, DirectedVendorSnapshot,            $(DIRECTED_VENDOR_SNAPSHOT))
 $(call add_json_map,  VendorSnapshotModules)
 $(foreach module,$(VENDOR_SNAPSHOT_MODULES),\
@@ -381,7 +386,6 @@
   $(call add_json_str, BoardFlashEraseBlockSize, $(BOARD_FLASH_ERASE_BLOCK_SIZE))
 
   $(call add_json_bool, BoardUsesRecoveryAsBoot, $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)))
-  $(call add_json_bool, BoardBuildGkiBootImageWithoutRamdisk, $(filter true,$(BOARD_BUILD_GKI_BOOT_IMAGE_WITHOUT_RAMDISK)))
   $(call add_json_bool, ProductUseDynamicPartitionSize, $(filter true,$(PRODUCT_USE_DYNAMIC_PARTITION_SIZE)))
   $(call add_json_bool, CopyImagesForTargetFilesZip, $(filter true,$(COPY_IMAGES_FOR_TARGET_FILES_ZIP)))
 
@@ -392,6 +396,8 @@
 
 $(call add_json_bool, NextReleaseHideFlaggedApi, $(filter true,$(PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API)))
 
+$(call add_json_bool, BuildFromSourceStub, $(findstring true,$(PRODUCT_BUILD_FROM_SOURCE_STUB) $(BUILD_FROM_SOURCE_STUB)))
+
 $(call json_end)
 
 $(file >$(SOONG_VARIABLES).tmp,$(json_contents))
diff --git a/core/tasks/ide.mk b/core/tasks/ide.mk
deleted file mode 100644
index a3aa0cd..0000000
--- a/core/tasks/ide.mk
+++ /dev/null
@@ -1,61 +0,0 @@
-#
-# Copyright (C) 2010 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.
-#
-
-define filter-ide-goals
-$(strip $(filter $(1)-%,$(MAKECMDGOALS)))
-endef
-
-define filter-ide-modules
-$(strip $(subst -,$(space),$(patsubst $(1)-%,%,$(2))))
-endef
-
-# eclipse
-eclipse_project_goals := $(call filter-ide-goals,ECLIPSE)
-ifdef eclipse_project_goals
-  ifneq ($(words $(eclipse_project_goals)),1)
-    $(error Only one ECLIPSE- goal may be specified: $(eclipse_project_goals))
-  endif
-  eclipse_project_modules := $(call filter-ide-modules,ECLIPSE,$(eclipse_project_goals))
-
-  ifneq ($(filter lunch,$(eclipse_project_modules)),)
-    eclipse_project_modules := $(filter-out lunch,$(eclipse_project_modules))
-    installed_modules := $(foreach m,$(ALL_DEFAULT_INSTALLED_MODULES),\
-        $(INSTALLABLE_FILES.$(m).MODULE))
-    java_modules := $(foreach m,$(installed_modules),\
-        $(if $(filter JAVA_LIBRARIES APPS,$(ALL_MODULES.$(m).CLASS)),$(m),))
-    eclipse_project_modules := $(sort $(eclipse_project_modules) $(java_modules))
-  endif
-
-  source_paths := $(foreach m,$(eclipse_project_modules),$(ALL_MODULES.$(m).PATH)) \
-              $(foreach m,$(eclipse_project_modules),$(ALL_MODULES.$(m).INTERMEDIATE_SOURCE_DIR))
-  source_paths := $(sort $(source_paths))
-
-.classpath: PRIVATE_MODULES := $(eclipse_project_modules)
-.classpath: PRIVATE_DIRS := $(source_paths)
-
-# the mess below with ./src tries to guess whether the src
-$(eclipse_project_goals): .classpath
-.classpath: FORCE
-	$(hide) echo Generating .classpath for eclipse
-	$(hide) echo '<classpath>' > $@
-	$(hide) for p in $(PRIVATE_DIRS) ; do \
-		echo -n '  <classpathentry kind="src" path="' >> $@ ; \
-		( if [ -d $$p/src ] ; then echo -n $$p/src ; else echo -n $$p ; fi ) >> $@ ; \
-		echo '"/>' >> $@ ; \
-	done
-	$(hide) echo '</classpath>' >> $@
-endif
-
diff --git a/core/tasks/module-info.mk b/core/tasks/module-info.mk
index 9668b53..8e2d58e 100644
--- a/core/tasks/module-info.mk
+++ b/core/tasks/module-info.mk
@@ -18,7 +18,7 @@
 			'"auto_test_config": [$(ALL_MODULES.$(m).auto_test_config)],' \
 			'"module_name": "$(ALL_MODULES.$(m).MODULE_NAME)"$(COMMA)' \
 			'"test_config": [$(KATI_foreach_sep w,$(COMMA) ,$(strip $(ALL_MODULES.$(m).TEST_CONFIG) $(ALL_MODULES.$(m).EXTRA_TEST_CONFIGS)),"$(w)")],' \
-			'"dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_DEPS.$(m).ALL_DEPS)),"$(w)")],' \
+			'"dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).ALL_DEPS)),"$(w)")],' \
 			'"shared_libs": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).SHARED_LIBS)),"$(w)")],' \
 			'"static_libs": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).STATIC_LIBS)),"$(w)")],' \
 			'"system_shared_libs": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).SYSTEM_SHARED_LIBS)),"$(w)")],' \
diff --git a/envsetup.sh b/envsetup.sh
index 2ea5507..cc808d2 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -56,7 +56,7 @@
 Run "m help" for help with the build system itself.
 
 Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
-- lunch:      lunch <product_name>-<build_variant>
+- lunch:      lunch <product_name>-<release_type>-<build_variant>
               Selects <product_name> as the product to build, and <build_variant> as the variant to
               build, and stores those selections in the environment to be read by subsequent
               invocations of 'm' etc.
@@ -205,6 +205,7 @@
         return
     fi
         TARGET_PRODUCT=$1 \
+        TARGET_RELEASE= \
         TARGET_BUILD_VARIANT= \
         TARGET_BUILD_TYPE= \
         TARGET_BUILD_APPS= \
@@ -486,7 +487,7 @@
 
 function multitree_lunch_help()
 {
-    echo "usage: lunch PRODUCT-VARIANT" 1>&2
+    echo "usage: lunch PRODUCT-RELEASE-VARIANT" 1>&2
     echo "    Set up android build environment based on a product short name and variant" 1>&2
     echo 1>&2
     echo "lunch COMBO_FILE VARIANT" 1>&2
@@ -728,7 +729,7 @@
 {
     local uname=$(uname)
     local choices
-    choices=$(TARGET_BUILD_APPS= TARGET_PRODUCT= TARGET_BUILD_VARIANT= get_build_var COMMON_LUNCH_CHOICES 2>/dev/null)
+    choices=$(TARGET_BUILD_APPS= TARGET_PRODUCT= TARGET_RELEASE= TARGET_BUILD_VARIANT= get_build_var COMMON_LUNCH_CHOICES 2>/dev/null)
     local ret=$?
 
     echo
@@ -775,7 +776,7 @@
     else
         print_lunch_menu
         echo "Which would you like? [aosp_arm-trunk_staging-eng]"
-        echo -n "Pick from common choices above (e.g. 13) or specify your own (e.g. aosp_barbet-eng): "
+        echo -n "Pick from common choices above (e.g. 13) or specify your own (e.g. aosp_barbet-trunk_staging-eng): "
         read answer
         used_lunch_menu=1
     fi
@@ -804,26 +805,16 @@
 
     export TARGET_BUILD_APPS=
 
-    # Support either <product>-<variant> or <product>-<release>-<variant>
-    local product release_and_variant release variant
-    product=${selection%%-*} # Trim everything after first dash
-    release_and_variant=${selection#*-} # Trim everything up to first dash
-    if [ "$release_and_variant" != "$selection" ]; then
-        local first=${release_and_variant%%-*} # Trim everything after first dash
-        if [ "$first" != "$release_and_variant" ]; then
-            # There is a 2nd dash, split into release-variant
-            release=$first # Everything up to the dash
-            variant=${release_and_variant#*-} # Trim everything up to dash
-        else
-            # There is not a 2nd dash, default to variant as the second param
-            variant=$first
-        fi
-    fi
+    # This must be <product>-<release>-<variant>
+    local product release variant
+    # Split string on the '-' character.
+    IFS="-" read -r product release variant <<< "$selection"
 
-    if [ -z "$product" ]
+    if [[ -z "$product" ]] || [[ -z "$release" ]] || [[ -z "$variant" ]]
     then
         echo
         echo "Invalid lunch combo: $selection"
+        echo "Valid combos must be of the form <product>-<release>-<variant>"
         return 1
     fi
 
@@ -841,22 +832,25 @@
     fi
     export TARGET_PRODUCT=$(get_build_var TARGET_PRODUCT)
     export TARGET_BUILD_VARIANT=$(get_build_var TARGET_BUILD_VARIANT)
-    if [ -n "$release" ]; then
-      export TARGET_RELEASE=$release
-    else
-      unset TARGET_RELEASE
-    fi
+    export TARGET_RELEASE=$release
+    # Note this is the string "release", not the value of the variable.
     export TARGET_BUILD_TYPE=release
 
-    if [ $used_lunch_menu -eq 1 ]; then
-      echo
-      echo "Hint: next time you can simply run 'lunch $selection'"
-    fi
-
     [[ -n "${ANDROID_QUIET_BUILD:-}" ]] || echo
 
     set_stuff_for_environment
     [[ -n "${ANDROID_QUIET_BUILD:-}" ]] || printconfig
+
+    if [ "${TARGET_BUILD_VARIANT}" = "userdebug" ] && [[  -z "${ANDROID_QUIET_BUILD}" ]]; then
+      echo
+      echo "Want FASTER LOCAL BUILDS? Use -eng instead of -userdebug (however for" \
+        "performance benchmarking continue to use userdebug)"
+    fi
+    if [ $used_lunch_menu -eq 1 ]; then
+      echo
+      echo "Hint: next time you can simply run 'lunch $selection'"
+    fi
+
     destroy_build_var_cache
 
     if [[ -n "${CHECK_MU_CONFIG:-}" ]]; then
@@ -887,6 +881,8 @@
 {
     local showHelp="$(echo $* | xargs -n 1 echo | \grep -E '^(help)$' | xargs)"
     local arch="$(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|arm64|x86_64)$' | xargs)"
+    # TODO(b/307975293): Expand tapas to take release arguments (and update hmm() usage).
+    local release="trunk_staging"
     local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)"
     local density="$(echo $* | xargs -n 1 echo | \grep -E '^(ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi)$' | xargs)"
     local keys="$(echo $* | xargs -n 1 echo | \grep -E '^(devkeys)$' | xargs)"
@@ -902,6 +898,10 @@
         echo "tapas: Error: Multiple build archs supplied: $arch"
         return
     fi
+    if [ $(echo $release | wc -w) -gt 1 ]; then
+        echo "tapas: Error: Multiple build releases supplied: $release"
+        return
+    fi
     if [ $(echo $variant | wc -w) -gt 1 ]; then
         echo "tapas: Error: Multiple build variants supplied: $variant"
         return
@@ -936,6 +936,7 @@
     fi
 
     export TARGET_PRODUCT=$product
+    export TARGET_RELEASE=$release
     export TARGET_BUILD_VARIANT=$variant
     export TARGET_BUILD_DENSITY=$density
     export TARGET_BUILD_TYPE=release
@@ -953,6 +954,8 @@
 {
     local showHelp="$(echo $* | xargs -n 1 echo | \grep -E '^(help)$' | xargs)"
     local product="$(echo $* | xargs -n 1 echo | \grep -E '^(.*_)?(arm|x86|arm64|riscv64|x86_64|arm64only|x86_64only)$' | xargs)"
+    # TODO: Expand banchan to take release arguments (and update hmm() usage).
+    local release="trunk_staging"
     local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)"
     local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|(.*_)?(arm|x86|arm64|riscv64|x86_64))$' | xargs)"
 
@@ -967,6 +970,10 @@
         echo "banchan: Error: Multiple build archs or products supplied: $products"
         return
     fi
+    if [ $(echo $release | wc -w) -gt 1 ]; then
+        echo "banchan: Error: Multiple build releases supplied: $release"
+        return
+    fi
     if [ $(echo $variant | wc -w) -gt 1 ]; then
         echo "banchan: Error: Multiple build variants supplied: $variant"
         return
@@ -990,6 +997,7 @@
     fi
 
     export TARGET_PRODUCT=$product
+    export TARGET_RELEASE=$release
     export TARGET_BUILD_VARIANT=$variant
     export TARGET_BUILD_DENSITY=alldpi
     export TARGET_BUILD_TYPE=release
diff --git a/rbesetup.sh b/rbesetup.sh
index 8386628..0da7a57 100644
--- a/rbesetup.sh
+++ b/rbesetup.sh
@@ -34,7 +34,7 @@
 # for the build to be executed with RBE.
 function use_rbe() {
   local RBE_BINARIES_DIR="prebuilts/remoteexecution-client/latest"
-  local DOCKER_IMAGE="gcr.io/androidbuild-re-dockerimage/android-build-remoteexec-image@sha256:582efb38f0c229ea39952fff9e132ccbe183e14869b39888010dacf56b360d62"
+  local DOCKER_IMAGE="gcr.io/androidbuild-re-dockerimage/android-build-remoteexec-image@sha256:1eb7f64b9e17102b970bd7a1af7daaebdb01c3fb777715899ef462d6c6d01a45"
 
   # Do not set an invocation-ID and let reproxy auto-generate one.
   USE_RBE="true" \
diff --git a/target/board/BoardConfigEmuCommon.mk b/target/board/BoardConfigEmuCommon.mk
deleted file mode 100644
index 6ed08f0..0000000
--- a/target/board/BoardConfigEmuCommon.mk
+++ /dev/null
@@ -1,74 +0,0 @@
-# BoardConfigEmuCommon.mk
-#
-# Common compile-time definitions for emulator
-#
-
-HAVE_HTC_AUDIO_DRIVER := true
-BOARD_USES_GENERIC_AUDIO := true
-TARGET_BOOTLOADER_BOARD_NAME := goldfish_$(TARGET_ARCH)
-
-# No Kernel
-TARGET_NO_KERNEL := true
-
-# no hardware camera
-USE_CAMERA_STUB := true
-
-NUM_FRAMEBUFFER_SURFACE_BUFFERS := 3
-
-# Build OpenGLES emulation guest and host libraries
-BUILD_EMULATOR_OPENGL := true
-BUILD_QEMU_IMAGES := true
-
-# Build and enable the OpenGL ES View renderer. When running on the emulator,
-# the GLES renderer disables itself if host GL acceleration isn't available.
-USE_OPENGL_RENDERER := true
-
-# Emulator doesn't support sparse image format.
-TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
-
-# emulator is Non-A/B device
-AB_OTA_UPDATER := false
-
-# emulator needs super.img
-BOARD_BUILD_SUPER_IMAGE_BY_DEFAULT := true
-
-# 8G + 8M
-BOARD_SUPER_PARTITION_SIZE ?= 8598323200
-BOARD_SUPER_PARTITION_GROUPS := emulator_dynamic_partitions
-
-BOARD_EMULATOR_DYNAMIC_PARTITIONS_PARTITION_LIST := \
-  system \
-  system_dlkm \
-  system_ext \
-  product \
-  vendor
-
-TARGET_COPY_OUT_PRODUCT := product
-BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE := ext4
-TARGET_COPY_OUT_SYSTEM_EXT := system_ext
-BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE := ext4
-
-BOARD_USES_SYSTEM_DLKMIMAGE := true
-BOARD_SYSTEM_DLKMIMAGE_FILE_SYSTEM_TYPE := erofs
-TARGET_COPY_OUT_SYSTEM_DLKM := system_dlkm
-
-# 8G
-BOARD_EMULATOR_DYNAMIC_PARTITIONS_SIZE ?= 8589934592
-
-#vendor boot
-BOARD_INCLUDE_DTB_IN_BOOTIMG := false
-BOARD_BOOT_HEADER_VERSION := 4
-BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)
-BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE := 0x06000000
-BOARD_RAMDISK_USE_LZ4 := true
-
-# Enable chain partition for system.
-BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
-BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048
-BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
-BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
-
-BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
-BOARD_FLASH_BLOCK_SIZE := 512
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/common
diff --git a/target/board/emulator_arm64/BoardConfig.mk b/target/board/emulator_arm64/BoardConfig.mk
deleted file mode 100644
index c16e61b..0000000
--- a/target/board/emulator_arm64/BoardConfig.mk
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright (C) 2020 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.
-#
-
-# arm64 emulator specific definitions
-TARGET_ARCH := arm64
-TARGET_ARCH_VARIANT := armv8-a
-TARGET_CPU_VARIANT := generic
-TARGET_CPU_ABI := arm64-v8a
-
-ifneq ($(TARGET_BUILD_APPS)$(filter cts sdk,$(MAKECMDGOALS)),)
-# DO NOT USE
-# DO NOT USE
-#
-# This architecture / CPU variant must NOT be used for any 64 bit
-# platform builds. It is the lowest common denominator required
-# to build an unbundled application or cts for all supported 32 and 64 bit
-# platforms.
-#
-# If you're building a 64 bit platform (and not an application) the
-# ARM-v8 specification allows you to assume all the features available in an
-# armv7-a-neon CPU. You should set the following as 2nd arch/cpu variant:
-#
-# TARGET_2ND_ARCH_VARIANT := armv8-a
-# TARGET_2ND_CPU_VARIANT := generic
-#
-# DO NOT USE
-# DO NOT USE
-TARGET_2ND_ARCH_VARIANT := armv7-a-neon
-# DO NOT USE
-# DO NOT USE
-TARGET_2ND_CPU_VARIANT := generic
-# DO NOT USE
-# DO NOT USE
-else
-TARGET_2ND_ARCH_VARIANT := armv8-a
-TARGET_2ND_CPU_VARIANT := generic
-endif
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-include build/make/target/board/BoardConfigEmuCommon.mk
-
-BOARD_BOOTIMAGE_PARTITION_SIZE := 0x02000000
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
-
-# Wifi.
-BOARD_WLAN_DEVICE           := emulator
-BOARD_HOSTAPD_DRIVER        := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB   := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION      := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM   := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA     := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP      := "/dev/null"
diff --git a/target/board/emulator_arm64/device.mk b/target/board/emulator_arm64/device.mk
deleted file mode 100644
index d221e64..0000000
--- a/target/board/emulator_arm64/device.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright (C) 2020 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.
-#
-
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
-
diff --git a/target/board/emulator_arm64/system_ext.prop b/target/board/emulator_arm64/system_ext.prop
deleted file mode 100644
index 2f8f803..0000000
--- a/target/board/emulator_arm64/system_ext.prop
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# system.prop for emulator arm64 sdk
-#
-
-rild.libpath=/vendor/lib64/libreference-ril.so
diff --git a/target/board/emulator_x86_64/BoardConfig.mk b/target/board/emulator_x86_64/BoardConfig.mk
deleted file mode 100755
index b9cbd8a..0000000
--- a/target/board/emulator_x86_64/BoardConfig.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (C) 2020 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.
-#
-
-# x86_64 emulator specific definitions
-TARGET_CPU_ABI := x86_64
-TARGET_ARCH := x86_64
-TARGET_ARCH_VARIANT := x86_64
-
-TARGET_2ND_CPU_ABI := x86
-TARGET_2ND_ARCH := x86
-TARGET_2ND_ARCH_VARIANT := x86_64
-
-TARGET_PRELINK_MODULE := false
-include build/make/target/board/BoardConfigGsiCommon.mk
-include build/make/target/board/BoardConfigEmuCommon.mk
-
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86
-
-# Wifi.
-BOARD_WLAN_DEVICE           := emulator
-BOARD_HOSTAPD_DRIVER        := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB   := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION      := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM   := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA     := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP      := "/dev/null"
diff --git a/target/board/emulator_x86_64/device.mk b/target/board/emulator_x86_64/device.mk
deleted file mode 100755
index 8a9d8da..0000000
--- a/target/board/emulator_x86_64/device.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2020 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.
-#
-
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
-
-ifdef NET_ETH0_STARTONBOOT
-  PRODUCT_VENDOR_PROPERTIES += net.eth0.startonboot=1
-endif
-
-# Ensure we package the BIOS files too.
-PRODUCT_HOST_PACKAGES += \
-	bios.bin \
-	vgabios-cirrus.bin \
diff --git a/target/board/emulator_x86_64/system_ext.prop b/target/board/emulator_x86_64/system_ext.prop
deleted file mode 100644
index ed9d173..0000000
--- a/target/board/emulator_x86_64/system_ext.prop
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# system.prop for generic sdk
-#
-
-rild.libpath=/vendor/lib64/libreference-ril.so
diff --git a/target/board/emulator_x86_64_arm64/BoardConfig.mk b/target/board/emulator_x86_64_arm64/BoardConfig.mk
deleted file mode 100755
index 26b61a6..0000000
--- a/target/board/emulator_x86_64_arm64/BoardConfig.mk
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright (C) 2020 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.
-#
-
-# x86_64 emulator specific definitions
-TARGET_CPU_ABI := x86_64
-TARGET_ARCH := x86_64
-TARGET_ARCH_VARIANT := x86_64
-
-TARGET_2ND_CPU_ABI := x86
-TARGET_2ND_ARCH := x86
-TARGET_2ND_ARCH_VARIANT := x86_64
-
-TARGET_NATIVE_BRIDGE_ARCH := arm64
-TARGET_NATIVE_BRIDGE_ARCH_VARIANT := armv8-a
-TARGET_NATIVE_BRIDGE_CPU_VARIANT := generic
-TARGET_NATIVE_BRIDGE_ABI := arm64-v8a
-
-TARGET_NATIVE_BRIDGE_2ND_ARCH := arm
-TARGET_NATIVE_BRIDGE_2ND_ARCH_VARIANT := armv7-a-neon
-TARGET_NATIVE_BRIDGE_2ND_CPU_VARIANT := generic
-TARGET_NATIVE_BRIDGE_2ND_ABI := armeabi-v7a armeabi
-
-BUILD_BROKEN_DUP_RULES := true
-
-TARGET_PRELINK_MODULE := false
-
-include build/make/target/board/BoardConfigMainlineCommon.mk
-include build/make/target/board/BoardConfigEmuCommon.mk
-
-# the settings differ from BoardConfigMainlineCommon.mk
-BOARD_USES_SYSTEM_OTHER_ODEX :=
-
-# Resize to 4G to accommodate ASAN and CTS
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86
-
-# Wifi.
-BOARD_WLAN_DEVICE           := emulator
-BOARD_HOSTAPD_DRIVER        := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB   := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION      := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM   := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA     := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP      := "/dev/null"
diff --git a/target/board/emulator_x86_64_arm64/device.mk b/target/board/emulator_x86_64_arm64/device.mk
deleted file mode 100755
index af023eb..0000000
--- a/target/board/emulator_x86_64_arm64/device.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (C) 2020 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.
-#
-
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
diff --git a/target/board/emulator_x86_64_arm64/system_ext.prop b/target/board/emulator_x86_64_arm64/system_ext.prop
deleted file mode 100644
index ed9d173..0000000
--- a/target/board/emulator_x86_64_arm64/system_ext.prop
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# system.prop for generic sdk
-#
-
-rild.libpath=/vendor/lib64/libreference-ril.so
diff --git a/target/board/emulator_x86_arm/BoardConfig.mk b/target/board/emulator_x86_arm/BoardConfig.mk
deleted file mode 100644
index 21fdbc8..0000000
--- a/target/board/emulator_x86_arm/BoardConfig.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (C) 2020 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.
-#
-
-# x86 emulator specific definitions
-TARGET_CPU_ABI := x86
-TARGET_ARCH := x86
-TARGET_ARCH_VARIANT := x86
-
-TARGET_NATIVE_BRIDGE_ARCH := arm
-TARGET_NATIVE_BRIDGE_ARCH_VARIANT := armv7-a-neon
-TARGET_NATIVE_BRIDGE_CPU_VARIANT := generic
-TARGET_NATIVE_BRIDGE_ABI := armeabi-v7a armeabi
-
-BUILD_BROKEN_DUP_RULES := true
-
-#
-# The inclusion order below is important.
-# The settings in latter makefiles overwrite those in the former.
-#
-include build/make/target/board/BoardConfigMainlineCommon.mk
-include build/make/target/board/BoardConfigEmuCommon.mk
-
-# the settings differ from BoardConfigMainlineCommon.mk
-BOARD_USES_SYSTEM_OTHER_ODEX :=
-
-# Resize to 4G to accommodate ASAN and CTS
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86
-
-# Wifi.
-BOARD_WLAN_DEVICE           := emulator
-BOARD_HOSTAPD_DRIVER        := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB   := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION      := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM   := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA     := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP      := "/dev/null"
diff --git a/target/board/emulator_x86_arm/device.mk b/target/board/emulator_x86_arm/device.mk
deleted file mode 100644
index af023eb..0000000
--- a/target/board/emulator_x86_arm/device.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (C) 2020 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.
-#
-
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
diff --git a/target/board/emulator_x86_arm/system_ext.prop b/target/board/emulator_x86_arm/system_ext.prop
deleted file mode 100644
index 64829f3..0000000
--- a/target/board/emulator_x86_arm/system_ext.prop
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# system.prop for generic sdk
-#
-
-rild.libpath=/vendor/lib/libreference-ril.so
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index 18b36aa..76b1c58 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -67,8 +67,6 @@
     $(LOCAL_DIR)/mainline_system_x86_arm.mk \
     $(LOCAL_DIR)/ndk.mk \
     $(LOCAL_DIR)/sdk.mk \
-    $(LOCAL_DIR)/sdk_phone_arm64.mk \
-    $(LOCAL_DIR)/sdk_phone_x86_64.mk \
 
 endif
 
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..f31749b 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -21,7 +21,6 @@
     am \
     android.hidl.base-V1.0-java \
     android.hidl.manager-V1.0-java \
-    android.hidl.memory@1.0-impl \
     android.system.suspend-service \
     android.test.base \
     android.test.mock \
@@ -53,7 +52,6 @@
     com.android.btservices \
     com.android.configinfrastructure \
     com.android.conscrypt \
-    com.android.crashrecovery \
     com.android.devicelock \
     com.android.extservices \
     com.android.healthfitness \
@@ -312,13 +310,17 @@
     system_manifest.xml \
     system_compatibility_matrix.xml \
 
-HIDL_SUPPORT_SERVICES := \
-    hwservicemanager \
-    android.hidl.allocator@1.0-service \
-
 # Base modules when shipping api level is less than or equal to 34
 PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34 += \
-    $(HIDL_SUPPORT_SERVICES) \
+    android.hidl.memory@1.0-impl \
+
+# hwservicemanager is now installed on system_ext, but apexes might be using
+# old libraries that are expecting it to be installed on system. This allows
+# those apexes to continue working. The symlink can be removed once we are sure
+# there are no devices using hwservicemanager (when Android V launching devices
+# are no longer supported for dessert upgrades).
+PRODUCT_PACKAGES += \
+    hwservicemanager_compat_symlink_module \
 
 PRODUCT_PACKAGES_ARM64 := libclang_rt.hwasan \
  libclang_rt.hwasan.bootstrap \
@@ -346,6 +348,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
@@ -415,6 +426,7 @@
     libclang_rt.ubsan_standalone \
     logpersist.start \
     logtagd.rc \
+    ot-cli-ftd \
     procrank \
     profcollectd \
     profcollectctl \
diff --git a/target/product/base_system_ext.mk b/target/product/base_system_ext.mk
index 852d7ca..d8c1863 100644
--- a/target/product/base_system_ext.mk
+++ b/target/product/base_system_ext.mk
@@ -22,3 +22,8 @@
     passwd_system_ext \
     selinux_policy_system_ext \
     system_ext_manifest.xml \
+
+# Base modules when shipping api level is less than or equal to 34
+PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34 += \
+    hwservicemanager \
+    android.hidl.allocator@1.0-service \
diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk
index 8d5b7bf..a0c5929 100644
--- a/target/product/base_vendor.mk
+++ b/target/product/base_vendor.mk
@@ -46,7 +46,6 @@
 
 # Base modules and settings for the vendor partition.
 PRODUCT_PACKAGES += \
-    android.hidl.memory@1.0-impl.vendor \
     com.android.hardware.cas \
     boringssl_self_test_vendor \
     dumpsys_vendor \
@@ -75,6 +74,10 @@
     selinux_policy_nonsystem \
     shell_and_utilities_vendor \
 
+# Base modules when shipping api level is less than or equal to 34
+PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34 += \
+     android.hidl.memory@1.0-impl.vendor \
+
 # OMX not supported for 64bit_only builds
 # Only supported when SHIPPING_API_LEVEL is less than or equal to 33
 ifneq ($(TARGET_SUPPORTS_OMX_SERVICE),false)
diff --git a/target/product/default_art_config.mk b/target/product/default_art_config.mk
index f7c92aa..b02a583 100644
--- a/target/product/default_art_config.mk
+++ b/target/product/default_art_config.mk
@@ -56,6 +56,8 @@
     ims-common
 
 # APEX boot jars. Keep the list sorted by module names and then library names.
+# Note: If the existing apex introduces the new jar, also add it to
+# PRODUCT_APEX_BOOT_JARS_FOR_SOURCE_BUILD_ONLY below.
 # Note: core-icu4j is moved back to PRODUCT_BOOT_JARS in product_config.mk at a later stage.
 # Note: For modules available in Q, DO NOT add new entries here.
 PRODUCT_APEX_BOOT_JARS := \
@@ -65,13 +67,13 @@
     com.android.btservices:framework-bluetooth \
     com.android.configinfrastructure:framework-configinfrastructure \
     com.android.conscrypt:conscrypt \
-    com.android.crashrecovery:framework-crashrecovery \
     com.android.devicelock:framework-devicelock \
     com.android.healthfitness:framework-healthfitness \
     com.android.i18n:core-icu4j \
     com.android.ipsec:android.net.ipsec.ike \
     com.android.media:updatable-media \
     com.android.mediaprovider:framework-mediaprovider \
+    com.android.mediaprovider:framework-pdf \
     com.android.ondevicepersonalization:framework-ondevicepersonalization \
     com.android.os.statsd:framework-statsd \
     com.android.permission:framework-permission \
@@ -85,6 +87,12 @@
     com.android.virt:framework-virtualization \
     com.android.wifi:framework-wifi \
 
+# TODO(b/308174306): Adjust this after multiple prebuilts version is supported.
+# APEX boot jars that are not in prebuilt apexes.
+# Keep the list sorted by module names and then library names.
+PRODUCT_APEX_BOOT_JARS_FOR_SOURCE_BUILD_ONLY := \
+    com.android.mediaprovider:framework-pdf \
+
 # List of system_server classpath jars delivered via apex.
 # Keep the list sorted by module names and then library names.
 # Note: For modules available in Q, DO NOT add new entries here.
@@ -94,7 +102,6 @@
     com.android.appsearch:service-appsearch \
     com.android.art:service-art \
     com.android.configinfrastructure:service-configinfrastructure \
-    com.android.crashrecovery:service-crashrecovery \
     com.android.healthfitness:service-healthfitness \
     com.android.media:service-media-s \
     com.android.ondevicepersonalization:service-ondevicepersonalization \
diff --git a/target/product/emulator_system.mk b/target/product/emulator_system.mk
deleted file mode 100644
index b7e7cfa..0000000
--- a/target/product/emulator_system.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2019 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.
-#
-# This file lists emulator experimental modules added to PRODUCT_PACKAGES,
-# only included by targets sdk_phone_x86/64 and sdk_gphone_x86/64
-
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST := \
-    system/lib/libemulator_multidisplay_jni.so \
-    system/lib64/libemulator_multidisplay_jni.so \
-    system/priv-app/MultiDisplayProvider/MultiDisplayProvider.apk \
-
-PRODUCT_PACKAGES += MultiDisplayProvider
diff --git a/target/product/emulator_vendor.mk b/target/product/emulator_vendor.mk
deleted file mode 100644
index f71b275..0000000
--- a/target/product/emulator_vendor.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# Copyright (C) 2012 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.
-
-#
-# This file is included by other product makefiles to add all the
-# emulator-related modules to PRODUCT_PACKAGES.
-#
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_vendor.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_vendor.mk)
-
-# need this for gles libraries to load properly
-# after moving to /vendor/lib/
-PRODUCT_PACKAGES += \
-    vndk-sp
-
-DEVICE_PACKAGE_OVERLAYS := device/generic/goldfish/overlay
-
-PRODUCT_CHARACTERISTICS := emulator
-
-PRODUCT_FULL_TREBLE_OVERRIDE := true
-
-# goldfish vendor partition configurations
-$(call inherit-product-if-exists, device/generic/goldfish/vendor.mk)
-
-#watchdog tiggers reboot because location service is not
-#responding, disble it for now.
-#still keep it on internal main (master) as it is still working
-#once it is fixed in aosp, remove this block of comment.
-#PRODUCT_VENDOR_PROPERTIES += \
-#config.disable_location=true
-
-# enable Google-specific location features,
-# like NetworkLocationProvider and LocationCollector
-PRODUCT_SYSTEM_EXT_PROPERTIES += \
-    ro.com.google.locationfeatures=1
-
-# disable setupwizard
-PRODUCT_SYSTEM_EXT_PROPERTIES += \
-    ro.setupwizard.mode?=DISABLED
diff --git a/target/product/generic_system.mk b/target/product/generic_system.mk
index 6d40436..38efde4 100644
--- a/target/product/generic_system.mk
+++ b/target/product/generic_system.mk
@@ -128,10 +128,6 @@
 
 _base_mk_allowed_list :=
 
-# TODO(b/299166571) Remove this after the artifact path requirements checker picks up
-# hwservicemanager correctly.
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += $(TARGET_COPY_OUT_SYSTEM)/bin/hwservicemanager
-
 _my_allowed_list := $(_base_mk_allowed_list)
 
 # For mainline, system.img should be mounted at /, so we include ROOT here.
diff --git a/target/product/gsi/Android.mk b/target/product/gsi/Android.mk
index fa3d1da..007aabd 100644
--- a/target/product/gsi/Android.mk
+++ b/target/product/gsi/Android.mk
@@ -7,7 +7,7 @@
 #####################################################################
 # This is the up-to-date list of vndk libs.
 LATEST_VNDK_LIB_LIST := $(LOCAL_PATH)/current.txt
-UNFROZEN_VNDK :=
+UNFROZEN_VNDK := true
 ifeq (REL,$(PLATFORM_VERSION_CODENAME))
     # Use frozen vndk lib list only if "34 >= PLATFORM_VNDK_VERSION"
     ifeq ($(call math_gt_or_eq,34,$(PLATFORM_VNDK_VERSION)),true)
@@ -15,8 +15,7 @@
         ifeq ($(wildcard $(LATEST_VNDK_LIB_LIST)),)
             $(error $(LATEST_VNDK_LIB_LIST) file not found. Please copy "$(LOCAL_PATH)/current.txt" to "$(LATEST_VNDK_LIB_LIST)" and commit a CL for release branch)
         endif
-    else
-        UNFROZEN_VNDK := true
+        UNFROZEN_VNDK :=
     endif
 endif
 
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index 9ff886e..53c9e0c 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -34,7 +34,6 @@
 VNDK-SP: android.hardware.graphics.mapper@4.0.so
 VNDK-SP: android.hardware.renderscript@1.0.so
 VNDK-SP: android.hidl.memory.token@1.0.so
-VNDK-SP: android.hidl.memory@1.0-impl.so
 VNDK-SP: android.hidl.memory@1.0.so
 VNDK-SP: android.hidl.safe_union@1.0.so
 VNDK-SP: libRSCpuRef.so
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index 23eb534..fc5db6a 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -62,13 +62,16 @@
 PRODUCT_COPY_FILES += \
     device/generic/common/overlays/overlay-config.xml:$(TARGET_COPY_OUT_SYSTEM_EXT)/overlay/config/config.xml
 
+# b/308878144 no more VNDK on 24Q1 and beyond
+KEEP_VNDK ?= false
+
 # Support additional VNDK snapshots
 PRODUCT_EXTRA_VNDK_VERSIONS := \
-    29 \
     30 \
     31 \
     32 \
     33 \
+    34 \
 
 # Do not build non-GSI partition images.
 PRODUCT_BUILD_CACHE_IMAGE := false
diff --git a/target/product/handheld_system.mk b/target/product/handheld_system.mk
index 00b62bc..6c93dd7 100644
--- a/target/product/handheld_system.mk
+++ b/target/product/handheld_system.mk
@@ -40,7 +40,6 @@
     BuiltInPrintService \
     CalendarProvider \
     cameraserver \
-    com.android.nfcservices \
     CameraExtensionsProxy \
     CaptivePortalLogin \
     CertInstaller \
@@ -57,6 +56,7 @@
     MmsService \
     MtpService \
     MusicFX \
+    NfcNci \
     PacProcessor \
     preinstalled-packages-platform-handheld-system.xml \
     PrintRecommendationService \
diff --git a/target/product/handheld_system_ext.mk b/target/product/handheld_system_ext.mk
index 187b627..1218f7a 100644
--- a/target/product/handheld_system_ext.mk
+++ b/target/product/handheld_system_ext.mk
@@ -29,3 +29,8 @@
     StorageManager \
     SystemUI \
     WallpaperCropper \
+
+# Base modules when shipping api level is less than or equal to 34
+PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34 += \
+    hwservicemanager \
+    android.hidl.allocator@1.0-service \
diff --git a/target/product/mainline_sdk.mk b/target/product/mainline_sdk.mk
index 0ea72cc..cb23bc8 100644
--- a/target/product/mainline_sdk.mk
+++ b/target/product/mainline_sdk.mk
@@ -18,3 +18,5 @@
 PRODUCT_DEVICE := mainline_sdk
 
 PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
+
+PRODUCT_BUILD_FROM_SOURCE_STUB := true
\ No newline at end of file
diff --git a/target/product/runtime_libart.mk b/target/product/runtime_libart.mk
index 68ed249..1e01b33 100644
--- a/target/product/runtime_libart.mk
+++ b/target/product/runtime_libart.mk
@@ -102,39 +102,63 @@
 PRODUCT_SYSTEM_PROPERTIES += \
     ro.dalvik.vm.native.bridge?=0
 
-# Different dexopt types for different package update/install times.
-# On eng builds, make "boot" reasons only extract for faster turnaround.
-ifeq (eng,$(TARGET_BUILD_VARIANT))
-    PRODUCT_SYSTEM_PROPERTIES += \
-        pm.dexopt.first-boot?=extract \
-        pm.dexopt.boot-after-ota?=extract
-else
-    PRODUCT_SYSTEM_PROPERTIES += \
-        pm.dexopt.first-boot?=verify \
-        pm.dexopt.boot-after-ota?=verify
-endif
-
 # The install filter is speed-profile in order to enable the use of
 # profiles from the dex metadata files. Note that if a profile is not provided
 # or if it is empty speed-profile is equivalent to (quicken + empty app image).
 # Note that `cmdline` is not strictly needed but it simplifies the management
 # of compilation reason in the platform (as we have a unified, single path,
 # without exceptions).
+# TODO(b/243646876): Remove `pm.dexopt.post-boot`.
 PRODUCT_SYSTEM_PROPERTIES += \
-    pm.dexopt.post-boot?=extract \
+    pm.dexopt.post-boot?=verify \
+    pm.dexopt.first-boot?=verify \
+    pm.dexopt.boot-after-ota?=verify \
     pm.dexopt.boot-after-mainline-update?=verify \
     pm.dexopt.install?=speed-profile \
     pm.dexopt.install-fast?=skip \
     pm.dexopt.install-bulk?=speed-profile \
     pm.dexopt.install-bulk-secondary?=verify \
     pm.dexopt.install-bulk-downgraded?=verify \
-    pm.dexopt.install-bulk-secondary-downgraded?=extract \
+    pm.dexopt.install-bulk-secondary-downgraded?=verify \
     pm.dexopt.bg-dexopt?=speed-profile \
     pm.dexopt.ab-ota?=speed-profile \
     pm.dexopt.inactive?=verify \
     pm.dexopt.cmdline?=verify \
     pm.dexopt.shared?=speed
 
+ifneq (,$(filter eng,$(TARGET_BUILD_VARIANT)))
+    OVERRIDE_DISABLE_DEXOPT_ALL ?= true
+endif
+
+# OVERRIDE_DISABLE_DEXOPT_ALL disables all dexpreopt (build-time) and dexopt (on-device) activities.
+# This option is for faster iteration during development and should never be enabled for production.
+ifneq (,$(filter true,$(OVERRIDE_DISABLE_DEXOPT_ALL)))
+  PRODUCT_SYSTEM_PROPERTIES += \
+    pm.dexopt.post-boot=skip \
+    pm.dexopt.first-boot=skip \
+    pm.dexopt.boot-after-ota=skip \
+    pm.dexopt.boot-after-mainline-update=skip \
+    pm.dexopt.install=skip \
+    pm.dexopt.install-fast=skip \
+    pm.dexopt.install-bulk=skip \
+    pm.dexopt.install-bulk-secondary=skip \
+    pm.dexopt.install-bulk-downgraded=skip \
+    pm.dexopt.install-bulk-secondary-downgraded=skip \
+    pm.dexopt.bg-dexopt=skip \
+    pm.dexopt.ab-ota=skip \
+    pm.dexopt.inactive=skip \
+    pm.dexopt.cmdline=skip \
+    pm.dexopt.shared=skip
+
+  PRODUCT_SYSTEM_PROPERTIES += dalvik.vm.disable-odrefresh=true
+
+  # Disable all dexpreopt activities except for the ART boot image.
+  # We have to dexpreopt the ART boot image because they are used by ART tests. This should not
+  # be too much of a problem for platform developers because a change to framework code should not
+  # trigger dexpreopt for the ART boot image.
+  WITH_DEXPREOPT_ART_BOOT_IMG_ONLY := true
+endif
+
 # Enable resolution of startup const strings.
 PRODUCT_SYSTEM_PROPERTIES += \
     dalvik.vm.dex2oat-resolve-startup-strings=true
diff --git a/target/product/sdk.mk b/target/product/sdk.mk
index fff8d4c..b9ccad3 100644
--- a/target/product/sdk.mk
+++ b/target/product/sdk.mk
@@ -30,3 +30,5 @@
 PRODUCT_DEVICE := mainline_x86
 
 PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
+
+PRODUCT_BUILD_FROM_SOURCE_STUB := true
\ No newline at end of file
diff --git a/target/product/sdk_phone_arm64.mk b/target/product/sdk_phone_arm64.mk
deleted file mode 100644
index c16c403..0000000
--- a/target/product/sdk_phone_arm64.mk
+++ /dev/null
@@ -1,66 +0,0 @@
-#
-# Copyright (C) 2009 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.
-#
-PRODUCT_USE_DYNAMIC_PARTITIONS := true
-
-# This is a build configuration for a full-featured build of the
-# Open-Source part of the tree. It's geared toward a US-centric
-# build quite specifically for the emulator, and might not be
-# entirely appropriate to inherit from for on-device configurations.
-
-# Enable mainline checking for exact this product name
-ifeq (sdk_phone_arm64,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-#
-# All components inherited here go to system image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
-
-#
-# All components inherited here go to system_ext image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
-
-#
-# All components inherited here go to product image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
-
-#
-# All components inherited here go to vendor or vendor_boot image
-#
-$(call inherit-product-if-exists, device/generic/goldfish/arm64-vendor.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/board/emulator_arm64/device.mk)
-
-# keep this apk for sdk targets for now
-PRODUCT_PACKAGES += \
-    EmulatorSmokeTests
-
-# Overrides
-PRODUCT_BRAND := Android
-PRODUCT_NAME := sdk_phone_arm64
-PRODUCT_DEVICE := emulator_arm64
-PRODUCT_MODEL := Android SDK built for arm64
-# Disable <uses-library> checks for SDK product. It lacks some libraries (e.g.
-# RadioConfigLib), which makes it impossible to translate their module names to
-# library name, so the check fails.
-PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
-
-PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_phone_x86_64.mk b/target/product/sdk_phone_x86_64.mk
deleted file mode 100644
index b2e14a5..0000000
--- a/target/product/sdk_phone_x86_64.mk
+++ /dev/null
@@ -1,62 +0,0 @@
-#
-# Copyright (C) 2009 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.
-#
-PRODUCT_USE_DYNAMIC_PARTITIONS := true
-
-# This is a build configuration for a full-featured build of the
-# Open-Source part of the tree. It's geared toward a US-centric
-# build quite specifically for the emulator, and might not be
-# entirely appropriate to inherit from for on-device configurations.
-
-#
-# All components inherited here go to system image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk)
-
-# Enable mainline checking for exact this product name
-ifeq (sdk_phone_x86_64,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-#
-# All components inherited here go to system_ext image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
-
-#
-# All components inherited here go to product image
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
-
-#
-# All components inherited here go to vendor image
-#
-$(call inherit-product-if-exists, device/generic/goldfish/x86_64-vendor.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/board/emulator_x86_64/device.mk)
-
-# Overrides
-PRODUCT_BRAND := Android
-PRODUCT_NAME := sdk_phone_x86_64
-PRODUCT_DEVICE := emulator_x86_64
-PRODUCT_MODEL := Android SDK built for x86_64
-# Disable <uses-library> checks for SDK product. It lacks some libraries (e.g.
-# RadioConfigLib), which makes it impossible to translate their module names to
-# library name, so the check fails.
-PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
-
-PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/telephony_system_ext.mk b/target/product/telephony_system_ext.mk
index f81a607..f821381 100644
--- a/target/product/telephony_system_ext.mk
+++ b/target/product/telephony_system_ext.mk
@@ -21,3 +21,7 @@
 PRODUCT_PACKAGES += \
     CarrierConfig \
     EmergencyInfo \
+
+PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34 += \
+    hwservicemanager \
+    android.hidl.allocator@1.0-service \
diff --git a/tools/Android.bp b/tools/Android.bp
index b8ab162..5c54fcf 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -96,3 +96,13 @@
         unit_test: true,
     },
 }
+
+python_binary_host {
+  name: "characteristics_rro_generator",
+  srcs: ["characteristics_rro_generator.py"],
+  version: {
+    py3: {
+      embedded_launcher: true,
+    },
+  },
+}
diff --git a/tools/aconfig/Android.bp b/tools/aconfig/Android.bp
index 02fc57c..e2fadb0 100644
--- a/tools/aconfig/Android.bp
+++ b/tools/aconfig/Android.bp
@@ -13,6 +13,11 @@
         type: "lite",
     },
     sdk_version: "current",
+    min_sdk_version: "UpsideDownCake",
+    apex_available: [
+        "com.android.configinfrastructure",
+        "//apex_available:platform",
+    ]
 }
 
 java_library_host {
@@ -53,6 +58,7 @@
         "libaconfig_protos",
         "libanyhow",
         "libclap",
+        "libitertools",
         "libprotobuf",
         "libserde",
         "libserde_json",
@@ -126,7 +132,7 @@
     name: "aconfig_host_test_java_library",
     aconfig_declarations: "aconfig.test.flags",
     host_supported: true,
-    test: true,
+    mode: "test",
 }
 
 java_test_host {
@@ -182,7 +188,7 @@
     name: "libaconfig_test_rust_library_with_test_mode",
     crate_name: "aconfig_test_rust_library",
     aconfig_declarations: "aconfig.test.flags",
-    test: true,
+    mode: "test",
 }
 
 rust_test {
diff --git a/tools/aconfig/Cargo.toml b/tools/aconfig/Cargo.toml
index 941b30d..2edf4b8 100644
--- a/tools/aconfig/Cargo.toml
+++ b/tools/aconfig/Cargo.toml
@@ -11,6 +11,7 @@
 [dependencies]
 anyhow = "1.0.69"
 clap = { version = "4.1.8", features = ["derive"] }
+itertools = "0.10.5"
 paste = "1.0.11"
 protobuf = "3.2.0"
 serde = { version = "1.0.152", features = ["derive"] }
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/protos/aconfig.proto b/tools/aconfig/protos/aconfig.proto
index d5e2868..9e193ec 100644
--- a/tools/aconfig/protos/aconfig.proto
+++ b/tools/aconfig/protos/aconfig.proto
@@ -40,6 +40,7 @@
   optional string description = 3;
   repeated string bug = 4;
   optional bool is_fixed_read_only = 5;
+  optional bool is_exported = 6;
 };
 
 message flag_declarations {
@@ -77,6 +78,8 @@
   optional flag_permission permission = 7;
   repeated tracepoint trace = 8;
   optional bool is_fixed_read_only = 9;
+  optional bool is_exported = 10;
+
 }
 
 message parsed_flags {
diff --git a/tools/aconfig/src/codegen_cpp.rs b/tools/aconfig/src/codegen_cpp.rs
index aeb57a3..5aa373a 100644
--- a/tools/aconfig/src/codegen_cpp.rs
+++ b/tools/aconfig/src/codegen_cpp.rs
@@ -31,9 +31,11 @@
 where
     I: Iterator<Item = &'a ProtoParsedFlag>,
 {
-    let class_elements: Vec<ClassElement> =
-        parsed_flags_iter.map(|pf| create_class_element(package, pf)).collect();
-    let readwrite = class_elements.iter().any(|item| item.readwrite);
+    let mut readwrite_count = 0;
+    let class_elements: Vec<ClassElement> = parsed_flags_iter
+        .map(|pf| create_class_element(package, pf, &mut readwrite_count))
+        .collect();
+    let readwrite = readwrite_count > 0;
     let has_fixed_read_only = class_elements.iter().any(|item| item.is_fixed_read_only);
     let header = package.replace('.', "_");
     let package_macro = header.to_uppercase();
@@ -46,6 +48,7 @@
         package,
         has_fixed_read_only,
         readwrite,
+        readwrite_count,
         for_test: codegen_mode == CodegenMode::Test,
         class_elements,
     };
@@ -88,12 +91,14 @@
     pub package: &'a str,
     pub has_fixed_read_only: bool,
     pub readwrite: bool,
+    pub readwrite_count: i32,
     pub for_test: bool,
     pub class_elements: Vec<ClassElement>,
 }
 
 #[derive(Serialize)]
 pub struct ClassElement {
+    pub readwrite_idx: i32,
     pub readwrite: bool,
     pub is_fixed_read_only: bool,
     pub default_value: String,
@@ -103,8 +108,15 @@
     pub device_config_flag: String,
 }
 
-fn create_class_element(package: &str, pf: &ProtoParsedFlag) -> ClassElement {
+fn create_class_element(package: &str, pf: &ProtoParsedFlag, rw_count: &mut i32) -> ClassElement {
     ClassElement {
+        readwrite_idx: if pf.permission() == ProtoFlagPermission::READ_WRITE {
+            let index = *rw_count;
+            *rw_count += 1;
+            index
+        } else {
+            -1
+        },
         readwrite: pf.permission() == ProtoFlagPermission::READ_WRITE,
         is_fixed_read_only: pf.is_fixed_read_only(),
         default_value: if pf.state() == ProtoFlagState::ENABLED {
@@ -141,6 +153,7 @@
 #include <memory>
 
 namespace com::android::aconfig::test {
+
 class flag_provider_interface {
 public:
     virtual ~flag_provider_interface() = default;
@@ -149,6 +162,8 @@
 
     virtual bool disabled_rw() = 0;
 
+    virtual bool disabled_rw_in_other_namespace() = 0;
+
     virtual bool enabled_fixed_ro() = 0;
 
     virtual bool enabled_ro() = 0;
@@ -166,6 +181,10 @@
     return provider_->disabled_rw();
 }
 
+inline bool disabled_rw_in_other_namespace() {
+    return provider_->disabled_rw_in_other_namespace();
+}
+
 inline bool enabled_fixed_ro() {
     return COM_ANDROID_ACONFIG_TEST_ENABLED_FIXED_RO;
 }
@@ -187,6 +206,8 @@
 
 bool com_android_aconfig_test_disabled_rw();
 
+bool com_android_aconfig_test_disabled_rw_in_other_namespace();
+
 bool com_android_aconfig_test_enabled_fixed_ro();
 
 bool com_android_aconfig_test_enabled_ro();
@@ -220,6 +241,10 @@
 
     virtual void disabled_rw(bool val) = 0;
 
+    virtual bool disabled_rw_in_other_namespace() = 0;
+
+    virtual void disabled_rw_in_other_namespace(bool val) = 0;
+
     virtual bool enabled_fixed_ro() = 0;
 
     virtual void enabled_fixed_ro(bool val) = 0;
@@ -253,6 +278,14 @@
     provider_->disabled_rw(val);
 }
 
+inline bool disabled_rw_in_other_namespace() {
+    return provider_->disabled_rw_in_other_namespace();
+}
+
+inline void disabled_rw_in_other_namespace(bool val) {
+    provider_->disabled_rw_in_other_namespace(val);
+}
+
 inline bool enabled_fixed_ro() {
     return provider_->enabled_fixed_ro();
 }
@@ -294,6 +327,10 @@
 
 void set_com_android_aconfig_test_disabled_rw(bool val);
 
+bool com_android_aconfig_test_disabled_rw_in_other_namespace();
+
+void set_com_android_aconfig_test_disabled_rw_in_other_namespace(bool val);
+
 bool com_android_aconfig_test_enabled_fixed_ro();
 
 void set_com_android_aconfig_test_enabled_fixed_ro(bool val);
@@ -319,6 +356,7 @@
     const PROD_SOURCE_FILE_EXPECTED: &str = r#"
 #include "com_android_aconfig_test.h"
 #include <server_configurable_flags/get_flags.h>
+#include <vector>
 
 namespace com::android::aconfig::test {
 
@@ -330,10 +368,23 @@
             }
 
             virtual bool disabled_rw() override {
-                return server_configurable_flags::GetServerConfigurableFlag(
-                    "aconfig_flags.aconfig_test",
-                    "com.android.aconfig.test.disabled_rw",
-                    "false") == "true";
+                if (cache_[0] == -1) {
+                    cache_[0] = server_configurable_flags::GetServerConfigurableFlag(
+                        "aconfig_flags.aconfig_test",
+                        "com.android.aconfig.test.disabled_rw",
+                        "false") == "true";
+                }
+                return cache_[0];
+            }
+
+            virtual bool disabled_rw_in_other_namespace() override {
+                if (cache_[1] == -1) {
+                    cache_[1] = server_configurable_flags::GetServerConfigurableFlag(
+                        "aconfig_flags.other_namespace",
+                        "com.android.aconfig.test.disabled_rw_in_other_namespace",
+                        "false") == "true";
+                }
+                return cache_[1];
             }
 
             virtual bool enabled_fixed_ro() override {
@@ -345,12 +396,17 @@
             }
 
             virtual bool enabled_rw() override {
-                return server_configurable_flags::GetServerConfigurableFlag(
-                    "aconfig_flags.aconfig_test",
-                    "com.android.aconfig.test.enabled_rw",
-                    "true") == "true";
+                if (cache_[2] == -1) {
+                    cache_[2] = server_configurable_flags::GetServerConfigurableFlag(
+                        "aconfig_flags.aconfig_test",
+                        "com.android.aconfig.test.enabled_rw",
+                        "true") == "true";
+                }
+                return cache_[2];
             }
 
+    private:
+        std::vector<int8_t> cache_ = std::vector<int8_t>(3, -1);
     };
 
     std::unique_ptr<flag_provider_interface> provider_ =
@@ -365,6 +421,10 @@
     return com::android::aconfig::test::disabled_rw();
 }
 
+bool com_android_aconfig_test_disabled_rw_in_other_namespace() {
+    return com::android::aconfig::test::disabled_rw_in_other_namespace();
+}
+
 bool com_android_aconfig_test_enabled_fixed_ro() {
     return COM_ANDROID_ACONFIG_TEST_ENABLED_FIXED_RO;
 }
@@ -425,6 +485,22 @@
                 overrides_["disabled_rw"] = val;
             }
 
+            virtual bool disabled_rw_in_other_namespace() override {
+                auto it = overrides_.find("disabled_rw_in_other_namespace");
+                  if (it != overrides_.end()) {
+                      return it->second;
+                } else {
+                  return server_configurable_flags::GetServerConfigurableFlag(
+                      "aconfig_flags.other_namespace",
+                      "com.android.aconfig.test.disabled_rw_in_other_namespace",
+                      "false") == "true";
+                }
+            }
+
+            virtual void disabled_rw_in_other_namespace(bool val) override {
+                overrides_["disabled_rw_in_other_namespace"] = val;
+            }
+
             virtual bool enabled_fixed_ro() override {
                 auto it = overrides_.find("enabled_fixed_ro");
                   if (it != overrides_.end()) {
@@ -494,6 +570,15 @@
     com::android::aconfig::test::disabled_rw(val);
 }
 
+bool com_android_aconfig_test_disabled_rw_in_other_namespace() {
+    return com::android::aconfig::test::disabled_rw_in_other_namespace();
+}
+
+
+void set_com_android_aconfig_test_disabled_rw_in_other_namespace(bool val) {
+    com::android::aconfig::test::disabled_rw_in_other_namespace(val);
+}
+
 
 bool com_android_aconfig_test_enabled_fixed_ro() {
     return com::android::aconfig::test::enabled_fixed_ro();
diff --git a/tools/aconfig/src/codegen_java.rs b/tools/aconfig/src/codegen_java.rs
index 43c2ecf..a822cd5 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::{BTreeMap, BTreeSet};
 use std::path::PathBuf;
 use tinytemplate::TinyTemplate;
 
@@ -31,12 +32,21 @@
 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 namespace_flags = gen_flags_by_namespace(&flag_elements);
+    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,
+        namespace_flags,
+        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(
@@ -64,51 +74,92 @@
         .collect::<Result<Vec<OutputFile>>>()
 }
 
-#[derive(Serialize)]
-struct Context {
-    pub class_elements: Vec<ClassElement>,
-    pub is_test_mode: bool,
-    pub is_read_write: bool,
-    pub package_name: String,
+fn gen_flags_by_namespace(flags: &[FlagElement]) -> Vec<NamespaceFlags> {
+    let mut namespace_to_flag: BTreeMap<String, Vec<FlagElement>> = BTreeMap::new();
+
+    for flag in flags {
+        match namespace_to_flag.get_mut(&flag.device_config_namespace) {
+            Some(flag_list) => flag_list.push(flag.clone()),
+            None => {
+                namespace_to_flag.insert(flag.device_config_namespace.clone(), vec![flag.clone()]);
+            }
+        }
+    }
+
+    namespace_to_flag
+        .iter()
+        .map(|(namespace, flags)| NamespaceFlags {
+            namespace: namespace.to_string(),
+            flags: flags.clone(),
+        })
+        .collect()
 }
 
 #[derive(Serialize)]
-struct ClassElement {
+struct Context {
+    pub flag_elements: Vec<FlagElement>,
+    pub namespace_flags: Vec<NamespaceFlags>,
+    pub is_test_mode: bool,
+    pub is_read_write: bool,
+    pub properties_set: BTreeSet<String>,
+    pub package_name: String,
+}
+
+#[derive(Serialize, Debug)]
+struct NamespaceFlags {
+    pub namespace: String,
+    pub flags: Vec<FlagElement>,
+}
+
+#[derive(Serialize, Clone, Debug)]
+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)]
@@ -127,6 +178,8 @@
         boolean disabledRo();
         @UnsupportedAppUsage
         boolean disabledRw();
+        @UnsupportedAppUsage
+        boolean disabledRwInOtherNamespace();
         @com.android.aconfig.annotations.AssumeTrueForR8
         @UnsupportedAppUsage
         boolean enabledFixedRo();
@@ -149,6 +202,8 @@
         /** @hide */
         public static final String FLAG_DISABLED_RW = "com.android.aconfig.test.disabled_rw";
         /** @hide */
+        public static final String FLAG_DISABLED_RW_IN_OTHER_NAMESPACE = "com.android.aconfig.test.disabled_rw_in_other_namespace";
+        /** @hide */
         public static final String FLAG_ENABLED_FIXED_RO = "com.android.aconfig.test.enabled_fixed_ro";
         /** @hide */
         public static final String FLAG_ENABLED_RO = "com.android.aconfig.test.enabled_ro";
@@ -164,6 +219,10 @@
         public static boolean disabledRw() {
             return FEATURE_FLAGS.disabledRw();
         }
+        @UnsupportedAppUsage
+        public static boolean disabledRwInOtherNamespace() {
+            return FEATURE_FLAGS.disabledRwInOtherNamespace();
+        }
         @com.android.aconfig.annotations.AssumeTrueForR8
         @UnsupportedAppUsage
         public static boolean enabledFixedRo() {
@@ -203,6 +262,11 @@
         }
         @Override
         @UnsupportedAppUsage
+        public boolean disabledRwInOtherNamespace() {
+            return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE);
+        }
+        @Override
+        @UnsupportedAppUsage
         public boolean enabledFixedRo() {
             return getValue(Flags.FLAG_ENABLED_FIXED_RO);
         }
@@ -238,6 +302,7 @@
             Map.ofEntries(
                 Map.entry(Flags.FLAG_DISABLED_RO, false),
                 Map.entry(Flags.FLAG_DISABLED_RW, false),
+                Map.entry(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false),
                 Map.entry(Flags.FLAG_ENABLED_FIXED_RO, false),
                 Map.entry(Flags.FLAG_ENABLED_RO, false),
                 Map.entry(Flags.FLAG_ENABLED_RW, false)
@@ -265,8 +330,55 @@
         // 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 static boolean aconfig_test_is_cached = false;
+            private static boolean other_namespace_is_cached = false;
+            private static boolean disabledRw = false;
+            private static boolean disabledRwInOtherNamespace = false;
+            private static boolean enabledRw = true;
+
+
+            private void load_overrides_aconfig_test() {
+                try {
+                    Properties properties = DeviceConfig.getProperties("aconfig_test");
+                    disabledRw =
+                        properties.getBoolean("com.android.aconfig.test.disabled_rw", false);
+                    enabledRw =
+                        properties.getBoolean("com.android.aconfig.test.enabled_rw", true);
+                } catch (NullPointerException e) {
+                    throw new RuntimeException(
+                        "Cannot read value from namespace aconfig_test "
+                        + "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
+                    );
+                }
+                aconfig_test_is_cached = true;
+            }
+
+            private void load_overrides_other_namespace() {
+                try {
+                    Properties properties = DeviceConfig.getProperties("other_namespace");
+                    disabledRwInOtherNamespace =
+                        properties.getBoolean("com.android.aconfig.test.disabled_rw_in_other_namespace", false);
+                } catch (NullPointerException e) {
+                    throw new RuntimeException(
+                        "Cannot read value from namespace other_namespace "
+                        + "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
+                    );
+                }
+                other_namespace_is_cached = true;
+            }
+
+
             @Override
             @UnsupportedAppUsage
             public boolean disabledRo() {
@@ -275,11 +387,18 @@
             @Override
             @UnsupportedAppUsage
             public boolean disabledRw() {
-                return getValue(
-                    "aconfig_test",
-                    "com.android.aconfig.test.disabled_rw",
-                    false
-                );
+                if (!aconfig_test_is_cached) {
+                    load_overrides_aconfig_test();
+                }
+                return disabledRw;
+            }
+            @Override
+            @UnsupportedAppUsage
+            public boolean disabledRwInOtherNamespace() {
+                if (!other_namespace_is_cached) {
+                    load_overrides_other_namespace();
+                }
+                return disabledRwInOtherNamespace;
             }
             @Override
             @UnsupportedAppUsage
@@ -294,32 +413,10 @@
             @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
-                    );
-                } 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.",
-                        e
-                    );
+                if (!aconfig_test_is_cached) {
+                    load_overrides_aconfig_test();
                 }
-                return value;
+                return enabledRw;
             }
         }
         "#;
@@ -392,6 +489,12 @@
             }
             @Override
             @UnsupportedAppUsage
+            public boolean disabledRwInOtherNamespace() {
+                throw new UnsupportedOperationException(
+                    "Method is not implemented.");
+            }
+            @Override
+            @UnsupportedAppUsage
             public boolean enabledFixedRo() {
                 throw new UnsupportedOperationException(
                     "Method is not implemented.");
@@ -441,9 +544,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/src/codegen_rust.rs b/tools/aconfig/src/codegen_rust.rs
index 4e4c7dd..d8675e7 100644
--- a/tools/aconfig/src/codegen_rust.rs
+++ b/tools/aconfig/src/codegen_rust.rs
@@ -32,10 +32,12 @@
 {
     let template_flags: Vec<TemplateParsedFlag> =
         parsed_flags_iter.map(|pf| TemplateParsedFlag::new(package, pf)).collect();
+    let has_readwrite = template_flags.iter().any(|item| item.readwrite);
     let context = TemplateContext {
         package: package.to_string(),
         template_flags,
         modules: package.split('.').map(|s| s.to_string()).collect::<Vec<_>>(),
+        has_readwrite,
     };
     let mut template = TinyTemplate::new();
     template.add_template(
@@ -55,6 +57,7 @@
     pub package: String,
     pub template_flags: Vec<TemplateParsedFlag>,
     pub modules: Vec<String>,
+    pub has_readwrite: bool,
 }
 
 #[derive(Serialize)]
@@ -94,6 +97,26 @@
 /// flag provider
 pub struct FlagProvider;
 
+lazy_static::lazy_static! {
+    /// flag value cache for disabled_rw
+    static ref CACHED_disabled_rw: bool = flags_rust::GetServerConfigurableFlag(
+        "aconfig_flags.aconfig_test",
+        "com.android.aconfig.test.disabled_rw",
+        "false") == "true";
+
+    /// flag value cache for disabled_rw_in_other_namespace
+    static ref CACHED_disabled_rw_in_other_namespace: bool = flags_rust::GetServerConfigurableFlag(
+        "aconfig_flags.other_namespace",
+        "com.android.aconfig.test.disabled_rw_in_other_namespace",
+        "false") == "true";
+
+    /// flag value cache for enabled_rw
+    static ref CACHED_enabled_rw: bool = flags_rust::GetServerConfigurableFlag(
+        "aconfig_flags.aconfig_test",
+        "com.android.aconfig.test.enabled_rw",
+        "true") == "true";
+}
+
 impl FlagProvider {
     /// query flag disabled_ro
     pub fn disabled_ro(&self) -> bool {
@@ -102,10 +125,12 @@
 
     /// query flag disabled_rw
     pub fn disabled_rw(&self) -> bool {
-        flags_rust::GetServerConfigurableFlag(
-            "aconfig_flags.aconfig_test",
-            "com.android.aconfig.test.disabled_rw",
-            "false") == "true"
+        *CACHED_disabled_rw
+    }
+
+    /// query flag disabled_rw_in_other_namespace
+    pub fn disabled_rw_in_other_namespace(&self) -> bool {
+        *CACHED_disabled_rw_in_other_namespace
     }
 
     /// query flag enabled_fixed_ro
@@ -120,10 +145,7 @@
 
     /// query flag enabled_rw
     pub fn enabled_rw(&self) -> bool {
-        flags_rust::GetServerConfigurableFlag(
-            "aconfig_flags.aconfig_test",
-            "com.android.aconfig.test.enabled_rw",
-            "true") == "true"
+        *CACHED_enabled_rw
     }
 }
 
@@ -142,6 +164,12 @@
     PROVIDER.disabled_rw()
 }
 
+/// query flag disabled_rw_in_other_namespace
+#[inline(always)]
+pub fn disabled_rw_in_other_namespace() -> bool {
+    PROVIDER.disabled_rw_in_other_namespace()
+}
+
 /// query flag enabled_fixed_ro
 #[inline(always)]
 pub fn enabled_fixed_ro() -> bool {
@@ -200,6 +228,21 @@
         self.overrides.insert("disabled_rw", val);
     }
 
+    /// query flag disabled_rw_in_other_namespace
+    pub fn disabled_rw_in_other_namespace(&self) -> bool {
+        self.overrides.get("disabled_rw_in_other_namespace").copied().unwrap_or(
+            flags_rust::GetServerConfigurableFlag(
+                "aconfig_flags.other_namespace",
+                "com.android.aconfig.test.disabled_rw_in_other_namespace",
+                "false") == "true"
+        )
+    }
+
+    /// set flag disabled_rw_in_other_namespace
+    pub fn set_disabled_rw_in_other_namespace(&mut self, val: bool) {
+        self.overrides.insert("disabled_rw_in_other_namespace", val);
+    }
+
     /// query flag enabled_fixed_ro
     pub fn enabled_fixed_ro(&self) -> bool {
         self.overrides.get("enabled_fixed_ro").copied().unwrap_or(
@@ -274,6 +317,18 @@
     PROVIDER.lock().unwrap().set_disabled_rw(val);
 }
 
+/// query flag disabled_rw_in_other_namespace
+#[inline(always)]
+pub fn disabled_rw_in_other_namespace() -> bool {
+    PROVIDER.lock().unwrap().disabled_rw_in_other_namespace()
+}
+
+/// set flag disabled_rw_in_other_namespace
+#[inline(always)]
+pub fn set_disabled_rw_in_other_namespace(val: bool) {
+    PROVIDER.lock().unwrap().set_disabled_rw_in_other_namespace(val);
+}
+
 /// query flag enabled_fixed_ro
 #[inline(always)]
 pub fn enabled_fixed_ro() -> bool {
diff --git a/tools/aconfig/src/commands.rs b/tools/aconfig/src/commands.rs
index 7b05147..ff0df1f 100644
--- a/tools/aconfig/src/commands.rs
+++ b/tools/aconfig/src/commands.rs
@@ -98,6 +98,7 @@
             };
             parsed_flag.set_permission(flag_permission);
             parsed_flag.set_is_fixed_read_only(flag_declaration.is_fixed_read_only());
+            parsed_flag.set_is_exported(flag_declaration.is_exported());
             let mut tracepoint = ProtoTracepoint::new();
             tracepoint.set_source(input.source.clone());
             tracepoint.set_state(DEFAULT_FLAG_STATE);
@@ -334,7 +335,7 @@
         assert_eq!(ProtoFlagState::ENABLED, enabled_ro.trace[2].state());
         assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.trace[2].permission());
 
-        assert_eq!(5, parsed_flags.parsed_flag.len());
+        assert_eq!(6, parsed_flags.parsed_flag.len());
         for pf in parsed_flags.parsed_flag.iter() {
             if pf.name() == "enabled_fixed_ro" {
                 continue;
@@ -433,7 +434,7 @@
         let input = parse_test_flags_as_input();
         let bytes = create_device_config_defaults(input).unwrap();
         let text = std::str::from_utf8(&bytes).unwrap();
-        assert_eq!("aconfig_test:com.android.aconfig.test.disabled_rw=disabled\naconfig_test:com.android.aconfig.test.enabled_rw=enabled\n", text);
+        assert_eq!("aconfig_test:com.android.aconfig.test.disabled_rw=disabled\nother_namespace:com.android.aconfig.test.disabled_rw_in_other_namespace=disabled\naconfig_test:com.android.aconfig.test.enabled_rw=enabled\n", text);
     }
 
     #[test]
@@ -441,7 +442,7 @@
         let input = parse_test_flags_as_input();
         let bytes = create_device_config_sysprops(input).unwrap();
         let text = std::str::from_utf8(&bytes).unwrap();
-        assert_eq!("persist.device_config.com.android.aconfig.test.disabled_rw=false\npersist.device_config.com.android.aconfig.test.enabled_rw=true\n", text);
+        assert_eq!("persist.device_config.com.android.aconfig.test.disabled_rw=false\npersist.device_config.com.android.aconfig.test.disabled_rw_in_other_namespace=false\npersist.device_config.com.android.aconfig.test.enabled_rw=true\n", text);
     }
 
     #[test]
diff --git a/tools/aconfig/src/protos.rs b/tools/aconfig/src/protos.rs
index d3b5b37..a5a5342 100644
--- a/tools/aconfig/src/protos.rs
+++ b/tools/aconfig/src/protos.rs
@@ -308,6 +308,7 @@
     namespace: "first_ns"
     description: "This is the description of the first flag."
     bug: "123"
+    is_exported: true
 }
 flag {
     name: "second"
@@ -326,12 +327,14 @@
         assert_eq!(first.description(), "This is the description of the first flag.");
         assert_eq!(first.bug, vec!["123"]);
         assert!(!first.is_fixed_read_only());
+        assert!(first.is_exported());
         let second = flag_declarations.flag.iter().find(|pf| pf.name() == "second").unwrap();
         assert_eq!(second.name(), "second");
         assert_eq!(second.namespace(), "second_ns");
         assert_eq!(second.description(), "This is the description of the second flag.");
         assert_eq!(second.bug, vec!["abc"]);
         assert!(second.is_fixed_read_only());
+        assert!(!second.is_exported());
 
         // bad input: missing package in flag declarations
         let error = flag_declarations::try_from_text_proto(
diff --git a/tools/aconfig/src/test.rs b/tools/aconfig/src/test.rs
index 9034704..31c67b3 100644
--- a/tools/aconfig/src/test.rs
+++ b/tools/aconfig/src/test.rs
@@ -42,6 +42,7 @@
     permission: READ_ONLY
   }
   is_fixed_read_only: false
+  is_exported: false
 }
 parsed_flag {
   package: "com.android.aconfig.test"
@@ -57,6 +58,28 @@
     permission: READ_WRITE
   }
   is_fixed_read_only: false
+  is_exported: true
+}
+parsed_flag {
+  package: "com.android.aconfig.test"
+  name: "disabled_rw_in_other_namespace"
+  namespace: "other_namespace"
+  description: "This flag is DISABLED + READ_WRITE, and is defined in another namespace"
+  bug: "999"
+  state: DISABLED
+  permission: READ_WRITE
+  trace {
+    source: "tests/test.aconfig"
+    state: DISABLED
+    permission: READ_WRITE
+  }
+  trace {
+    source: "tests/first.values"
+    state: DISABLED
+    permission: READ_WRITE
+  }
+  is_fixed_read_only: false
+  is_exported: false
 }
 parsed_flag {
   package: "com.android.aconfig.test"
@@ -77,6 +100,7 @@
     permission: READ_ONLY
   }
   is_fixed_read_only: true
+  is_exported: false
 }
 parsed_flag {
   package: "com.android.aconfig.test"
@@ -102,6 +126,7 @@
     permission: READ_ONLY
   }
   is_fixed_read_only: false
+  is_exported: false
 }
 parsed_flag {
   package: "com.android.aconfig.test"
@@ -122,6 +147,7 @@
     permission: READ_WRITE
   }
   is_fixed_read_only: false
+  is_exported: false
 }
 "#;
 
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..ec8822c 100644
--- a/tools/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/templates/FeatureFlagsImpl.java.template
@@ -4,59 +4,73 @@
 {{ 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}}
-    @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}
-        );
-    {{ else }}
-        return {item.default_value};
-    {{ endif- }}
-    }
+{{- if is_read_write }}
+{{- for namespace_with_flags in namespace_flags }}
+    private static boolean {namespace_with_flags.namespace}_is_cached = false;
+{{- endfor- }}
+
+{{ for flag in flag_elements }}
+{{- if flag.is_read_write }}
+    private static boolean {flag.method_name} = {flag.default_value};
+{{- endif- }}
 {{ endfor }}
-{{ if is_read_write- }}
-    private boolean getValue(String nameSpace,
-        String flagName, boolean defaultValue) \{
-        boolean value = defaultValue;
+
+{{ for namespace_with_flags in namespace_flags }}
+    private void load_overrides_{namespace_with_flags.namespace}() \{
         try \{
-            value = DeviceConfig.getBoolean(
-                nameSpace,
-                flagName,
-                defaultValue
-            );
+            Properties properties = DeviceConfig.getProperties("{namespace_with_flags.namespace}");
+
+            {{- for flag in namespace_with_flags.flags }}
+            {{- if flag.is_read_write }}
+            {flag.method_name} =
+                properties.getBoolean("{flag.device_config_flag}", {flag.default_value});
+            {{- endif- }}
+            {{ endfor }}
         } 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 from namespace {namespace_with_flags.namespace} "
+                + "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;
+        {namespace_with_flags.namespace}_is_cached = true;
     }
+{{ endfor- }}
 {{ endif- }}
+
+{{ for flag in flag_elements }}
+    @Override
+    @UnsupportedAppUsage
+    public boolean {flag.method_name}() \{
+    {{ -if flag.is_read_write }}
+        if (!{flag.device_config_namespace}_is_cached) \{
+            load_overrides_{flag.device_config_namespace}();
+        }
+        return {flag.method_name};
+    {{ else }}
+        return {flag.default_value};
+    {{ endif- }}
+    }
+{{ endfor }}
 }
 {{ else }}
 {#- 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.");
     }
-{{ endfor }}
+{{ endfor- }}
 }
 {{ endif }}
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/aconfig/templates/cpp_exported_header.template b/tools/aconfig/templates/cpp_exported_header.template
index 6413699..cc1b18d 100644
--- a/tools/aconfig/templates/cpp_exported_header.template
+++ b/tools/aconfig/templates/cpp_exported_header.template
@@ -19,7 +19,6 @@
 
 #include <memory>
 
-
 namespace {cpp_namespace} \{
 
 class flag_provider_interface \{
diff --git a/tools/aconfig/templates/cpp_source_file.template b/tools/aconfig/templates/cpp_source_file.template
index 0f1b845..1bfa4b6 100644
--- a/tools/aconfig/templates/cpp_source_file.template
+++ b/tools/aconfig/templates/cpp_source_file.template
@@ -5,6 +5,8 @@
 {{ if for_test }}
 #include <unordered_map>
 #include <string>
+{{ -else- }}
+#include <vector>
 {{ endif }}
 
 namespace {cpp_namespace} \{
@@ -53,10 +55,13 @@
         {{ for item in class_elements}}
         virtual bool {item.flag_name}() override \{
             {{ if item.readwrite- }}
-            return server_configurable_flags::GetServerConfigurableFlag(
-                "aconfig_flags.{item.device_config_namespace}",
-                "{item.device_config_flag}",
-                "{item.default_value}") == "true";
+            if (cache_[{item.readwrite_idx}] == -1) \{
+                cache_[{item.readwrite_idx}] = server_configurable_flags::GetServerConfigurableFlag(
+                    "aconfig_flags.{item.device_config_namespace}",
+                    "{item.device_config_flag}",
+                    "{item.default_value}") == "true";
+            }
+            return cache_[{item.readwrite_idx}];
             {{ -else- }}
             {{ if item.is_fixed_read_only }}
             return {package_macro}_{item.flag_macro};
@@ -66,15 +71,15 @@
             {{ -endif }}
         }
         {{ endfor }}
+    private:
+        std::vector<int8_t> cache_ = std::vector<int8_t>({readwrite_count}, -1);
     };
 
 
 {{ -endif }}
 
-
 std::unique_ptr<flag_provider_interface> provider_ =
     std::make_unique<flag_provider>();
-
 }
 
 
diff --git a/tools/aconfig/templates/rust_prod.template b/tools/aconfig/templates/rust_prod.template
index e22ad6f..30ea646 100644
--- a/tools/aconfig/templates/rust_prod.template
+++ b/tools/aconfig/templates/rust_prod.template
@@ -3,16 +3,27 @@
 /// flag provider
 pub struct FlagProvider;
 
+{{ if has_readwrite - }}
+lazy_static::lazy_static! \{
+    {{ for flag in template_flags }}
+    {{ if flag.readwrite -}}
+    /// flag value cache for {flag.name}
+    static ref CACHED_{flag.name}: bool = flags_rust::GetServerConfigurableFlag(
+        "aconfig_flags.{flag.device_config_namespace}",
+        "{flag.device_config_flag}",
+        "{flag.default_value}") == "true";
+    {{ -endif }}
+    {{ endfor }}
+}
+{{ -endif }}
+
 impl FlagProvider \{
 
     {{ for flag in template_flags }}
     /// query flag {flag.name}
     pub fn {flag.name}(&self) -> bool \{
     {{ if flag.readwrite -}}
-        flags_rust::GetServerConfigurableFlag(
-          "aconfig_flags.{flag.device_config_namespace}",
-          "{flag.device_config_flag}",
-          "{flag.default_value}") == "true"
+        *CACHED_{flag.name}
     {{ -else- }}
         {flag.default_value}
     {{ -endif }}
diff --git a/tools/aconfig/tests/first.values b/tools/aconfig/tests/first.values
index a450f78..07d8d1d 100644
--- a/tools/aconfig/tests/first.values
+++ b/tools/aconfig/tests/first.values
@@ -18,6 +18,12 @@
 }
 flag_value {
     package: "com.android.aconfig.test"
+    name: "disabled_rw_in_other_namespace"
+    state: DISABLED
+    permission: READ_WRITE
+}
+flag_value {
+    package: "com.android.aconfig.test"
     name: "enabled_fixed_ro"
     state: ENABLED
     permission: READ_ONLY
diff --git a/tools/aconfig/tests/test.aconfig b/tools/aconfig/tests/test.aconfig
index aaa6df5..b49b665 100644
--- a/tools/aconfig/tests/test.aconfig
+++ b/tools/aconfig/tests/test.aconfig
@@ -39,6 +39,7 @@
     namespace: "aconfig_test"
     description: "This flag is DISABLED + READ_WRITE"
     bug: "456"
+    is_exported: true
 }
 
 # This flag's final value calculated from:
@@ -51,3 +52,10 @@
     bug: ""
     is_fixed_read_only: true
 }
+
+flag {
+    name: "disabled_rw_in_other_namespace"
+    namespace: "other_namespace"
+    description: "This flag is DISABLED + READ_WRITE, and is defined in another namespace"
+    bug: "999"
+}
diff --git a/tools/auto_gen_test_config_test.py b/tools/auto_gen_test_config_test.py
index ce97723..b7ef0b0 100644
--- a/tools/auto_gen_test_config_test.py
+++ b/tools/auto_gen_test_config_test.py
@@ -93,7 +93,7 @@
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        {EXTRA_TEST_RUNNER_CONFIGS}<option name="package" value="com.android.my.tests.x" />
+        <option name="package" value="com.android.my.tests.x" />
         <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
     </test>
 </configuration>
@@ -125,7 +125,7 @@
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.InstrumentationTest" >
-        {EXTRA_TEST_RUNNER_CONFIGS}<option name="package" value="com.android.my.tests.x" />
+        <option name="package" value="com.android.my.tests.x" />
         <option name="runner" value="android.test.InstrumentationTestRunner" />
     </test>
 </configuration>
@@ -178,7 +178,7 @@
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.{TEST_TYPE}" >
-        {EXTRA_TEST_RUNNER_CONFIGS}<option name="package" value="{PACKAGE}" />
+        <option name="package" value="{PACKAGE}" />
         <option name="runner" value="{RUNNER}" />
     </test>
 </configuration>
diff --git a/tools/characteristics_rro_generator.py b/tools/characteristics_rro_generator.py
new file mode 100644
index 0000000..6489673
--- /dev/null
+++ b/tools/characteristics_rro_generator.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+import sys
+from xml.dom.minidom import parseString
+
+def parse_package(manifest):
+    with open(manifest, 'r') as f:
+        data = f.read()
+    dom = parseString(data)
+    return dom.documentElement.getAttribute('package')
+
+if __name__ == '__main__':
+    if len(sys.argv) != 3:
+        sys.exit(f"usage: {sys_argv[0]} target_package_manifest output\n")
+    package_name = parse_package(sys.argv[1])
+    with open(sys.argv[2], "w") as f:
+        f.write(f'''<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="{package_name}.auto_generated_characteristics_rro">
+    <application android:hasCode="false" />
+    <overlay android:targetPackage="{package_name}"
+             android:isStatic="true"
+             android:priority="0" />
+</manifest>
+''')
diff --git a/tools/finalization/environment.sh b/tools/finalization/environment.sh
index 9714ac4..d9c42c8 100755
--- a/tools/finalization/environment.sh
+++ b/tools/finalization/environment.sh
@@ -22,3 +22,5 @@
 # 'sdk' - SDK/API is finalized
 # 'rel' - branch is finalized, switched to REL
 export FINAL_STATE='unfinalized'
+
+export BUILD_FROM_SOURCE_STUB=true
\ No newline at end of file
diff --git a/tools/metadata/Android.bp b/tools/metadata/Android.bp
new file mode 100644
index 0000000..b2fabec
--- /dev/null
+++ b/tools/metadata/Android.bp
@@ -0,0 +1,14 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+blueprint_go_binary {
+    name: "metadata",
+    deps: [
+            "soong-testing-test_spec_proto",
+            "golang-protobuf-proto",
+        ],
+    srcs: [
+        "generator.go",
+    ]
+}
\ No newline at end of file
diff --git a/tools/metadata/OWNERS b/tools/metadata/OWNERS
new file mode 100644
index 0000000..03bcdf1
--- /dev/null
+++ b/tools/metadata/OWNERS
@@ -0,0 +1,4 @@
+dariofreni@google.com
+joeo@google.com
+ronish@google.com
+caditya@google.com
diff --git a/tools/metadata/generator.go b/tools/metadata/generator.go
new file mode 100644
index 0000000..e970e17
--- /dev/null
+++ b/tools/metadata/generator.go
@@ -0,0 +1,195 @@
+package main
+
+import (
+	"flag"
+	"fmt"
+	"io"
+	"log"
+	"os"
+	"sort"
+	"strings"
+	"sync"
+
+	"android/soong/testing/test_spec_proto"
+	"google.golang.org/protobuf/proto"
+)
+
+type keyToLocksMap struct {
+	locks sync.Map
+}
+
+func (kl *keyToLocksMap) GetLockForKey(key string) *sync.Mutex {
+	mutex, _ := kl.locks.LoadOrStore(key, &sync.Mutex{})
+	return mutex.(*sync.Mutex)
+}
+
+func getSortedKeys(syncMap *sync.Map) []string {
+	var allKeys []string
+	syncMap.Range(
+		func(key, _ interface{}) bool {
+			allKeys = append(allKeys, key.(string))
+			return true
+		},
+	)
+
+	sort.Strings(allKeys)
+	return allKeys
+}
+
+func writeOutput(
+	outputFile string,
+	allMetadata []*test_spec_proto.TestSpec_OwnershipMetadata,
+) {
+	testSpec := &test_spec_proto.TestSpec{
+		OwnershipMetadataList: allMetadata,
+	}
+	data, err := proto.Marshal(testSpec)
+	if err != nil {
+		log.Fatal(err)
+	}
+	file, err := os.Create(outputFile)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer file.Close()
+
+	_, err = file.Write(data)
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+func readFileToString(filePath string) string {
+	file, err := os.Open(filePath)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer file.Close()
+
+	data, err := io.ReadAll(file)
+	if err != nil {
+		log.Fatal(err)
+	}
+	return string(data)
+}
+
+func writeNewlineToOutputFile(outputFile string) {
+	file, err := os.Create(outputFile)
+	data := "\n"
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer file.Close()
+
+	_, err = file.Write([]byte(data))
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+func processTestSpecProtobuf(
+	filePath string, ownershipMetadataMap *sync.Map, keyLocks *keyToLocksMap,
+	errCh chan error, wg *sync.WaitGroup,
+) {
+	defer wg.Done()
+
+	fileContent := strings.TrimRight(readFileToString(filePath), "\n")
+	testData := test_spec_proto.TestSpec{}
+	err := proto.Unmarshal([]byte(fileContent), &testData)
+	if err != nil {
+		errCh <- err
+		return
+	}
+
+	ownershipMetadata := testData.GetOwnershipMetadataList()
+	for _, metadata := range ownershipMetadata {
+		key := metadata.GetTargetName()
+		lock := keyLocks.GetLockForKey(key)
+		lock.Lock()
+
+		value, loaded := ownershipMetadataMap.LoadOrStore(
+			key, []*test_spec_proto.TestSpec_OwnershipMetadata{metadata},
+		)
+		if loaded {
+			existingMetadata := value.([]*test_spec_proto.TestSpec_OwnershipMetadata)
+			isDuplicate := false
+			for _, existing := range existingMetadata {
+				if metadata.GetTrendyTeamId() != existing.GetTrendyTeamId() {
+					errCh <- fmt.Errorf(
+						"Conflicting trendy team IDs found for %s at:\n%s with teamId"+
+							": %s,\n%s with teamId: %s",
+						key,
+						metadata.GetPath(), metadata.GetTrendyTeamId(), existing.GetPath(),
+						existing.GetTrendyTeamId(),
+					)
+
+					lock.Unlock()
+					return
+				}
+				if metadata.GetTrendyTeamId() == existing.GetTrendyTeamId() && metadata.GetPath() == existing.GetPath() {
+					isDuplicate = true
+					break
+				}
+			}
+			if !isDuplicate {
+				existingMetadata = append(existingMetadata, metadata)
+				ownershipMetadataMap.Store(key, existingMetadata)
+			}
+		}
+
+		lock.Unlock()
+	}
+}
+
+func main() {
+	inputFile := flag.String("inputFile", "", "Input file path")
+	outputFile := flag.String("outputFile", "", "Output file path")
+	rule := flag.String("rule", "", "Metadata rule (Hint: test_spec or code_metadata)")
+	flag.Parse()
+
+	if *inputFile == "" || *outputFile == "" || *rule == "" {
+		fmt.Println("Usage: metadata -rule <rule> -inputFile <input file path> -outputFile <output file path>")
+		os.Exit(1)
+	}
+
+	inputFileData := strings.TrimRight(readFileToString(*inputFile), "\n")
+	filePaths := strings.Split(inputFileData, " ")
+	if len(filePaths) == 1 && filePaths[0] == "" {
+		writeNewlineToOutputFile(*outputFile)
+		return
+	}
+	ownershipMetadataMap := &sync.Map{}
+	keyLocks := &keyToLocksMap{}
+	errCh := make(chan error, len(filePaths))
+	var wg sync.WaitGroup
+
+	switch *rule {
+	case "test_spec":
+		for _, filePath := range filePaths {
+			wg.Add(1)
+			go processTestSpecProtobuf(filePath, ownershipMetadataMap, keyLocks, errCh, &wg)
+		}
+
+		wg.Wait()
+		close(errCh)
+
+		for err := range errCh {
+			log.Fatal(err)
+		}
+
+		allKeys := getSortedKeys(ownershipMetadataMap)
+		var allMetadata []*test_spec_proto.TestSpec_OwnershipMetadata
+
+		for _, key := range allKeys {
+			value, _ := ownershipMetadataMap.Load(key)
+			metadataList := value.([]*test_spec_proto.TestSpec_OwnershipMetadata)
+			allMetadata = append(allMetadata, metadataList...)
+		}
+
+		writeOutput(*outputFile, allMetadata)
+		break
+	case "code_metadata":
+	default:
+		log.Fatalf("No specific processing implemented for rule '%s'.\n", *rule)
+	}
+}
diff --git a/tools/metadata/go.mod b/tools/metadata/go.mod
new file mode 100644
index 0000000..e9d04b1
--- /dev/null
+++ b/tools/metadata/go.mod
@@ -0,0 +1,7 @@
+module android/soong/tools/metadata
+
+require google.golang.org/protobuf v0.0.0
+
+replace google.golang.org/protobuf v0.0.0 => ../../../external/golang-protobuf
+
+go 1.18
\ No newline at end of file
diff --git a/tools/metadata/go.work b/tools/metadata/go.work
new file mode 100644
index 0000000..23875da
--- /dev/null
+++ b/tools/metadata/go.work
@@ -0,0 +1,10 @@
+go 1.18
+
+use (
+	.
+	../../../../external/golang-protobuf
+	../../../soong/testing/test_spec_proto
+
+)
+
+replace google.golang.org/protobuf v0.0.0 => ../../../../external/golang-protobuf
diff --git a/tools/metadata/testdata/emptyInputFile.txt b/tools/metadata/testdata/emptyInputFile.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/tools/metadata/testdata/emptyInputFile.txt
@@ -0,0 +1 @@
+
diff --git a/tools/metadata/testdata/expectedOutputFile.txt b/tools/metadata/testdata/expectedOutputFile.txt
new file mode 100644
index 0000000..b0d382f
--- /dev/null
+++ b/tools/metadata/testdata/expectedOutputFile.txt
@@ -0,0 +1,22 @@
+
+.
+java-test-module-name-one
+Android.bp12345
+.
+java-test-module-name-six
+Android.bp12346
+.
+java-test-module-name-six
+Aqwerty.bp12346
+.
+java-test-module-name-six
+Apoiuyt.bp12346
+.
+java-test-module-name-two
+Android.bp12345
+.
+java-test-module-name-two
+Asdfghj.bp12345
+.
+java-test-module-name-two
+Azxcvbn.bp12345
\ No newline at end of file
diff --git a/tools/metadata/testdata/file1.txt b/tools/metadata/testdata/file1.txt
new file mode 100644
index 0000000..81beed0
--- /dev/null
+++ b/tools/metadata/testdata/file1.txt
@@ -0,0 +1,13 @@
+
+.
+java-test-module-name-one
+Android.bp12345
+.
+java-test-module-name-two
+Android.bp12345
+.
+java-test-module-name-two
+Asdfghj.bp12345
+.
+java-test-module-name-two
+Azxcvbn.bp12345
diff --git a/tools/metadata/testdata/file2.txt b/tools/metadata/testdata/file2.txt
new file mode 100644
index 0000000..32a753f
--- /dev/null
+++ b/tools/metadata/testdata/file2.txt
@@ -0,0 +1,25 @@
+
+.
+java-test-module-name-one
+Android.bp12345
+.
+java-test-module-name-six
+Android.bp12346
+.
+java-test-module-name-one
+Android.bp12345
+.
+java-test-module-name-six
+Aqwerty.bp12346
+.
+java-test-module-name-six
+Apoiuyt.bp12346
+.
+java-test-module-name-six
+Apoiuyt.bp12346
+.
+java-test-module-name-six
+Apoiuyt.bp12346
+.
+java-test-module-name-six
+Apoiuyt.bp12346
diff --git a/tools/metadata/testdata/file3.txt b/tools/metadata/testdata/file3.txt
new file mode 100644
index 0000000..81beed0
--- /dev/null
+++ b/tools/metadata/testdata/file3.txt
@@ -0,0 +1,13 @@
+
+.
+java-test-module-name-one
+Android.bp12345
+.
+java-test-module-name-two
+Android.bp12345
+.
+java-test-module-name-two
+Asdfghj.bp12345
+.
+java-test-module-name-two
+Azxcvbn.bp12345
diff --git a/tools/metadata/testdata/file4.txt b/tools/metadata/testdata/file4.txt
new file mode 100644
index 0000000..6a75900
--- /dev/null
+++ b/tools/metadata/testdata/file4.txt
@@ -0,0 +1,25 @@
+
+.
+java-test-module-name-one
+Android.bp12345
+.
+java-test-module-name-six
+Android.bp12346
+.
+java-test-module-name-one
+Android.bp12346
+.
+java-test-module-name-six
+Aqwerty.bp12346
+.
+java-test-module-name-six
+Apoiuyt.bp12346
+.
+java-test-module-name-six
+Apoiuyt.bp12346
+.
+java-test-module-name-six
+Apoiuyt.bp12346
+.
+java-test-module-name-six
+Apoiuyt.bp12346
diff --git a/tools/metadata/testdata/generatedEmptyOutputFile.txt b/tools/metadata/testdata/generatedEmptyOutputFile.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/tools/metadata/testdata/generatedEmptyOutputFile.txt
@@ -0,0 +1 @@
+
diff --git a/tools/metadata/testdata/generatedOutputFile.txt b/tools/metadata/testdata/generatedOutputFile.txt
new file mode 100644
index 0000000..b0d382f
--- /dev/null
+++ b/tools/metadata/testdata/generatedOutputFile.txt
@@ -0,0 +1,22 @@
+
+.
+java-test-module-name-one
+Android.bp12345
+.
+java-test-module-name-six
+Android.bp12346
+.
+java-test-module-name-six
+Aqwerty.bp12346
+.
+java-test-module-name-six
+Apoiuyt.bp12346
+.
+java-test-module-name-two
+Android.bp12345
+.
+java-test-module-name-two
+Asdfghj.bp12345
+.
+java-test-module-name-two
+Azxcvbn.bp12345
\ No newline at end of file
diff --git a/tools/metadata/testdata/inputFiles.txt b/tools/metadata/testdata/inputFiles.txt
new file mode 100644
index 0000000..e44bc94
--- /dev/null
+++ b/tools/metadata/testdata/inputFiles.txt
@@ -0,0 +1 @@
+file1.txt file2.txt
\ No newline at end of file
diff --git a/tools/metadata/testdata/inputFilesNegativeCase.txt b/tools/metadata/testdata/inputFilesNegativeCase.txt
new file mode 100644
index 0000000..a37aa3f
--- /dev/null
+++ b/tools/metadata/testdata/inputFilesNegativeCase.txt
@@ -0,0 +1 @@
+file3.txt file4.txt
\ No newline at end of file
diff --git a/tools/metadata/testdata/metadata_test.go b/tools/metadata/testdata/metadata_test.go
new file mode 100644
index 0000000..71856fe
--- /dev/null
+++ b/tools/metadata/testdata/metadata_test.go
@@ -0,0 +1,89 @@
+package main
+
+import (
+	"fmt"
+	"io/ioutil"
+	"os/exec"
+	"strings"
+	"testing"
+)
+
+func TestMetadata(t *testing.T) {
+	cmd := exec.Command(
+		"metadata", "-rule", "test_spec", "-inputFile", "./inputFiles.txt", "-outputFile",
+		"./generatedOutputFile.txt",
+	)
+	stderr, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Fatalf("Error running metadata command: %s. Error: %v", stderr, err)
+	}
+
+	// Read the contents of the expected output file
+	expectedOutput, err := ioutil.ReadFile("./expectedOutputFile.txt")
+	if err != nil {
+		t.Fatalf("Error reading expected output file: %s", err)
+	}
+
+	// Read the contents of the generated output file
+	generatedOutput, err := ioutil.ReadFile("./generatedOutputFile.txt")
+	if err != nil {
+		t.Fatalf("Error reading generated output file: %s", err)
+	}
+
+	fmt.Println()
+
+	// Compare the contents
+	if string(expectedOutput) != string(generatedOutput) {
+		t.Errorf("Generated file contents do not match the expected output")
+	}
+}
+
+func TestMetadataNegativeCase(t *testing.T) {
+	cmd := exec.Command(
+		"metadata", "-rule", "test_spec", "-inputFile", "./inputFilesNegativeCase.txt", "-outputFile",
+		"./generatedOutputFileNegativeCase.txt",
+	)
+	stderr, err := cmd.CombinedOutput()
+	if err == nil {
+		t.Fatalf(
+			"Expected an error, but the metadata command executed successfully. Output: %s",
+			stderr,
+		)
+	}
+
+	expectedError := "Conflicting trendy team IDs found for java-test-module" +
+		"-name-one at:\nAndroid.bp with teamId: 12346," +
+		"\nAndroid.bp with teamId: 12345"
+	if !strings.Contains(
+		strings.TrimSpace(string(stderr)), strings.TrimSpace(expectedError),
+	) {
+		t.Errorf(
+			"Unexpected error message. Expected to contain: %s, Got: %s",
+			expectedError, stderr,
+		)
+	}
+}
+
+func TestEmptyInputFile(t *testing.T) {
+	cmd := exec.Command(
+		"metadata", "-rule", "test_spec", "-inputFile", "./emptyInputFile.txt", "-outputFile",
+		"./generatedEmptyOutputFile.txt",
+	)
+	stderr, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Fatalf("Error running metadata command: %s. Error: %v", stderr, err)
+	}
+
+	// Read the contents of the generated output file
+	generatedOutput, err := ioutil.ReadFile("./generatedEmptyOutputFile.txt")
+	if err != nil {
+		t.Fatalf("Error reading generated output file: %s", err)
+	}
+
+	fmt.Println()
+
+	// Compare the contents
+	if string(generatedOutput) != "\n" {
+		t.Errorf("Generated file contents do not match the expected output")
+	}
+}
diff --git a/tools/metadata/testdata/outputFile.txt b/tools/metadata/testdata/outputFile.txt
new file mode 100644
index 0000000..b0d382f
--- /dev/null
+++ b/tools/metadata/testdata/outputFile.txt
@@ -0,0 +1,22 @@
+
+.
+java-test-module-name-one
+Android.bp12345
+.
+java-test-module-name-six
+Android.bp12346
+.
+java-test-module-name-six
+Aqwerty.bp12346
+.
+java-test-module-name-six
+Apoiuyt.bp12346
+.
+java-test-module-name-two
+Android.bp12345
+.
+java-test-module-name-two
+Asdfghj.bp12345
+.
+java-test-module-name-two
+Azxcvbn.bp12345
\ No newline at end of file
diff --git a/tools/post_process_props.py b/tools/post_process_props.py
index 31a460d..32829c1 100755
--- a/tools/post_process_props.py
+++ b/tools/post_process_props.py
@@ -39,54 +39,26 @@
         val = val + ",adb"
       prop_list.put("persist.sys.usb.config", val)
 
-def validate_grf_props(prop_list, sdk_version):
+def validate_grf_props(prop_list):
   """Validate GRF properties if exist.
 
-  If ro.board.first_api_level is defined, check if its value is valid for the
-  sdk version. This is only for the release version.
-  Also, validate the value of ro.board.api_level if defined.
+  If ro.board.first_api_level is defined, check if its value is valid.
 
   Returns:
     True if the GRF properties are valid.
   """
   grf_api_level = prop_list.get_value("ro.board.first_api_level")
   board_api_level = prop_list.get_value("ro.board.api_level")
-  platform_version_codename = prop_list.get_value("ro.build.version.codename")
 
-  if not grf_api_level:
-    if board_api_level:
-      sys.stderr.write("error: non-GRF device must not define "
-                       "ro.board.api_level\n")
-      return False
-    # non-GRF device skips the GRF validation test
-    return True
-
-  grf_api_level = int(grf_api_level)
-  if board_api_level:
+  if grf_api_level and board_api_level:
+    grf_api_level = int(grf_api_level)
     board_api_level = int(board_api_level)
     if board_api_level < grf_api_level:
-      sys.stderr.write("error: ro.board.api_level(%d) must be greater than "
+      sys.stderr.write("error: ro.board.api_level(%d) must not be less than "
                        "ro.board.first_api_level(%d)\n"
                        % (board_api_level, grf_api_level))
       return False
 
-  # skip sdk version validation for dev-stage non-REL devices
-  if platform_version_codename != "REL":
-    return True
-
-  if grf_api_level > sdk_version:
-    sys.stderr.write("error: ro.board.first_api_level(%d) must be less than "
-                     "or equal to ro.build.version.sdk(%d)\n"
-                     % (grf_api_level, sdk_version))
-    return False
-
-  if board_api_level:
-    if board_api_level > sdk_version:
-      sys.stderr.write("error: ro.board.api_level(%d) must be less than or "
-                       "equal to ro.build.version.sdk(%d)\n"
-                       % (board_api_level, sdk_version))
-      return False
-
   return True
 
 def validate(prop_list):
@@ -271,7 +243,7 @@
   mangle_build_prop(props)
   if not override_optional_props(props, args.allow_dup):
     sys.exit(1)
-  if not validate_grf_props(props, args.sdk_version):
+  if not validate_grf_props(props):
     sys.exit(1)
   if not validate(props):
     sys.exit(1)
diff --git a/tools/rbcrun/host.go b/tools/rbcrun/host.go
index 1d68d43..8cd2845 100644
--- a/tools/rbcrun/host.go
+++ b/tools/rbcrun/host.go
@@ -24,18 +24,17 @@
 	"strings"
 
 	"go.starlark.net/starlark"
-	"go.starlark.net/starlarkjson"
 	"go.starlark.net/starlarkstruct"
 )
 
 type ExecutionMode int
 const (
 	ExecutionModeRbc ExecutionMode = iota
-	ExecutionModeMake ExecutionMode = iota
+	ExecutionModeScl ExecutionMode = iota
 )
 
 const allowExternalEntrypointKey = "allowExternalEntrypoint"
-const callerDirKey = "callerDir"
+const callingFileKey = "callingFile"
 const executionModeKey = "executionMode"
 const shellKey = "shell"
 
@@ -58,9 +57,16 @@
 	"rblf_wildcard": starlark.NewBuiltin("rblf_wildcard", wildcard),
 }
 
-var makeBuiltins starlark.StringDict = starlark.StringDict{
+var sclBuiltins starlark.StringDict = starlark.StringDict{
 	"struct":   starlark.NewBuiltin("struct", starlarkstruct.Make),
-	"json": starlarkjson.Module,
+}
+
+func isSymlink(filepath string) (bool, error) {
+	if info, err := os.Lstat(filepath); err == nil {
+		return info.Mode() & os.ModeSymlink != 0, nil
+	} else {
+		return false, err
+	}
 }
 
 // Takes a module name (the first argument to the load() function) and returns the path
@@ -128,7 +134,8 @@
 			module = module[:pipePos]
 		}
 	}
-	modulePath, err := cleanModuleName(module, thread.Local(callerDirKey).(string), allowExternalEntrypoint)
+	callingFile := thread.Local(callingFileKey).(string)
+	modulePath, err := cleanModuleName(module, filepath.Dir(callingFile), allowExternalEntrypoint)
 	if err != nil {
 		return nil, err
 	}
@@ -150,6 +157,20 @@
 
 		// Load or return default
 		if mustLoad {
+			if strings.HasSuffix(callingFile, ".scl") && !strings.HasSuffix(modulePath, ".scl") {
+				return nil, fmt.Errorf(".scl files can only load other .scl files: %q loads %q", callingFile, modulePath)
+			}
+			// Switch into scl mode from here on
+			if strings.HasSuffix(modulePath, ".scl") {
+				mode = ExecutionModeScl
+			}
+
+			if sym, err := isSymlink(modulePath); sym && err == nil {
+				return nil, fmt.Errorf("symlinks to starlark files are not allowed. Instead, load the target file and re-export its symbols: %s", modulePath)
+			} else if err != nil {
+				return nil, err
+			}
+
 			childThread := &starlark.Thread{Name: "exec " + module, Load: thread.Load}
 			// Cheating for the sake of testing:
 			// propagate starlarktest's Reporter key, otherwise testing
@@ -161,14 +182,14 @@
 
 			// Only the entrypoint starlark file allows external loads.
 			childThread.SetLocal(allowExternalEntrypointKey, false)
-			childThread.SetLocal(callerDirKey, filepath.Dir(modulePath))
+			childThread.SetLocal(callingFileKey, modulePath)
 			childThread.SetLocal(executionModeKey, mode)
 			childThread.SetLocal(shellKey, thread.Local(shellKey))
 			if mode == ExecutionModeRbc {
 				globals, err := starlark.ExecFile(childThread, modulePath, nil, rbcBuiltins)
 				e = &modentry{globals, err}
-			} else if mode == ExecutionModeMake {
-				globals, err := starlark.ExecFile(childThread, modulePath, nil, makeBuiltins)
+			} else if mode == ExecutionModeScl {
+				globals, err := starlark.ExecFile(childThread, modulePath, nil, sclBuiltins)
 				e = &modentry{globals, err}
 			} else {
 				return nil, fmt.Errorf("unknown executionMode %d", mode)
@@ -338,7 +359,7 @@
 			if mode == ExecutionModeRbc {
 				// In rbc mode, rblf_log is used to print to stderr
 				fmt.Println(msg)
-			} else if mode == ExecutionModeMake {
+			} else if mode == ExecutionModeScl {
 				fmt.Fprintln(os.Stderr, msg)
 			}
 		},
@@ -360,18 +381,28 @@
 		return nil, nil, err
 	}
 
+	if sym, err := isSymlink(filename); sym && err == nil {
+		return nil, nil, fmt.Errorf("symlinks to starlark files are not allowed. Instead, load the target file and re-export its symbols: %s", filename)
+	} else if err != nil {
+		return nil, nil, err
+	}
+
+	if mode == ExecutionModeScl && !strings.HasSuffix(filename, ".scl") {
+		return nil, nil, fmt.Errorf("filename must end in .scl: %s", filename)
+	}
+
 	// Add top-level file to cache for cycle detection purposes
 	moduleCache[filename] = nil
 
 	var results starlark.StringDict
 	mainThread.SetLocal(allowExternalEntrypointKey, allowExternalEntrypoint)
-	mainThread.SetLocal(callerDirKey, filepath.Dir(filename))
+	mainThread.SetLocal(callingFileKey, filename)
 	mainThread.SetLocal(executionModeKey, mode)
 	mainThread.SetLocal(shellKey, shellPath)
 	if mode == ExecutionModeRbc {
 		results, err = starlark.ExecFile(mainThread, filename, src, rbcBuiltins)
-	} else if mode == ExecutionModeMake {
-		results, err = starlark.ExecFile(mainThread, filename, src, makeBuiltins)
+	} else if mode == ExecutionModeScl {
+		results, err = starlark.ExecFile(mainThread, filename, src, sclBuiltins)
 	} else {
 		return results, nil, fmt.Errorf("unknown executionMode %d", mode)
 	}
diff --git a/tools/rbcrun/host_test.go b/tools/rbcrun/host_test.go
index 10ce55e..38b2923 100644
--- a/tools/rbcrun/host_test.go
+++ b/tools/rbcrun/host_test.go
@@ -19,6 +19,7 @@
 	"os"
 	"path/filepath"
 	"runtime"
+	"strings"
 	"testing"
 
 	"go.starlark.net/resolve"
@@ -126,7 +127,7 @@
 		t.Fatal(err)
 	}
 	thread.SetLocal(allowExternalEntrypointKey, false)
-	thread.SetLocal(callerDirKey, dir)
+	thread.SetLocal(callingFileKey, "testdata/load.star")
 	thread.SetLocal(executionModeKey, ExecutionModeRbc)
 	if _, err := starlark.ExecFile(thread, "testdata/load.star", nil, rbcBuiltins); err != nil {
 		if err, ok := err.(*starlark.EvalError); ok {
@@ -136,6 +137,70 @@
 	}
 }
 
+func TestBzlLoadsScl(t *testing.T) {
+	moduleCache = make(map[string]*modentry)
+	dir := dataDir()
+	if err := os.Chdir(filepath.Dir(dir)); err != nil {
+		t.Fatal(err)
+	}
+	vars, _, err := Run("testdata/bzl_loads_scl.bzl", nil, ExecutionModeRbc, false)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if val, ok := vars["foo"]; !ok {
+		t.Fatalf("Failed to load foo variable")
+	} else if val.(starlark.String) != "bar" {
+		t.Fatalf("Expected \"bar\", got %q", val)
+	}
+}
+
+func TestNonEntrypointBzlLoadsScl(t *testing.T) {
+	moduleCache = make(map[string]*modentry)
+	dir := dataDir()
+	if err := os.Chdir(filepath.Dir(dir)); err != nil {
+		t.Fatal(err)
+	}
+	vars, _, err := Run("testdata/bzl_loads_scl_2.bzl", nil, ExecutionModeRbc, false)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if val, ok := vars["foo"]; !ok {
+		t.Fatalf("Failed to load foo variable")
+	} else if val.(starlark.String) != "bar" {
+		t.Fatalf("Expected \"bar\", got %q", val)
+	}
+}
+
+func TestSclLoadsBzl(t *testing.T) {
+	moduleCache = make(map[string]*modentry)
+	dir := dataDir()
+	if err := os.Chdir(filepath.Dir(dir)); err != nil {
+		t.Fatal(err)
+	}
+	_, _, err := Run("testdata/scl_incorrectly_loads_bzl.scl", nil, ExecutionModeScl, false)
+	if err == nil {
+		t.Fatal("Expected failure")
+	}
+	if !strings.Contains(err.Error(), ".scl files can only load other .scl files") {
+		t.Fatalf("Expected error to contain \".scl files can only load other .scl files\": %q", err.Error())
+	}
+}
+
+func TestCantLoadSymlink(t *testing.T) {
+	moduleCache = make(map[string]*modentry)
+	dir := dataDir()
+	if err := os.Chdir(filepath.Dir(dir)); err != nil {
+		t.Fatal(err)
+	}
+	_, _, err := Run("testdata/test_scl_symlink.scl", nil, ExecutionModeScl, false)
+	if err == nil {
+		t.Fatal("Expected failure")
+	}
+	if !strings.Contains(err.Error(), "symlinks to starlark files are not allowed") {
+		t.Fatalf("Expected error to contain \"symlinks to starlark files are not allowed\": %q", err.Error())
+	}
+}
+
 func TestShell(t *testing.T) {
 	exerciseStarlarkTestFile(t, "testdata/shell.star")
 }
diff --git a/tools/rbcrun/rbcrun/rbcrun.go b/tools/rbcrun/rbcrun/rbcrun.go
index a15b867..8c372c7 100644
--- a/tools/rbcrun/rbcrun/rbcrun.go
+++ b/tools/rbcrun/rbcrun/rbcrun.go
@@ -55,13 +55,13 @@
 	case "rbc":
 		return rbcrun.ExecutionModeRbc
 	case "make":
-		return rbcrun.ExecutionModeMake
+		return rbcrun.ExecutionModeScl
 	case "":
 		quit("-mode flag is required.")
 	default:
 		quit("Unknown -mode value %q, expected 1 of \"rbc\", \"make\"", *modeFlag)
 	}
-	return rbcrun.ExecutionModeMake
+	return rbcrun.ExecutionModeScl
 }
 
 var makeStringReplacer = strings.NewReplacer("#", "\\#", "$", "$$")
@@ -175,7 +175,7 @@
 			quit("%s\n", err)
 		}
 	}
-	if mode == rbcrun.ExecutionModeMake {
+	if mode == rbcrun.ExecutionModeScl {
 		if err := printVarsInMakeFormat(variables); err != nil {
 			quit("%s\n", err)
 		}
diff --git a/tools/rbcrun/testdata/bzl_loads_scl.bzl b/tools/rbcrun/testdata/bzl_loads_scl.bzl
new file mode 100644
index 0000000..e8deca3
--- /dev/null
+++ b/tools/rbcrun/testdata/bzl_loads_scl.bzl
@@ -0,0 +1,3 @@
+load(":test_scl.scl", _foo = "foo")
+
+foo = _foo
diff --git a/tools/rbcrun/testdata/bzl_loads_scl_2.bzl b/tools/rbcrun/testdata/bzl_loads_scl_2.bzl
new file mode 100644
index 0000000..9a680ed
--- /dev/null
+++ b/tools/rbcrun/testdata/bzl_loads_scl_2.bzl
@@ -0,0 +1,3 @@
+load(":bzl_loads_scl.bzl", _foo = "foo")
+
+foo = _foo
diff --git a/tools/rbcrun/testdata/scl_incorrectly_loads_bzl.scl b/tools/rbcrun/testdata/scl_incorrectly_loads_bzl.scl
new file mode 100644
index 0000000..9a680ed
--- /dev/null
+++ b/tools/rbcrun/testdata/scl_incorrectly_loads_bzl.scl
@@ -0,0 +1,3 @@
+load(":bzl_loads_scl.bzl", _foo = "foo")
+
+foo = _foo
diff --git a/tools/rbcrun/testdata/test_scl.scl b/tools/rbcrun/testdata/test_scl.scl
new file mode 100644
index 0000000..6360ccb
--- /dev/null
+++ b/tools/rbcrun/testdata/test_scl.scl
@@ -0,0 +1,2 @@
+
+foo = "bar"
diff --git a/tools/rbcrun/testdata/test_scl_symlink.scl b/tools/rbcrun/testdata/test_scl_symlink.scl
new file mode 120000
index 0000000..3f5aef4
--- /dev/null
+++ b/tools/rbcrun/testdata/test_scl_symlink.scl
@@ -0,0 +1 @@
+test_scl.scl
\ No newline at end of file
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 843d8ca..8ce6083 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -39,18 +39,23 @@
 import threading
 import time
 import zipfile
+
+from typing import Iterable, Callable
 from dataclasses import dataclass
-from genericpath import isdir
 from hashlib import sha1, sha256
 
 import images
-import rangelib
 import sparse_img
 from blockimgdiff import BlockImageDiff
 
 logger = logging.getLogger(__name__)
 
 
+@dataclass
+class OptionHandler:
+  extra_long_opts: Iterable[str]
+  handler: Callable
+
 class Options(object):
 
   def __init__(self):
@@ -1235,26 +1240,16 @@
   system_root_image = info_dict.get('system_root_image') == 'true'
   if info_dict.get('no_recovery') != 'true':
     recovery_fstab_path = 'RECOVERY/RAMDISK/system/etc/recovery.fstab'
-    if isinstance(input_file, zipfile.ZipFile):
-      if recovery_fstab_path not in input_file.namelist():
-        recovery_fstab_path = 'RECOVERY/RAMDISK/etc/recovery.fstab'
-    else:
-      path = os.path.join(input_file, *recovery_fstab_path.split('/'))
-      if not os.path.exists(path):
-        recovery_fstab_path = 'RECOVERY/RAMDISK/etc/recovery.fstab'
+    if not DoesInputFileContain(input_file, recovery_fstab_path):
+      recovery_fstab_path = 'RECOVERY/RAMDISK/etc/recovery.fstab'
     return LoadRecoveryFSTab(
         read_helper, info_dict['fstab_version'], recovery_fstab_path,
         system_root_image)
 
   if info_dict.get('recovery_as_boot') == 'true':
     recovery_fstab_path = 'BOOT/RAMDISK/system/etc/recovery.fstab'
-    if isinstance(input_file, zipfile.ZipFile):
-      if recovery_fstab_path not in input_file.namelist():
-        recovery_fstab_path = 'BOOT/RAMDISK/etc/recovery.fstab'
-    else:
-      path = os.path.join(input_file, *recovery_fstab_path.split('/'))
-      if not os.path.exists(path):
-        recovery_fstab_path = 'BOOT/RAMDISK/etc/recovery.fstab'
+    if not DoesInputFileContain(input_file, recovery_fstab_path):
+      recovery_fstab_path = 'BOOT/RAMDISK/etc/recovery.fstab'
     return LoadRecoveryFSTab(
         read_helper, info_dict['fstab_version'], recovery_fstab_path,
         system_root_image)
@@ -1953,8 +1948,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():
@@ -2661,7 +2659,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
 
@@ -2798,12 +2798,19 @@
 def ParseOptions(argv,
                  docstring,
                  extra_opts="", extra_long_opts=(),
-                 extra_option_handler=None):
+                 extra_option_handler: Iterable[OptionHandler] = None):
   """Parse the options in argv and return any arguments that aren't
   flags.  docstring is the calling module's docstring, to be displayed
   for errors and -h.  extra_opts and extra_long_opts are for flags
   defined by the caller, which are processed by passing them to
   extra_option_handler."""
+  extra_long_opts = list(extra_long_opts)
+  if not isinstance(extra_option_handler, Iterable):
+    extra_option_handler = [extra_option_handler]
+
+  for handler in extra_option_handler:
+    if isinstance(handler, OptionHandler):
+      extra_long_opts.extend(handler.extra_long_opts)
 
   try:
     opts, args = getopt.getopt(
@@ -2865,8 +2872,19 @@
     elif o in ("--logfile",):
       OPTIONS.logfile = a
     else:
-      if extra_option_handler is None or not extra_option_handler(o, a):
-        assert False, "unknown option \"%s\"" % (o,)
+      if extra_option_handler is None:
+        raise ValueError("unknown option \"%s\"" % (o,))
+      success = False
+      for handler in extra_option_handler:
+        if isinstance(handler, OptionHandler):
+          if handler.handler(o, a):
+            success = True
+            break
+        elif handler(o, a):
+          success = True
+      if not success:
+        raise ValueError("unknown option \"%s\"" % (o,))
+
 
   if OPTIONS.search_path:
     os.environ["PATH"] = (os.path.join(OPTIONS.search_path, "bin") +
diff --git a/tools/releasetools/merge/merge_target_files.py b/tools/releasetools/merge/merge_target_files.py
index 6bf1b49..4619246 100755
--- a/tools/releasetools/merge/merge_target_files.py
+++ b/tools/releasetools/merge/merge_target_files.py
@@ -46,6 +46,10 @@
       The optional path to a newline-separated config file of items that
       are extracted as-is from the vendor target files package.
 
+  --boot-image-dir-path
+      The input boot image directory path. This path contains IMAGES/boot.img
+      file.
+
   --output-target-files output-target-files-package
       If provided, the output merged target files package. Also a zip archive.
 
@@ -136,6 +140,7 @@
 OPTIONS.framework_misc_info_keys = []
 OPTIONS.vendor_target_files = None
 OPTIONS.vendor_item_list = []
+OPTIONS.boot_image_dir_path = None
 OPTIONS.output_target_files = None
 OPTIONS.output_dir = None
 OPTIONS.output_item_list = []
@@ -210,6 +215,12 @@
       output_dir=output_target_files_temp_dir,
       item_list=OPTIONS.vendor_item_list)
 
+  if OPTIONS.boot_image_dir_path:
+    merge_utils.CollectTargetFiles(
+        input_zipfile_or_dir=OPTIONS.boot_image_dir_path,
+        output_dir=output_target_files_temp_dir,
+        item_list=['IMAGES/boot.img'])
+
   # Perform special case processing on META/* items.
   # After this function completes successfully, all the files we need to create
   # the output target files package are in place.
@@ -539,6 +550,8 @@
       OPTIONS.vendor_item_list = a
     elif o == '--vendor-item-list':
       OPTIONS.vendor_item_list = a
+    elif o == '--boot-image-dir-path':
+      OPTIONS.boot_image_dir_path = a
     elif o == '--output-target-files':
       OPTIONS.output_target_files = a
     elif o == '--output-dir':
@@ -587,6 +600,7 @@
           'vendor-target-files=',
           'other-item-list=',
           'vendor-item-list=',
+          'boot-image-dir-path=',
           'output-target-files=',
           'output-dir=',
           'output-item-list=',
diff --git a/tools/releasetools/ota_from_raw_img.py b/tools/releasetools/ota_from_raw_img.py
index 0c1c05a..c186940 100644
--- a/tools/releasetools/ota_from_raw_img.py
+++ b/tools/releasetools/ota_from_raw_img.py
@@ -68,6 +68,11 @@
   if args.verbose:
     logger.setLevel(logging.INFO)
   logger.info(args)
+  old_imgs = [""] * len(args.images)
+  for (i, img) in enumerate(args.images):
+    if ":" in img:
+      old_imgs[i], args.images[i] = img.split(":", maxsplit=1)
+
   if not args.partition_names:
     args.partition_names = [os.path.os.path.splitext(os.path.basename(path))[
         0] for path in args.images]
@@ -79,6 +84,7 @@
     cmd.append("--partition_names=" + ",".join(args.partition_names))
     cmd.append("--dynamic_partition_info_file=" +
                dynamic_partition_info_file.name)
+    cmd.append("--old_partitions=" + ",".join(old_imgs))
     cmd.append("--new_partitions=" + ",".join(args.images))
     cmd.append("--out_file=" + unsigned_payload.name)
     cmd.append("--is_partial_update")
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index de0e187..fa4ed09 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -265,7 +265,6 @@
 import os
 import os.path
 import re
-import shlex
 import shutil
 import subprocess
 import sys
@@ -274,6 +273,7 @@
 import care_map_pb2
 import common
 import ota_utils
+import payload_signer
 from ota_utils import (VABC_COMPRESSION_PARAM_SUPPORT, FinalizeMetadata, GetPackageMetadata,
                        PayloadGenerator, SECURITY_PATCH_LEVEL_PROP_NAME, ExtractTargetFiles, CopyTargetFilesDir)
 from common import DoesInputFileContain, IsSparseImage
@@ -308,9 +308,6 @@
 OPTIONS.cache_size = None
 OPTIONS.stash_threshold = 0.8
 OPTIONS.log_diff = None
-OPTIONS.payload_signer = None
-OPTIONS.payload_signer_args = []
-OPTIONS.payload_signer_maximum_signature_size = None
 OPTIONS.extracted_input = None
 OPTIONS.skip_postinstall = False
 OPTIONS.skip_compatibility_check = False
@@ -1125,9 +1122,7 @@
 def main(argv):
 
   def option_handler(o, a):
-    if o in ("-k", "--package_key"):
-      OPTIONS.package_key = a
-    elif o in ("-i", "--incremental_from"):
+    if o in ("-i", "--incremental_from"):
       OPTIONS.incremental_source = a
     elif o == "--full_radio":
       OPTIONS.full_radio = True
@@ -1172,17 +1167,6 @@
                          "a float" % (a, o))
     elif o == "--log_diff":
       OPTIONS.log_diff = a
-    elif o == "--payload_signer":
-      OPTIONS.payload_signer = a
-    elif o == "--payload_signer_args":
-      OPTIONS.payload_signer_args = shlex.split(a)
-    elif o == "--payload_signer_maximum_signature_size":
-      OPTIONS.payload_signer_maximum_signature_size = a
-    elif o == "--payload_signer_key_size":
-      # TODO(Xunchang) remove this option after cleaning up the callers.
-      logger.warning("The option '--payload_signer_key_size' is deprecated."
-                     " Use '--payload_signer_maximum_signature_size' instead.")
-      OPTIONS.payload_signer_maximum_signature_size = a
     elif o == "--extracted_input_target_files":
       OPTIONS.extracted_input = a
     elif o == "--skip_postinstall":
@@ -1258,7 +1242,6 @@
   args = common.ParseOptions(argv, __doc__,
                              extra_opts="b:k:i:d:e:t:2o:",
                              extra_long_opts=[
-                                 "package_key=",
                                  "incremental_from=",
                                  "full_radio",
                                  "full_bootloader",
@@ -1277,10 +1260,6 @@
                                  "verify",
                                  "stash_threshold=",
                                  "log_diff=",
-                                 "payload_signer=",
-                                 "payload_signer_args=",
-                                 "payload_signer_maximum_signature_size=",
-                                 "payload_signer_key_size=",
                                  "extracted_input_target_files=",
                                  "skip_postinstall",
                                  "retrofit_dynamic_partitions",
@@ -1304,7 +1283,7 @@
                                  "vabc_compression_param=",
                                  "security_patch_level=",
                                  "max_threads=",
-                             ], extra_option_handler=option_handler)
+                             ], extra_option_handler=[option_handler, payload_signer.signer_options])
   common.InitLogging()
 
   if len(args) != 2:
diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py
index 6ca9d64..0a6ff39 100644
--- a/tools/releasetools/ota_utils.py
+++ b/tools/releasetools/ota_utils.py
@@ -37,7 +37,6 @@
 OPTIONS.wipe_user_data = False
 OPTIONS.downgrade = False
 OPTIONS.key_passwords = {}
-OPTIONS.package_key = None
 OPTIONS.incremental_source = None
 OPTIONS.retrofit_dynamic_partitions = False
 OPTIONS.output_metadata_path = None
diff --git a/tools/releasetools/payload_signer.py b/tools/releasetools/payload_signer.py
index bbd2896..a5d09e1 100644
--- a/tools/releasetools/payload_signer.py
+++ b/tools/releasetools/payload_signer.py
@@ -16,10 +16,51 @@
 
 import common
 import logging
-from common import OPTIONS
+import shlex
+from common import OPTIONS, OptionHandler
 
 logger = logging.getLogger(__name__)
 
+OPTIONS.payload_signer = None
+OPTIONS.payload_signer_args = []
+OPTIONS.payload_signer_maximum_signature_size = None
+OPTIONS.package_key = None
+
+
+class SignerOptions(OptionHandler):
+
+  @staticmethod
+  def ParseOptions(o, a):
+    if o in ("-k", "--package_key"):
+      OPTIONS.package_key = a
+    elif o == "--payload_signer":
+      OPTIONS.payload_signer = a
+    elif o == "--payload_signer_args":
+      OPTIONS.payload_signer_args = shlex.split(a)
+    elif o == "--payload_signer_maximum_signature_size":
+      OPTIONS.payload_signer_maximum_signature_size = a
+    elif o == "--payload_signer_key_size":
+      # TODO(xunchang) remove this option after cleaning up the callers.
+      logger.warning("The option '--payload_signer_key_size' is deprecated."
+                      " Use '--payload_signer_maximum_signature_size' instead.")
+      OPTIONS.payload_signer_maximum_signature_size = a
+    else:
+      return False
+    return True
+
+  def __init__(self):
+    super().__init__(
+      ["payload_signer=",
+       "package_key=",
+       "payload_signer_args=",
+       "payload_signer_maximum_signature_size=",
+       "payload_signer_key_size="],
+       SignerOptions.ParseOptions
+    )
+
+
+signer_options = SignerOptions()
+
 
 class PayloadSigner(object):
   """A class that wraps the payload signing works.
diff --git a/tools/sbom/Android.bp b/tools/sbom/Android.bp
index 27a160e..2b2b573 100644
--- a/tools/sbom/Android.bp
+++ b/tools/sbom/Android.bp
@@ -80,15 +80,15 @@
 
 python_binary_host {
     name: "generate-sbom-framework_res",
-        srcs: [
-            "generate-sbom-framework_res.py",
-        ],
-        version: {
-            py3: {
-                embedded_launcher: true,
-            },
+    srcs: [
+        "generate-sbom-framework_res.py",
+    ],
+    version: {
+        py3: {
+            embedded_launcher: true,
         },
-        libs: [
-            "sbom_lib",
-        ],
+    },
+    libs: [
+        "sbom_lib",
+    ],
 }
\ No newline at end of file
diff --git a/tools/sbom/generate-sbom-framework_res.py b/tools/sbom/generate-sbom-framework_res.py
index d6be734..e637d53 100644
--- a/tools/sbom/generate-sbom-framework_res.py
+++ b/tools/sbom/generate-sbom-framework_res.py
@@ -20,6 +20,13 @@
 import sbom_data
 import sbom_writers
 
+'''
+This script generates SBOM of framework_res.jar of layoutlib shipped with Android Studio.
+
+The generated SBOM contains some placeholders which should be substituted by release_layoutlib.sh.
+The placeholders include: document name, document namespace, organization, created timestamp and 
+the SHA1 checksum of framework_res.jar.
+'''
 
 def get_args():
   parser = argparse.ArgumentParser()
diff --git a/tools/sbom/generate-sbom.py b/tools/sbom/generate-sbom.py
index a2b33b5..5eae262 100755
--- a/tools/sbom/generate-sbom.py
+++ b/tools/sbom/generate-sbom.py
@@ -130,6 +130,7 @@
   parser.add_argument('--metadata', required=True, help='The SBOM metadata file path.')
   parser.add_argument('--build_version', required=True, help='The build version.')
   parser.add_argument('--product_mfr', required=True, help='The product manufacturer.')
+  parser.add_argument('--module_name', help='The module name. If specified, the generated SBOM is for the module.')
   parser.add_argument('--json', action='store_true', default=False, help='Generated SBOM file in SPDX JSON format')
   parser.add_argument('--unbundled_apk', action='store_true', default=False, help='Generate SBOM for unbundled APKs')
   parser.add_argument('--unbundled_apex', action='store_true', default=False, help='Generate SBOM for unbundled APEXs')
@@ -483,16 +484,25 @@
   global metadata_file_protos
   metadata_file_protos = {}
 
-  product_package = sbom_data.Package(id=sbom_data.SPDXID_PRODUCT,
-                                      name=sbom_data.PACKAGE_NAME_PRODUCT,
+  product_package_id = sbom_data.SPDXID_PRODUCT
+  product_package_name = sbom_data.PACKAGE_NAME_PRODUCT
+  if args.module_name:
+    # Build SBOM of a module so use the module name instead.
+    product_package_id = f'SPDXRef-{sbom_data.encode_for_spdxid(args.module_name)}'
+    product_package_name = args.module_name
+  product_package = sbom_data.Package(id=product_package_id,
+                                      name=product_package_name,
                                       download_location=sbom_data.VALUE_NONE,
                                       version=args.build_version,
                                       supplier='Organization: ' + args.product_mfr,
                                       files_analyzed=True)
-
-  doc = sbom_data.Document(name=args.build_version,
-                           namespace=f'https://www.google.com/sbom/spdx/android/{args.build_version}',
-                           creators=['Organization: ' + args.product_mfr])
+  doc_name = args.build_version
+  if args.module_name:
+    doc_name = f'{args.build_version}/{args.module_name}'
+  doc = sbom_data.Document(name=doc_name,
+                           namespace=f'https://www.google.com/sbom/spdx/android/{doc_name}',
+                           creators=['Organization: ' + args.product_mfr],
+                           describes=product_package_id)
   if not args.unbundled_apex:
     doc.packages.append(product_package)
 
diff --git a/tools/test_post_process_props.py b/tools/test_post_process_props.py
index 439fc9f..2addefc 100644
--- a/tools/test_post_process_props.py
+++ b/tools/test_post_process_props.py
@@ -255,29 +255,17 @@
     stderr_redirect = io.StringIO()
     with contextlib.redirect_stderr(stderr_redirect):
       props = PropList("hello")
-      props.put("ro.board.first_api_level","25")
+      props.put("ro.board.first_api_level","202504")
       props.put("ro.build.version.codename", "REL")
 
-      # ro.board.first_api_level must be less than or equal to the sdk version
-      self.assertFalse(validate_grf_props(props, 20))
-      self.assertTrue(validate_grf_props(props, 26))
-      self.assertTrue(validate_grf_props(props, 35))
-
       # manually set ro.board.api_level to an invalid value
-      props.put("ro.board.api_level","20")
-      self.assertFalse(validate_grf_props(props, 26))
+      props.put("ro.board.api_level","202404")
+      self.assertFalse(validate_grf_props(props))
 
       props.get_all_props()[-1].make_as_comment()
       # manually set ro.board.api_level to a valid value
-      props.put("ro.board.api_level","26")
-      self.assertTrue(validate_grf_props(props, 26))
-      # ro.board.api_level must be less than or equal to the sdk version
-      self.assertFalse(validate_grf_props(props, 25))
-
-      # allow setting future api_level before release
-      props.get_all_props()[-2].make_as_comment()
-      props.put("ro.build.version.codename", "NonRel")
-      self.assertTrue(validate_grf_props(props, 24))
+      props.put("ro.board.api_level","202504")
+      self.assertTrue(validate_grf_props(props))
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)