Merge "Switch to static_rlibs" into main
diff --git a/core/Makefile b/core/Makefile
index cdb8423..61b4cb6 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -1375,30 +1375,7 @@
 	@echo "make $@: ignoring dependencies"
 	$(foreach b,$(INSTALLED_BOOTIMAGE_TARGET),$(call build_boot_board_avb_enabled,$(b)))
 
-else ifeq (true,$(PRODUCT_SUPPORTS_VBOOT)) # BOARD_AVB_ENABLE != true
-
-# $1: boot image target
-define build_boot_supports_vboot
-  $(MKBOOTIMG) --kernel $(call bootimage-to-kernel,$(1)) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1).unsigned
-  $(VBOOT_SIGNER) $(FUTILITY) $(1).unsigned $(PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(1).keyblock $(1)
-  $(call assert-max-image-size,$(1),$(call get-bootimage-partition-size,$(1),boot))
-endef
-
-$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(VBOOT_SIGNER) $(FUTILITY)
-	$(call pretty,"Target boot image: $@")
-	$(call build_boot_supports_vboot,$@)
-
-$(call declare-container-license-metadata,$(INSTALLED_BOOTIMAGE_TARGET),SPDX-license-identifier-GPL-2.0-only SPDX-license-identifier-Apache-2.0,restricted notice,$(BUILD_SYSTEM)/LINUX_KERNEL_COPYING build/soong/licenses/LICENSE,"Boot Image",boot)
-$(call declare-container-license-deps,$(INSTALLED_BOOTIMAGE_TARGET),$(INTERNAL_BOOTIMAGE_FILES),$(PRODUCT_OUT)/:/)
-
-UNMOUNTED_NOTICE_VENDOR_DEPS += $(INSTALLED_BOOTIMAGE_TARGET)
-
-.PHONY: bootimage-nodeps
-bootimage-nodeps: $(MKBOOTIMG) $(VBOOT_SIGNER) $(FUTILITY)
-	@echo "make $@: ignoring dependencies"
-	$(foreach b,$(INSTALLED_BOOTIMAGE_TARGET),$(call build_boot_supports_vboot,$(b)))
-
-else # PRODUCT_SUPPORTS_VBOOT != true
+else # BOARD_AVB_ENABLE != true
 
 # $1: boot image target
 define build_boot_novboot
@@ -1697,6 +1674,30 @@
 $(call declare-1p-container,$(INSTALLED_VENDOR_BOOTIMAGE_TARGET),)
 $(call declare-container-license-deps,$(INSTALLED_VENDOR_BOOTIMAGE_TARGET),$(INTERNAL_VENDOR_RAMDISK_TARGET) $(INSTALLED_DTB_IMAGE_TARGET) $(INTERNAL_VENDOR_RAMDISK_FRAGMENT_TARGETS) $(INTERNAL_VENDOR_BOOTCONDIG_TARGET),$(PRODUCT_OUT)/:/)
 VENDOR_NOTICE_DEPS += $(INSTALLED_VENDOR_BOOTIMAGE_TARGET)
+
+else # BUILDING_VENDOR_BOOT_IMAGE not defined, use prebuilt image
+
+ifdef BOARD_PREBUILT_VENDOR_BOOTIMAGE
+INTERNAL_PREBUILT_VENDOR_BOOTIMAGE := $(BOARD_PREBUILT_VENDOR_BOOTIMAGE)
+INSTALLED_VENDOR_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/vendor_boot.img
+
+ifeq ($(BOARD_AVB_ENABLE),true)
+$(INSTALLED_VENDOR_BOOTIMAGE_TARGET): $(INTERNAL_PREBUILT_VENDOR_BOOTIMAGE) $(AVBTOOL) $(BOARD_AVB_VENDOR_BOOT_KEY_PATH)
+	cp $(INTERNAL_PREBUILT_VENDOR_BOOTIMAGE) $@
+	chmod +w $@
+	$(AVBTOOL) add_hash_footer \
+	    --image $@ \
+	    $(call get-partition-size-argument,$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE)) \
+	    --partition_name vendor_boot $(INTERNAL_AVB_VENDOR_BOOT_SIGNING_ARGS) \
+	    $(BOARD_AVB_VENDOR_BOOT_ADD_HASH_FOOTER_ARGS)
+else
+$(INSTALLED_VENDOR_BOOTIMAGE_TARGET): $(INTERNAL_PREBUILT_VENDOR_BOOTIMAGE)
+	cp $(INTERNAL_PREBUILT_VENDOR_BOOTIMAGE) $@
+
+endif # BOARD_AVB_ENABLE
+$(call declare-1p-container,$(INSTALLED_VENDOR_BOOTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_VENDOR_BOOTIMAGE_TARGET),$(INTERNAL_PREBUILT_VENDOR_BOOTIMAGE),$(PRODUCT_OUT)/:/)
+endif # BOARD_PREBUILT_VENDOR_BOOTIMAGE
 endif # BUILDING_VENDOR_BOOT_IMAGE
 
 # -----------------------------------------------------------------
@@ -2233,11 +2234,6 @@
 $(if $(PRODUCT_VENDOR_DLKM_VERITY_PARTITION),$(hide) echo "vendor_dlkm_verity_block_device=$(PRODUCT_VENDOR_DLKM_VERITY_PARTITION)" >> $(1))
 $(if $(PRODUCT_ODM_DLKM_VERITY_PARTITION),$(hide) echo "odm_dlkm_verity_block_device=$(PRODUCT_ODM_DLKM_VERITY_PARTITION)" >> $(1))
 $(if $(PRODUCT_SYSTEM_DLKM_VERITY_PARTITION),$(hide) echo "system_dlkm_verity_block_device=$(PRODUCT_SYSTEM_DLKM_VERITY_PARTITION)" >> $(1))
-$(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot=$(PRODUCT_SUPPORTS_VBOOT)" >> $(1))
-$(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_key=$(PRODUCT_VBOOT_SIGNING_KEY)" >> $(1))
-$(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_subkey=$(PRODUCT_VBOOT_SIGNING_SUBKEY)" >> $(1))
-$(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "futility=$(notdir $(FUTILITY))" >> $(1))
-$(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_signer_cmd=$(VBOOT_SIGNER)" >> $(1))
 $(if $(BOARD_AVB_ENABLE), \
   $(hide) echo "avb_avbtool=$(notdir $(AVBTOOL))" >> $(1)$(newline) \
   $(if $(filter $(2),system), \
@@ -2747,15 +2743,9 @@
 # $(1): output file
 # $(2): optional kernel file
 define build-recoveryimage-target
-  $(if $(filter true,$(PRODUCT_SUPPORTS_VBOOT)), \
-    $(MKBOOTIMG) $(if $(strip $(2)),--kernel $(strip $(2))) $(INTERNAL_RECOVERYIMAGE_ARGS) \
-                 $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_RECOVERY_MKBOOTIMG_ARGS) \
-                 --output $(1).unsigned, \
-    $(MKBOOTIMG) $(if $(strip $(2)),--kernel $(strip $(2))) $(INTERNAL_RECOVERYIMAGE_ARGS) \
-                 $(INTERNAL_MKBOOTIMG_VERSION_ARGS) \
-                 $(BOARD_RECOVERY_MKBOOTIMG_ARGS) --output $(1))
-  $(if $(filter true,$(PRODUCT_SUPPORTS_VBOOT)), \
-    $(VBOOT_SIGNER) $(FUTILITY) $(1).unsigned $(PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(1).keyblock $(1))
+  $(MKBOOTIMG) $(if $(strip $(2)),--kernel $(strip $(2))) $(INTERNAL_RECOVERYIMAGE_ARGS) \
+               $(INTERNAL_MKBOOTIMG_VERSION_ARGS) \
+               $(BOARD_RECOVERY_MKBOOTIMG_ARGS) --output $(1)
   $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)), \
     $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(call get-bootimage-partition-size,$(1),boot))), \
     $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE))))
@@ -2766,9 +2756,6 @@
 endef
 
 recoveryimage-deps := $(MKBOOTIMG) $(recovery_ramdisk) $(recovery_kernel)
-ifeq (true,$(PRODUCT_SUPPORTS_VBOOT))
-  recoveryimage-deps += $(VBOOT_SIGNER)
-endif
 ifeq (true,$(BOARD_AVB_ENABLE))
   recoveryimage-deps += $(AVBTOOL) $(BOARD_AVB_BOOT_KEY_PATH)
 endif
@@ -5651,12 +5638,6 @@
   resize2fs \
   soong_zip \
 
-ifeq (true,$(PRODUCT_SUPPORTS_VBOOT))
-INTERNAL_OTATOOLS_MODULES += \
-  futility-host \
-  vboot_signer
-endif
-
 INTERNAL_OTATOOLS_FILES := \
   $(filter $(HOST_OUT)/%,$(call module-installed-files,$(INTERNAL_OTATOOLS_MODULES)))
 
@@ -5692,10 +5673,6 @@
   $(sort $(shell find external/avb/test/data -type f -name "testkey_*.pem" -o \
       -name "atx_metadata.bin"))
 endif
-ifeq (true,$(PRODUCT_SUPPORTS_VBOOT))
-INTERNAL_OTATOOLS_PACKAGE_FILES += \
-  $(sort $(shell find external/vboot_reference/tests/devkeys -type f))
-endif
 
 INTERNAL_OTATOOLS_RELEASETOOLS := \
   $(shell find build/make/tools/releasetools -name "*.pyc" -prune -o \
@@ -6708,6 +6685,10 @@
 	@# If breakpad symbols have been generated, add them to the zip.
 	$(hide) cp -R $(TARGET_OUT_BREAKPAD) $(zip_root)/BREAKPAD
 endif
+ifdef BOARD_PREBUILT_VENDOR_BOOTIMAGE
+	$(hide) mkdir -p $(zip_root)/IMAGES
+	$(hide) cp $(INSTALLED_VENDOR_BOOTIMAGE_TARGET) $(zip_root)/IMAGES/
+endif
 ifdef BOARD_PREBUILT_VENDORIMAGE
 	$(hide) mkdir -p $(zip_root)/IMAGES
 	$(hide) cp $(INSTALLED_VENDORIMAGE_TARGET) $(zip_root)/IMAGES/
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 9b536f0..f2ff286 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -27,8 +27,9 @@
 # Add variables to the namespace below:
 
 $(call add_soong_config_var,ANDROID,BOARD_USES_ODMIMAGE)
-$(call add_soong_config_var,ANDROID,BOARD_USES_RECOVERY_AS_BOOT)
+$(call soong_config_set_bool,ANDROID,BOARD_USES_RECOVERY_AS_BOOT,$(BOARD_USES_RECOVERY_AS_BOOT))
 $(call add_soong_config_var,ANDROID,CHECK_DEV_TYPE_VIOLATIONS)
+$(call add_soong_config_var,ANDROID,PLATFORM_SEPOLICY_VERSION)
 $(call add_soong_config_var,ANDROID,PLATFORM_SEPOLICY_COMPAT_VERSIONS)
 $(call add_soong_config_var,ANDROID,PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT)
 $(call add_soong_config_var,ANDROID,TARGET_DYNAMIC_64_32_DRMSERVER)
@@ -36,7 +37,7 @@
 $(call add_soong_config_var,ANDROID,TARGET_DYNAMIC_64_32_MEDIASERVER)
 
 # PRODUCT_PRECOMPILED_SEPOLICY defaults to true. Explicitly check if it's "false" or not.
-$(call add_soong_config_var_value,ANDROID,PRODUCT_PRECOMPILED_SEPOLICY,$(if $(filter false,$(PRODUCT_PRECOMPILED_SEPOLICY)),false,true))
+$(call soong_config_set_bool,ANDROID,PRODUCT_PRECOMPILED_SEPOLICY,$(if $(filter false,$(PRODUCT_PRECOMPILED_SEPOLICY)),false,true))
 
 ifdef ART_DEBUG_OPT_FLAG
 $(call soong_config_set,art_module,art_debug_opt_flag,$(ART_DEBUG_OPT_FLAG))
diff --git a/core/binary.mk b/core/binary.mk
index 77ae6ef..0bc9469 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -258,13 +258,6 @@
       my_ndk_stl_shared_lib_fullpath := $(my_libcxx_libdir)/libc++_shared.so
     endif
 
-    ifneq ($(my_ndk_api),current)
-      ifeq ($(call math_lt,$(my_ndk_api),21),true)
-        my_ndk_stl_include_path += $(my_ndk_source_root)/android/support/include
-        my_ndk_stl_static_lib += $(my_libcxx_libdir)/libandroid_support.a
-      endif
-    endif
-
     my_ndk_stl_static_lib += $(my_libcxx_libdir)/libunwind.a
     my_ldlibs += -ldl
   else # LOCAL_NDK_STL_VARIANT must be none
diff --git a/core/config.mk b/core/config.mk
index f9e6b1f..99337fc 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -316,6 +316,19 @@
 $(eval SOONG_CONFIG_$(strip $1)_$(strip $2):=$(strip $3))
 endef
 
+# soong_config_set_bool is the same as soong_config_set, but it will
+# also type the variable as a bool, so that when using select() expressions
+# in blueprint files they can use boolean values instead of strings.
+# It will only accept "true" for its value, any other value will be
+# treated as false.
+# $1 is the namespace. $2 is the variable name. $3 is the variable value.
+# Ex: $(call soong_config_set_bool,acme,COOL_FEATURE,true)
+define soong_config_set_bool
+$(call soong_config_define_internal,$1,$2) \
+$(eval SOONG_CONFIG_$(strip $1)_$(strip $2):=$(filter true,$3))
+$(eval SOONG_CONFIG_TYPE_$(strip $1)_$(strip $2):=bool)
+endef
+
 # soong_config_append appends to the value of the variable in the given Soong
 # config namespace. If the variable does not exist, it will be defined. If the
 # namespace does not  exist, it will be defined.
@@ -718,8 +731,6 @@
 VERITY_SIGNER := $(HOST_OUT_EXECUTABLES)/verity_signer
 BUILD_VERITY_METADATA := $(HOST_OUT_EXECUTABLES)/build_verity_metadata
 BUILD_VERITY_TREE := $(HOST_OUT_EXECUTABLES)/build_verity_tree
-FUTILITY := $(HOST_OUT_EXECUTABLES)/futility-host
-VBOOT_SIGNER := $(HOST_OUT_EXECUTABLES)/vboot_signer
 
 DEXDUMP := $(HOST_OUT_EXECUTABLES)/dexdump$(BUILD_EXECUTABLE_SUFFIX)
 PROFMAN := $(HOST_OUT_EXECUTABLES)/profman
diff --git a/core/main.mk b/core/main.mk
index 62fa53d..f3980f1 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -1925,6 +1925,64 @@
 	  echo '$(_lib_stem).a,$(_module_path),$(_soong_module_type),,,,,$(_built_file),$(_static_libs),$(_whole_static_libs),$(_is_static_lib)' >> $@; \
 	)
 
+# Create metadata for compliance support in Soong
+.PHONY: make-compliance-metadata
+make-compliance-metadata: \
+    $(SOONG_OUT_DIR)/compliance-metadata/$(TARGET_PRODUCT)/make-metadata.csv \
+    $(SOONG_OUT_DIR)/compliance-metadata/$(TARGET_PRODUCT)/make-modules.csv
+
+$(SOONG_OUT_DIR)/compliance-metadata/$(TARGET_PRODUCT)/make-metadata.csv:
+	rm -f $@
+	echo 'installed_file,module_path,is_soong_module,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,static_libs,whole_static_libs,license_text' >> $@
+	$(foreach f,$(installed_files),\
+	  $(eval _module_name := $(ALL_INSTALLED_FILES.$f)) \
+	  $(eval _path_on_device := $(patsubst $(PRODUCT_OUT)/%,%,$f)) \
+	  $(eval _build_output_path := $(PRODUCT_OUT)/$(_path_on_device)) \
+	  $(eval _module_path := $(strip $(sort $(ALL_MODULES.$(_module_name).PATH)))) \
+	  $(eval _is_soong_module := $(ALL_MODULES.$(_module_name).IS_SOONG_MODULE)) \
+	  $(eval _is_prebuilt_make_module := $(ALL_MODULES.$(_module_name).IS_PREBUILT_MAKE_MODULE)) \
+	  $(eval _product_copy_files := $(sort $(filter %:$(_path_on_device),$(product_copy_files_without_owner)))) \
+	  $(eval _kernel_module_copy_files := $(sort $(filter %$(_path_on_device),$(KERNEL_MODULE_COPY_FILES)))) \
+	  $(eval _is_build_prop := $(call is-build-prop,$f)) \
+	  $(eval _is_notice_file := $(call is-notice-file,$f)) \
+	  $(eval _is_dexpreopt_image_profile := $(if $(filter %:/$(_path_on_device),$(DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED)),Y)) \
+	  $(eval _is_product_system_other_avbkey := $(if $(findstring $f,$(INSTALLED_PRODUCT_SYSTEM_OTHER_AVBKEY_TARGET)),Y)) \
+	  $(eval _is_event_log_tags_file := $(if $(findstring $f,$(event_log_tags_file)),Y)) \
+	  $(eval _is_system_other_odex_marker := $(if $(findstring $f,$(INSTALLED_SYSTEM_OTHER_ODEX_MARKER)),Y)) \
+	  $(eval _is_kernel_modules_blocklist := $(if $(findstring $f,$(ALL_KERNEL_MODULES_BLOCKLIST)),Y)) \
+	  $(eval _is_fsverity_build_manifest_apk := $(if $(findstring $f,$(ALL_FSVERITY_BUILD_MANIFEST_APK)),Y)) \
+	  $(eval _is_linker_config := $(if $(findstring $f,$(SYSTEM_LINKER_CONFIG) $(vendor_linker_config_file)),Y)) \
+	  $(eval _is_partition_compat_symlink := $(if $(findstring $f,$(PARTITION_COMPAT_SYMLINKS)),Y)) \
+	  $(eval _is_flags_file := $(if $(findstring $f, $(ALL_FLAGS_FILES)),Y)) \
+	  $(eval _is_rootdir_symlink := $(if $(findstring $f, $(ALL_ROOTDIR_SYMLINKS)),Y)) \
+	  $(eval _is_platform_generated := $(_is_build_prop)$(_is_notice_file)$(_is_dexpreopt_image_profile)$(_is_product_system_other_avbkey)$(_is_event_log_tags_file)$(_is_system_other_odex_marker)$(_is_kernel_modules_blocklist)$(_is_fsverity_build_manifest_apk)$(_is_linker_config)$(_is_partition_compat_symlink)$(_is_flags_file)$(_is_rootdir_symlink)) \
+	  $(eval _static_libs := $(if $(_is_soong_module),,$(ALL_INSTALLED_FILES.$f.STATIC_LIBRARIES))) \
+	  $(eval _whole_static_libs := $(if $(_is_soong_module),,$(ALL_INSTALLED_FILES.$f.WHOLE_STATIC_LIBRARIES))) \
+	  $(eval _license_text := $(if $(filter $(_build_output_path),$(ALL_NON_MODULES)),$(ALL_NON_MODULES.$(_build_output_path).NOTICES))) \
+	  echo '$(_build_output_path),$(_module_path),$(_is_soong_module),$(_is_prebuilt_make_module),$(_product_copy_files),$(_kernel_module_copy_files),$(_is_platform_generated),$(_static_libs),$(_whole_static_libs),$(_license_text)' >> $@; \
+	)
+
+$(SOONG_OUT_DIR)/compliance-metadata/$(TARGET_PRODUCT)/make-modules.csv:
+	rm -f $@
+	echo 'name,module_path,module_class,module_type,static_libs,whole_static_libs,built_files,installed_files' >> $@
+	$(foreach m,$(ALL_MODULES), \
+	  $(eval _module_name := $m) \
+	  $(eval _module_path := $(strip $(sort $(ALL_MODULES.$(_module_name).PATH)))) \
+	  $(eval _make_module_class := $(ALL_MODULES.$(_module_name).CLASS)) \
+	  $(eval _make_module_type := $(ALL_MODULES.$(_module_name).MAKE_MODULE_TYPE)) \
+	  $(eval _static_libs := $(strip $(sort $(ALL_MODULES.$(_module_name).STATIC_LIBS)))) \
+	  $(eval _whole_static_libs := $(strip $(sort $(ALL_MODULES.$(_module_name).WHOLE_STATIC_LIBS)))) \
+	  $(eval _built_files := $(strip $(sort $(ALL_MODULES.$(_module_name).BUILT)))) \
+	  $(eval _installed_files := $(strip $(sort $(ALL_MODULES.$(_module_name).INSTALLED)))) \
+	  $(eval _is_soong_module := $(ALL_MODULES.$(_module_name).IS_SOONG_MODULE)) \
+	  $(if $(_is_soong_module),, \
+		echo '$(_module_name),$(_module_path),$(_make_module_class),$(_make_module_type),$(_static_libs),$(_whole_static_libs),$(_built_files),$(_installed_files)' >> $@; \
+	  ) \
+	)
+
+$(SOONG_OUT_DIR)/compliance-metadata/$(TARGET_PRODUCT)/installed_files.stamp: $(installed_files)
+	touch $@
+
 # (TODO: b/272358583 find another way of always rebuilding sbom.spdx)
 # Remove the always_dirty_file.txt whenever the makefile is evaluated
 $(shell rm -f $(PRODUCT_OUT)/always_dirty_file.txt)
diff --git a/core/product.mk b/core/product.mk
index 7908e1d..5ceccbf 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -160,7 +160,6 @@
 # List of jars to be included in the ART boot image for testing.
 _product_list_vars += PRODUCT_TEST_ONLY_ART_BOOT_IMAGE_JARS
 
-_product_single_value_vars += PRODUCT_SUPPORTS_VBOOT
 _product_list_vars += PRODUCT_SYSTEM_SERVER_APPS
 # List of system_server classpath jars on the platform.
 _product_list_vars += PRODUCT_SYSTEM_SERVER_JARS
diff --git a/core/soong_config.mk b/core/soong_config.mk
index f799ba0..068034b 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -29,6 +29,7 @@
 $(call add_json_str,  Make_suffix, -$(TARGET_PRODUCT))
 
 $(call add_json_str,  BuildId,                           $(BUILD_ID))
+$(call add_json_str,  BuildFingerprintFile,              build_fingerprint.txt)
 $(call add_json_str,  BuildNumberFile,                   build_number.txt)
 $(call add_json_str,  BuildHostnameFile,                 build_hostname.txt)
 $(call add_json_str,  BuildThumbprintFile,               build_thumbprint.txt)
@@ -261,6 +262,18 @@
   $(call end_json_map))
 $(call end_json_map)
 
+# Add the types of the variables in VendorVars. Since this is much newer
+# than VendorVars, which has a history of just using string values for everything,
+# variables are assumed to be strings by default. For strings, SOONG_CONFIG_TYPE_*
+# will not be set, and they will not have an entry in the VendorVarTypes map.
+$(call add_json_map, VendorVarTypes)
+$(foreach namespace,$(sort $(SOONG_CONFIG_NAMESPACES)),\
+  $(call add_json_map, $(namespace))\
+  $(foreach key,$(sort $(SOONG_CONFIG_$(namespace))),\
+    $(if $(SOONG_CONFIG_TYPE_$(namespace)_$(key)),$(call add_json_str,$(key),$(subst ",\",$(SOONG_CONFIG_TYPE_$(namespace)_$(key))))))\
+  $(call end_json_map))
+$(call end_json_map)
+
 $(call add_json_bool, EnforceProductPartitionInterface,  $(filter true,$(PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE)))
 $(call add_json_str,  DeviceCurrentApiLevelForVendorModules,  $(BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES))
 
@@ -296,6 +309,7 @@
 $(call add_json_bool, BuildBrokenIncorrectPartitionImages, $(filter true,$(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES)))
 $(call add_json_list, BuildBrokenInputDirModules,          $(BUILD_BROKEN_INPUT_DIR_MODULES))
 $(call add_json_bool, BuildBrokenDontCheckSystemSdk,       $(filter true,$(BUILD_BROKEN_DONT_CHECK_SYSTEMSDK)))
+$(call add_json_bool, BuildBrokenDupSysprop,               $(filter true,$(BUILD_BROKEN_DUP_SYSPROP)))
 
 $(call add_json_list, BuildWarningBadOptionalUsesLibsAllowlist,    $(BUILD_WARNING_BAD_OPTIONAL_USES_LIBS_ALLOWLIST))
 
diff --git a/core/soong_extra_config.mk b/core/soong_extra_config.mk
index 006174c..c2b4775 100644
--- a/core/soong_extra_config.mk
+++ b/core/soong_extra_config.mk
@@ -1,6 +1,5 @@
 $(call json_start)
 
-$(call add_json_str, BuildFingerprintFile,              build_fingerprint.txt)
 $(call add_json_str, DeviceCpuVariantRuntime,           $(TARGET_CPU_VARIANT_RUNTIME))
 $(call add_json_str, DeviceAbiList,                     $(TARGET_CPU_ABI_LIST))
 $(call add_json_str, DeviceAbiList32,                   $(TARGET_CPU_ABI_LIST_32_BIT))
@@ -17,8 +16,6 @@
 $(call add_json_str, ShippingApiLevel,       $(PRODUCT_SHIPPING_API_LEVEL))
 $(call add_json_str, ShippingVendorApiLevel, $(PRODUCT_SHIPPING_VENDOR_API_LEVEL))
 
-$(call add_json_bool,BuildBrokenDupSysprop, $(filter true,$(BUILD_BROKEN_DUP_SYSPROP)))
-
 $(call add_json_str, ProductModel,                      $(PRODUCT_MODEL))
 $(call add_json_str, ProductModelForAttestation,        $(PRODUCT_MODEL_FOR_ATTESTATION))
 $(call add_json_str, ProductBrandForAttestation,        $(PRODUCT_BRAND_FOR_ATTESTATION))
@@ -39,17 +36,18 @@
 $(subst ",,$(call collapse-pairs,$(call collapse-pairs,$$($(1)),?=),=))
 endef
 
-$(call add_json_list, SystemProperties,        $(call collapse-prop-pairs,PRODUCT_SYSTEM_PROPERTIES))
-$(call add_json_list, SystemDefaultProperties, $(call collapse-prop-pairs,PRODUCT_SYSTEM_DEFAULT_PROPERTIES))
-$(call add_json_list, SystemExtProperties,     $(call collapse-prop-pairs,PRODUCT_SYSTEM_EXT_PROPERTIES))
-$(call add_json_list, VendorProperties,        $(call collapse-prop-pairs,PRODUCT_VENDOR_PROPERTIES))
-$(call add_json_list, ProductProperties,       $(call collapse-prop-pairs,PRODUCT_PRODUCT_PROPERTIES))
-$(call add_json_list, OdmProperties,           $(call collapse-prop-pairs,PRODUCT_ODM_PROPERTIES))
-$(call add_json_list, OemProperties,           $(call collapse-prop-pairs,PRODUCT_OEM_PROPERTIES))
-$(call add_json_list, PropertyOverrides,       $(call collapse-prop-pairs,PRODUCT_PROPERTY_OVERRIDES))
+$(call add_json_list, PRODUCT_SYSTEM_PROPERTIES,         $(call collapse-prop-pairs,PRODUCT_SYSTEM_PROPERTIES))
+$(call add_json_list, PRODUCT_SYSTEM_DEFAULT_PROPERTIES, $(call collapse-prop-pairs,PRODUCT_SYSTEM_DEFAULT_PROPERTIES))
+$(call add_json_list, PRODUCT_SYSTEM_EXT_PROPERTIES,     $(call collapse-prop-pairs,PRODUCT_SYSTEM_EXT_PROPERTIES))
+$(call add_json_list, PRODUCT_VENDOR_PROPERTIES,         $(call collapse-prop-pairs,PRODUCT_VENDOR_PROPERTIES))
+$(call add_json_list, PRODUCT_PRODUCT_PROPERTIES,        $(call collapse-prop-pairs,PRODUCT_PRODUCT_PROPERTIES))
+$(call add_json_list, PRODUCT_ODM_PROPERTIES,            $(call collapse-prop-pairs,PRODUCT_ODM_PROPERTIES))
+$(call add_json_list, PRODUCT_PROPERTY_OVERRIDES,        $(call collapse-prop-pairs,PRODUCT_PROPERTY_OVERRIDES))
 
 $(call add_json_str, BootloaderBoardName, $(TARGET_BOOTLOADER_BOARD_NAME))
 
+$(call add_json_bool, SdkBuild, $(filter sdk sdk_addon,$(MAKECMDGOALS)))
+
 _config_enable_uffd_gc := \
   $(firstword $(OVERRIDE_ENABLE_UFFD_GC) $(PRODUCT_ENABLE_UFFD_GC) default)
 $(call add_json_str, EnableUffdGc, $(_config_enable_uffd_gc))
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index 2e2ea79..294cb57 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -92,8 +92,16 @@
 
 cts_api_coverage_exe := $(HOST_OUT_EXECUTABLES)/cts-api-coverage
 dexdeps_exe := $(HOST_OUT_EXECUTABLES)/dexdeps
+cts_api_map_exe := $(HOST_OUT_EXECUTABLES)/cts-api-map
 
 coverage_out := $(HOST_OUT)/cts-api-coverage
+api_map_out := $(HOST_OUT)/cts-api-map
+
+cts_jar_files := $(api_map_out)/api_map_files.txt
+$(cts_jar_files): PRIVATE_API_MAP_FILES := $(sort $(COMPATIBILITY.cts.API_MAP_FILES))
+$(cts_jar_files):
+	mkdir -p $(dir $@)
+	echo $(PRIVATE_API_MAP_FILES) > $@
 
 api_xml_description := $(TARGET_OUT_COMMON_INTERMEDIATES)/api.xml
 
@@ -116,6 +124,14 @@
 cts_api_coverage_dependencies := $(cts_api_coverage_exe) $(dexdeps_exe) $(api_xml_description) $(napi_xml_description)
 cts_system_api_coverage_dependencies := $(cts_api_coverage_exe) $(dexdeps_exe) $(system_api_xml_description)
 
+cts-api-xml-api-map-report := $(api_map_out)/api-map.xml
+cts-api-html-api-map-report := $(api_map_out)/api-map.html
+cts-system-api-xml-api-map-report := $(api_map_out)/system-api-map.xml
+cts-system-api-html-api-map-report := $(api_map_out)/system-api-map.html
+
+cts_system_api_map_dependencies := $(cts_api_map_exe) $(system_api_xml_description) $(cts_jar_files)
+cts_api_map_dependencies := $(cts_api_map_exe) $(api_xml_description) $(cts_jar_files)
+
 android_cts_zip := $(HOST_OUT)/cts/android-cts.zip
 cts_verifier_apk := $(call intermediates-dir-for,APPS,CtsVerifier)/package.apk
 
@@ -194,6 +210,48 @@
 .PHONY: cts-coverage-report-all cts-api-coverage
 cts-coverage-report-all: cts-test-coverage cts-verifier-coverage cts-combined-coverage cts-combined-xml-coverage
 
+$(cts-system-api-xml-api-map-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
+$(cts-system-api-xml-api-map-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
+$(cts-system-api-xml-api-map-report): PRIVATE_JAR_FILES := $(cts_jar_files)
+$(cts-system-api-xml-api-map-report) : $(android_cts_zip) $(cts_system_api_map_dependencies) | $(ACP)
+	$(call generate-api-map-report-cts,"CTS System API MAP Report - XML",\
+			$(PRIVATE_JAR_FILES),xml)
+
+$(cts-system-api-html-api-map-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
+$(cts-system-api-html-api-map-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
+$(cts-system-api-html-api-map-report): PRIVATE_JAR_FILES := $(cts_jar_files)
+$(cts-system-api-html-api-map-report) : $(android_cts_zip) $(cts_system_api_map_dependencies) | $(ACP)
+	$(call generate-api-map-report-cts,"CTS System API MAP Report - HTML",\
+			$(PRIVATE_JAR_FILES),html)
+
+$(cts-api-xml-api-map-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
+$(cts-api-xml-api-map-report): PRIVATE_API_XML_DESC := $(api_xml_description)
+$(cts-api-xml-api-map-report): PRIVATE_JAR_FILES := $(cts_jar_files)
+$(cts-api-xml-api-map-report) : $(android_cts_zip) $(cts_api_map_dependencies) | $(ACP)
+	$(call generate-api-map-report-cts,"CTS API MAP Report - XML",\
+			$(PRIVATE_JAR_FILES),xml)
+
+$(cts-api-html-api-map-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
+$(cts-api-html-api-map-report): PRIVATE_API_XML_DESC := $(api_xml_description)
+$(cts-api-html-api-map-report): PRIVATE_JAR_FILES := $(cts_jar_files)
+$(cts-api-html-api-map-report) : $(android_cts_zip) $(cts_api_map_dependencies) | $(ACP)
+	$(call generate-api-map-report-cts,"CTS API MAP Report - HTML",\
+			$(PRIVATE_JAR_FILES),html)
+
+.PHONY: cts-system-api-xml-api-map
+cts-system-api-xml-api-map : $(cts-system-api-xml-api-map-report)
+
+.PHONY: cts-system-api-html-api-map
+cts-system-api-html-api-map : $(cts-system-api-html-api-map-report)
+
+.PHONY: cts-api-xml-api-map
+cts-api-xml-api-map : $(cts-api-xml-api-map-report)
+
+.PHONY: cts-api-html-api-map
+cts-api-html-api-map : $(cts-api-html-api-map-report)
+
+.PHONY: cts-api-map-all
+
 # Put the test coverage report in the dist dir if "cts-api-coverage" is among the build goals.
 $(call dist-for-goals, cts-api-coverage, $(cts-test-coverage-report):cts-test-coverage-report.html)
 $(call dist-for-goals, cts-api-coverage, $(cts-system-api-coverage-report):cts-system-api-coverage-report.html)
@@ -209,6 +267,17 @@
 ALL_TARGETS.$(cts-combined-coverage-report).META_LIC:=$(module_license_metadata)
 ALL_TARGETS.$(cts-combined-xml-coverage-report).META_LIC:=$(module_license_metadata)
 
+# Put the test api map report in the dist dir if "cts-api-map-all" is among the build goals.
+$(call dist-for-goals, cts-api-map-all, $(cts-system-api-xml-api-map-report):cts-system-api-xml-api-map-report.xml)
+$(call dist-for-goals, cts-api-map-all, $(cts-system-api-html-api-map-report):cts-system-api-html-api-map-report.html)
+$(call dist-for-goals, cts-api-map-all, $(cts-api-xml-api-map-report):cts-api-xml-api-map-report.xml)
+$(call dist-for-goals, cts-api-map-all, $(cts-api-html-api-map-report):cts-api-html-api-map-report.html)
+
+ALL_TARGETS.$(cts-system-api-xml-api-map-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-system-api-html-api-map-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-api-xml-api-map-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-api-html-api-map-report).META_LIC:=$(module_license_metadata)
+
 # Arguments;
 #  1 - Name of the report printed out on the screen
 #  2 - List of apk files that will be scanned to generate the report
@@ -219,23 +288,42 @@
 	@ echo $(1): file://$$(cd $(dir $@); pwd)/$(notdir $@)
 endef
 
+# Arguments;
+#  1 - Name of the report printed out on the screen
+#  2 - A file containing list of files that to be analyzed
+#  3 - Format of the report
+define generate-api-map-report-cts
+	$(hide) mkdir -p $(dir $@)
+	$(hide) $(PRIVATE_CTS_API_MAP_EXE) -j 8 -a $(PRIVATE_API_XML_DESC) -i $(2) -f $(3) -o $@
+	@ echo $(1): file://$$(cd $(dir $@); pwd)/$(notdir $@)
+endef
+
 # Reset temp vars
 cts_api_coverage_dependencies :=
 cts_system_api_coverage_dependencies :=
+cts_api_map_dependencies :=
+cts_system_api_map_dependencies :=
 cts-combined-coverage-report :=
 cts-combined-xml-coverage-report :=
 cts-verifier-coverage-report :=
 cts-test-coverage-report :=
 cts-system-api-coverage-report :=
 cts-system-api-xml-coverage-report :=
+cts-api-xml-api-map-report :=
+cts-api-html-api-map-report :=
+cts-system-api-xml-api-map-report :=
+cts-system-api-html-api-map-report :=
 api_xml_description :=
 api_text_description :=
 system_api_xml_description :=
 napi_xml_description :=
 napi_text_description :=
 coverage_out :=
+api_map_out :=
+cts_jar_files :=
 dexdeps_exe :=
 cts_api_coverage_exe :=
+cts_api_map_exe :=
 cts_verifier_apk :=
 android_cts_zip :=
 cts-dir :=
diff --git a/core/tasks/meta-lic.mk b/core/tasks/meta-lic.mk
index a94a016..3520a32 100644
--- a/core/tasks/meta-lic.mk
+++ b/core/tasks/meta-lic.mk
@@ -185,3 +185,6 @@
 $(eval $(call declare-1p-copy-files,device/generic/goldfish,init.ranchu-core.sh))
 $(eval $(call declare-1p-copy-files,device/generic/goldfish,init.ranchu-net.sh))
 $(eval $(call declare-1p-copy-files,device/generic/goldfish,audio_policy_configuration.xml))
+
+# Moved here from packages/services/Car/Android.mk
+$(eval $(call declare-1p-copy-files,packages/services/Car,))
diff --git a/target/product/aosp_arm64.mk b/target/product/aosp_arm64.mk
index 783ed3b..7a9325d 100644
--- a/target/product/aosp_arm64.mk
+++ b/target/product/aosp_arm64.mk
@@ -58,9 +58,6 @@
 AB_OTA_UPDATER := true
 AB_OTA_PARTITIONS ?= system
 
-# Set widevine apex signed with dev key
-$(call soong_config_set,widevine,use_devkey,true)
-
 #
 # Special settings for GSI releasing
 #
diff --git a/target/product/aosp_x86_64.mk b/target/product/aosp_x86_64.mk
index e9ca482..595940d 100644
--- a/target/product/aosp_x86_64.mk
+++ b/target/product/aosp_x86_64.mk
@@ -60,9 +60,6 @@
 AB_OTA_UPDATER := true
 AB_OTA_PARTITIONS ?= system
 
-# Set widevine apex signed with dev key
-$(call soong_config_set,widevine,use_devkey,true)
-
 #
 # Special settings for GSI releasing
 #
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 8ce8855..795d3f8 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -336,7 +336,8 @@
 # Check if the build supports Profiling module
 ifeq ($(RELEASE_PACKAGE_PROFILING_MODULE),true)
     PRODUCT_PACKAGES += \
-       com.android.profiling
+       com.android.profiling \
+       trace_redactor
 endif
 
 ifeq ($(RELEASE_USE_WEBVIEW_BOOTSTRAP_MODULE),true)
@@ -412,7 +413,7 @@
     flags_health_check \
     fsck.erofs \
     icu-data_host_i18n_apex \
-    icu_tzdata.dat_host_tzdata_apex \
+    tzdata_icu_res_files_host_prebuilts \
     idmap2 \
     incident_report \
     ld.mc \
@@ -512,3 +513,4 @@
 $(call inherit-product,$(SRC_TARGET_DIR)/product/updatable_apex.mk)
 
 $(call soong_config_set, bionic, large_system_property_node, $(RELEASE_LARGE_SYSTEM_PROPERTY_NODE))
+$(call soong_config_set, Aconfig, read_from_new_storage, $(RELEASE_READ_FROM_NEW_STORAGE))
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index da1284e..39428d2 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -51,9 +51,11 @@
     init.vndk-nodef.rc \
 
 
-# Overlay the GSI specific SystemUI setting
+# Overlay the GSI specific setting for framework and SystemUI
 ifneq ($(PRODUCT_IS_AUTOMOTIVE),true)
-    PRODUCT_PACKAGES += gsi_overlay_systemui
+    PRODUCT_PACKAGES += \
+        gsi_overlay_framework \
+        gsi_overlay_systemui \
     PRODUCT_COPY_FILES += \
         device/generic/common/overlays/overlay-config.xml:$(TARGET_COPY_OUT_SYSTEM_EXT)/overlay/config/config.xml
 endif
diff --git a/target/product/handheld_system.mk b/target/product/handheld_system.mk
index fb55f56..3f3bd01 100644
--- a/target/product/handheld_system.mk
+++ b/target/product/handheld_system.mk
@@ -33,6 +33,7 @@
 $(call inherit-product-if-exists, frameworks/webview/chromium/chromium.mk)
 
 PRODUCT_PACKAGES += \
+    android.software.window_magnification.prebuilt.xml \
     BasicDreams \
     BlockedNumberProvider \
     BluetoothMidiService \
@@ -88,9 +89,6 @@
 
 PRODUCT_PACKAGES += framework-audio_effects.xml
 
-PRODUCT_COPY_FILES += \
-    frameworks/native/data/etc/android.software.window_magnification.xml:$(TARGET_COPY_OUT_SYSTEM)/etc/permissions/android.software.window_magnification.xml \
-
 PRODUCT_VENDOR_PROPERTIES += \
     ro.carrier?=unknown \
     ro.config.notification_sound?=OnTheHunt.ogg \
diff --git a/target/product/media_system.mk b/target/product/media_system.mk
index 503c9b3..af3857e 100644
--- a/target/product/media_system.mk
+++ b/target/product/media_system.mk
@@ -21,6 +21,7 @@
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base_system.mk)
 
 PRODUCT_PACKAGES += \
+    android.software.webview.prebuilt.xml \
     com.android.future.usb.accessory \
     com.android.mediadrm.signer \
     com.android.media.remotedisplay \
@@ -39,12 +40,9 @@
 PRODUCT_HOST_PACKAGES += \
     fsck.f2fs \
 
-PRODUCT_COPY_FILES += \
-    frameworks/native/data/etc/android.software.webview.xml:system/etc/permissions/android.software.webview.xml
-
 ifneq (REL,$(PLATFORM_VERSION_CODENAME))
-PRODUCT_COPY_FILES += \
-    frameworks/native/data/etc/android.software.preview_sdk.xml:system/etc/permissions/android.software.preview_sdk.xml
+PRODUCT_PACKAGES += \
+    android.software.preview_sdk.prebuilt.xml
 endif
 
 # The order here is the same order they end up on the classpath, so it matters.
diff --git a/target/product/vboot.mk b/target/product/vboot.mk
deleted file mode 100644
index 48a4883..0000000
--- a/target/product/vboot.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright (C) 2015 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.
-#
-
-# Provides dependencies necessary for verified boot
-
-PRODUCT_SUPPORTS_VBOOT := true
-
-# The dev key is used to sign boot and recovery images.
-# We expect this file to exist with the suffixes ".vbprivk" and ".vbpupk".
-# TODO: find a proper location for this
-PRODUCT_VBOOT_SIGNING_KEY := external/vboot_reference/tests/devkeys/kernel_data_key
-PRODUCT_VBOOT_SIGNING_SUBKEY := external/vboot_reference/tests/devkeys/kernel_subkey
diff --git a/target/product/virtual_ab_ota/vabc_features.mk b/target/product/virtual_ab_ota/vabc_features.mk
index 1219763..e2745a1 100644
--- a/target/product/virtual_ab_ota/vabc_features.mk
+++ b/target/product/virtual_ab_ota/vabc_features.mk
@@ -40,6 +40,7 @@
 # ro.virtual_ab.compression.xor.enabled and ro.virtual_ab.io_uring.enabled
 # is also recommended
 #
+# PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.read_ahead_size=16
 # PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.o_direct.enabled=true
 # PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.merge_thread_priority=19
 # PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.worker_thread_priority=0
diff --git a/teams/Android.bp b/teams/Android.bp
index c56af6b..fbf1344 100644
--- a/teams/Android.bp
+++ b/teams/Android.bp
@@ -4405,3 +4405,10 @@
     // go/trendy/manage/engineers/4705629185081344
     trendy_team_id: "4705629185081344",
 }
+
+team {
+    name: "trendy_team_android_media_solutions_editing",
+
+    // go/trendy/manage/engineers/5350750192762880
+    trendy_team_id: "5350750192762880",
+}
diff --git a/tools/aconfig/aconfig_device_paths/src/lib.rs b/tools/aconfig/aconfig_device_paths/src/lib.rs
index 7480b30..9ab9cea 100644
--- a/tools/aconfig/aconfig_device_paths/src/lib.rs
+++ b/tools/aconfig/aconfig_device_paths/src/lib.rs
@@ -30,9 +30,11 @@
         .collect()
 }
 
-/// Determine all paths that contain an aconfig protobuf file.
+/// Determines all paths that contain an aconfig protobuf file,
+/// filtering out nonexistent partition protobuf files.
 pub fn parsed_flags_proto_paths() -> Result<Vec<PathBuf>> {
-    let mut result: Vec<PathBuf> = read_partition_paths();
+    let mut result: Vec<PathBuf> =
+        read_partition_paths().into_iter().filter(|s| s.exists()).collect();
 
     for dir in fs::read_dir("/apex")? {
         let dir = dir?;
diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp
index 01eb398..eb7127b 100644
--- a/tools/aconfig/aconfig_storage_read_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/Android.bp
@@ -104,6 +104,33 @@
     afdo: true,
 }
 
+soong_config_module_type {
+    name: "aconfig_lib_cc_shared_link_defaults",
+    module_type: "cc_defaults",
+    config_namespace: "Aconfig",
+    bool_variables: [
+        "read_from_new_storage",
+    ],
+    properties: [
+        "shared_libs",
+    ],
+}
+
+soong_config_bool_variable {
+    name: "read_from_new_storage",
+}
+
+aconfig_lib_cc_shared_link_defaults {
+    name: "aconfig_lib_cc_shared_link.defaults",
+    soong_config_variables: {
+        read_from_new_storage: {
+            shared_libs: [
+                "libaconfig_storage_read_api_cc",
+            ],
+        },
+    },
+}
+
 cc_defaults {
     name: "aconfig_lib_cc_static_link.defaults",
     shared_libs: [
diff --git a/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp b/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp
index cabc65e..7b43574 100644
--- a/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp
+++ b/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp
@@ -1,6 +1,7 @@
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/unique_fd.h>
 
 #include <sys/mman.h>
 #include <sys/stat.h>
@@ -13,8 +14,8 @@
 namespace aconfig_storage {
 
 /// Map a storage file
-android::base::Result<MutableMappedStorageFile*> map_mutable_storage_file(
-    std::string const& file) {
+android::base::Result<MutableMappedStorageFile *> map_mutable_storage_file(
+    std::string const &file) {
   struct stat file_stat;
   if (stat(file.c_str(), &file_stat) < 0) {
     return android::base::ErrnoError() << "stat failed";
@@ -26,13 +27,13 @@
 
   size_t file_size = file_stat.st_size;
 
-  const int fd = open(file.c_str(), O_RDWR | O_NOFOLLOW | O_CLOEXEC);
-  if (fd == -1) {
+  android::base::unique_fd ufd(open(file.c_str(), O_RDWR | O_NOFOLLOW | O_CLOEXEC));
+  if (ufd.get() == -1) {
     return android::base::ErrnoError() << "failed to open " << file;
   };
 
-  void* const map_result =
-      mmap(nullptr, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  void *const map_result =
+      mmap(nullptr, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, ufd.get(), 0);
   if (map_result == MAP_FAILED) {
     return android::base::ErrnoError() << "mmap failed";
   }
@@ -46,47 +47,56 @@
 
 /// Set boolean flag value
 android::base::Result<void> set_boolean_flag_value(
-    const MutableMappedStorageFile& file,
+    const MutableMappedStorageFile &file,
     uint32_t offset,
     bool value) {
   auto content = rust::Slice<uint8_t>(
-      static_cast<uint8_t*>(file.file_ptr), file.file_size);
+      static_cast<uint8_t *>(file.file_ptr), file.file_size);
   auto update_cxx = update_boolean_flag_value_cxx(content, offset, value);
   if (!update_cxx.update_success) {
     return android::base::Error() << update_cxx.error_message.c_str();
   }
+  if (!msync(static_cast<uint8_t *>(file.file_ptr) + update_cxx.offset, 1, MS_SYNC)) {
+    return android::base::ErrnoError() << "msync failed";
+  }
   return {};
 }
 
 /// Set if flag has server override
 android::base::Result<void> set_flag_has_server_override(
-    const MutableMappedStorageFile& file,
+    const MutableMappedStorageFile &file,
     FlagValueType value_type,
     uint32_t offset,
     bool value) {
   auto content = rust::Slice<uint8_t>(
-      static_cast<uint8_t*>(file.file_ptr), file.file_size);
+      static_cast<uint8_t *>(file.file_ptr), file.file_size);
   auto update_cxx = update_flag_has_server_override_cxx(
       content, static_cast<uint16_t>(value_type), offset, value);
   if (!update_cxx.update_success) {
     return android::base::Error() << update_cxx.error_message.c_str();
   }
+  if (!msync(static_cast<uint8_t *>(file.file_ptr) + update_cxx.offset, 1, MS_SYNC)) {
+    return android::base::ErrnoError() << "msync failed";
+  }
   return {};
 }
 
 /// Set if flag has local override
 android::base::Result<void> set_flag_has_local_override(
-    const MutableMappedStorageFile& file,
+    const MutableMappedStorageFile &file,
     FlagValueType value_type,
     uint32_t offset,
     bool value) {
   auto content = rust::Slice<uint8_t>(
-      static_cast<uint8_t*>(file.file_ptr), file.file_size);
+      static_cast<uint8_t *>(file.file_ptr), file.file_size);
   auto update_cxx = update_flag_has_local_override_cxx(
       content, static_cast<uint16_t>(value_type), offset, value);
   if (!update_cxx.update_success) {
     return android::base::Error() << update_cxx.error_message.c_str();
   }
+  if (!msync(static_cast<uint8_t *>(file.file_ptr) + update_cxx.offset, 1, MS_SYNC)) {
+    return android::base::ErrnoError() << "msync failed";
+  }
   return {};
 }
 
diff --git a/tools/aconfig/aconfig_storage_write_api/src/flag_info_update.rs b/tools/aconfig/aconfig_storage_write_api/src/flag_info_update.rs
index 6f03f12..7e60713 100644
--- a/tools/aconfig/aconfig_storage_write_api/src/flag_info_update.rs
+++ b/tools/aconfig/aconfig_storage_write_api/src/flag_info_update.rs
@@ -67,13 +67,13 @@
     flag_type: FlagValueType,
     flag_index: u32,
     value: bool,
-) -> Result<(), AconfigStorageError> {
+) -> Result<usize, AconfigStorageError> {
     let (attribute, head) = get_flag_attribute_and_offset(buf, flag_type, flag_index)?;
     let has_override = (attribute & (FlagInfoBit::HasServerOverride as u8)) != 0;
     if has_override != value {
         buf[head] = (attribute ^ FlagInfoBit::HasServerOverride as u8).to_le_bytes()[0];
     }
-    Ok(())
+    Ok(head)
 }
 
 /// Set if flag has local override
@@ -82,13 +82,13 @@
     flag_type: FlagValueType,
     flag_index: u32,
     value: bool,
-) -> Result<(), AconfigStorageError> {
+) -> Result<usize, AconfigStorageError> {
     let (attribute, head) = get_flag_attribute_and_offset(buf, flag_type, flag_index)?;
     let has_override = (attribute & (FlagInfoBit::HasLocalOverride as u8)) != 0;
     if has_override != value {
         buf[head] = (attribute ^ FlagInfoBit::HasLocalOverride as u8).to_le_bytes()[0];
     }
-    Ok(())
+    Ok(head)
 }
 
 #[cfg(test)]
diff --git a/tools/aconfig/aconfig_storage_write_api/src/flag_value_update.rs b/tools/aconfig/aconfig_storage_write_api/src/flag_value_update.rs
index 0938715..dd15c99 100644
--- a/tools/aconfig/aconfig_storage_write_api/src/flag_value_update.rs
+++ b/tools/aconfig/aconfig_storage_write_api/src/flag_value_update.rs
@@ -24,7 +24,7 @@
     buf: &mut [u8],
     flag_index: u32,
     flag_value: bool,
-) -> Result<(), AconfigStorageError> {
+) -> Result<usize, AconfigStorageError> {
     let interpreted_header = FlagValueHeader::from_bytes(buf)?;
     if interpreted_header.version > FILE_VERSION {
         return Err(AconfigStorageError::HigherStorageFileVersion(anyhow!(
@@ -43,7 +43,7 @@
     }
 
     buf[head] = u8::from(flag_value).to_le_bytes()[0];
-    Ok(())
+    Ok(head)
 }
 
 #[cfg(test)]
diff --git a/tools/aconfig/aconfig_storage_write_api/src/lib.rs b/tools/aconfig/aconfig_storage_write_api/src/lib.rs
index aec28de..0396a63 100644
--- a/tools/aconfig/aconfig_storage_write_api/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_write_api/src/lib.rs
@@ -194,18 +194,21 @@
     // Flag value update return for cc interlop
     pub struct BooleanFlagValueUpdateCXX {
         pub update_success: bool,
+        pub offset: usize,
         pub error_message: String,
     }
 
     // Flag has server override update return for cc interlop
     pub struct FlagHasServerOverrideUpdateCXX {
         pub update_success: bool,
+        pub offset: usize,
         pub error_message: String,
     }
 
     // Flag has local override update return for cc interlop
     pub struct FlagHasLocalOverrideUpdateCXX {
         pub update_success: bool,
+        pub offset: usize,
         pub error_message: String,
     }
 
@@ -251,11 +254,14 @@
     value: bool,
 ) -> ffi::BooleanFlagValueUpdateCXX {
     match crate::flag_value_update::update_boolean_flag_value(file, offset, value) {
-        Ok(()) => {
-            ffi::BooleanFlagValueUpdateCXX { update_success: true, error_message: String::from("") }
-        }
+        Ok(head) => ffi::BooleanFlagValueUpdateCXX {
+            update_success: true,
+            offset: head,
+            error_message: String::from(""),
+        },
         Err(errmsg) => ffi::BooleanFlagValueUpdateCXX {
             update_success: false,
+            offset: usize::MAX,
             error_message: format!("{:?}", errmsg),
         },
     }
@@ -272,18 +278,21 @@
             match crate::flag_info_update::update_flag_has_server_override(
                 file, value_type, offset, value,
             ) {
-                Ok(()) => ffi::FlagHasServerOverrideUpdateCXX {
+                Ok(head) => ffi::FlagHasServerOverrideUpdateCXX {
                     update_success: true,
+                    offset: head,
                     error_message: String::from(""),
                 },
                 Err(errmsg) => ffi::FlagHasServerOverrideUpdateCXX {
                     update_success: false,
+                    offset: usize::MAX,
                     error_message: format!("{:?}", errmsg),
                 },
             }
         }
         Err(errmsg) => ffi::FlagHasServerOverrideUpdateCXX {
             update_success: false,
+            offset: usize::MAX,
             error_message: format!("{:?}", errmsg),
         },
     }
@@ -300,18 +309,21 @@
             match crate::flag_info_update::update_flag_has_local_override(
                 file, value_type, offset, value,
             ) {
-                Ok(()) => ffi::FlagHasLocalOverrideUpdateCXX {
+                Ok(head) => ffi::FlagHasLocalOverrideUpdateCXX {
                     update_success: true,
+                    offset: head,
                     error_message: String::from(""),
                 },
                 Err(errmsg) => ffi::FlagHasLocalOverrideUpdateCXX {
                     update_success: false,
+                    offset: usize::MAX,
                     error_message: format!("{:?}", errmsg),
                 },
             }
         }
         Err(errmsg) => ffi::FlagHasLocalOverrideUpdateCXX {
             update_success: false,
+            offset: usize::MAX,
             error_message: format!("{:?}", errmsg),
         },
     }
diff --git a/tools/aconfig/aconfig_storage_write_api/tests/Android.bp b/tools/aconfig/aconfig_storage_write_api/tests/Android.bp
index f6409b7..d7afc1a 100644
--- a/tools/aconfig/aconfig_storage_write_api/tests/Android.bp
+++ b/tools/aconfig/aconfig_storage_write_api/tests/Android.bp
@@ -39,4 +39,10 @@
         "general-tests",
     ],
     ldflags: ["-Wl,--allow-multiple-definition"],
+        generated_headers: [
+        "cxx-bridge-header",
+        "libcxx_aconfig_storage_read_api_bridge_header",
+    ],
+    generated_sources: ["libcxx_aconfig_storage_read_api_bridge_code"],
+    whole_static_libs: ["libaconfig_storage_read_api_cxx_bridge"],
 }
diff --git a/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp b/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp
index 31183fa..133f5a0 100644
--- a/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp
+++ b/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp
@@ -25,6 +25,9 @@
 #include <android-base/file.h>
 #include <android-base/result.h>
 
+#include "rust/cxx.h"
+#include "aconfig_storage/lib.rs.h"
+
 using namespace android::base;
 
 namespace api = aconfig_storage;
@@ -85,6 +88,23 @@
     ASSERT_TRUE(value.ok());
     ASSERT_TRUE(*value);
   }
+
+  // load the file on disk and check has been updated
+  std::ifstream file(flag_val, std::ios::binary | std::ios::ate);
+  std::streamsize size = file.tellg();
+  file.seekg(0, std::ios::beg);
+
+  std::vector<uint8_t> buffer(size);
+  file.read(reinterpret_cast<char *>(buffer.data()), size);
+
+  auto content = rust::Slice<const uint8_t>(
+      buffer.data(), mapped_file->file_size);
+
+  for (int offset = 0; offset < 8; ++offset) {
+    auto value_cxx = get_boolean_flag_value_cxx(content, offset);
+    ASSERT_TRUE(value_cxx.query_success);
+    ASSERT_TRUE(value_cxx.flag_value);
+  }
 }
 
 /// Negative test to lock down the error when querying flag value out of range
@@ -112,15 +132,43 @@
         *mapped_file, api::FlagValueType::Boolean, offset);
     ASSERT_TRUE(attribute.ok());
     ASSERT_TRUE(*attribute & api::FlagInfoBit::HasServerOverride);
+  }
 
-    update_result = api::set_flag_has_server_override(
+  // load the file on disk and check has been updated
+  std::ifstream file(flag_info, std::ios::binary | std::ios::ate);
+  std::streamsize size = file.tellg();
+  file.seekg(0, std::ios::beg);
+
+  std::vector<uint8_t> buffer(size);
+  file.read(reinterpret_cast<char *>(buffer.data()), size);
+
+  auto content = rust::Slice<const uint8_t>(
+      buffer.data(), mapped_file->file_size);
+
+  for (int offset = 0; offset < 8; ++offset) {
+    auto attribute = get_flag_attribute_cxx(content, api::FlagValueType::Boolean, offset);
+    ASSERT_TRUE(attribute.query_success);
+    ASSERT_TRUE(attribute.flag_attribute & api::FlagInfoBit::HasServerOverride);
+  }
+
+  for (int offset = 0; offset < 8; ++offset) {
+    auto update_result = api::set_flag_has_server_override(
         *mapped_file, api::FlagValueType::Boolean, offset, false);
     ASSERT_TRUE(update_result.ok());
-    attribute = api::get_flag_attribute(
+    auto attribute = api::get_flag_attribute(
         *mapped_file, api::FlagValueType::Boolean, offset);
     ASSERT_TRUE(attribute.ok());
     ASSERT_FALSE(*attribute & api::FlagInfoBit::HasServerOverride);
   }
+
+  std::ifstream file2(flag_info, std::ios::binary);
+  buffer.clear();
+  file2.read(reinterpret_cast<char *>(buffer.data()), size);
+  for (int offset = 0; offset < 8; ++offset) {
+    auto attribute = get_flag_attribute_cxx(content, api::FlagValueType::Boolean, offset);
+    ASSERT_TRUE(attribute.query_success);
+    ASSERT_FALSE(attribute.flag_attribute & api::FlagInfoBit::HasServerOverride);
+  }
 }
 
 /// Test to lock down storage flag has local override update api
@@ -137,13 +185,41 @@
         *mapped_file, api::FlagValueType::Boolean, offset);
     ASSERT_TRUE(attribute.ok());
     ASSERT_TRUE(*attribute & api::FlagInfoBit::HasLocalOverride);
+  }
 
-    update_result = api::set_flag_has_local_override(
+  // load the file on disk and check has been updated
+  std::ifstream file(flag_info, std::ios::binary | std::ios::ate);
+  std::streamsize size = file.tellg();
+  file.seekg(0, std::ios::beg);
+
+  std::vector<uint8_t> buffer(size);
+  file.read(reinterpret_cast<char *>(buffer.data()), size);
+
+  auto content = rust::Slice<const uint8_t>(
+      buffer.data(), mapped_file->file_size);
+
+  for (int offset = 0; offset < 8; ++offset) {
+    auto attribute = get_flag_attribute_cxx(content, api::FlagValueType::Boolean, offset);
+    ASSERT_TRUE(attribute.query_success);
+    ASSERT_TRUE(attribute.flag_attribute & api::FlagInfoBit::HasLocalOverride);
+  }
+
+  for (int offset = 0; offset < 8; ++offset) {
+    auto update_result = api::set_flag_has_local_override(
         *mapped_file, api::FlagValueType::Boolean, offset, false);
     ASSERT_TRUE(update_result.ok());
-    attribute = api::get_flag_attribute(
+    auto attribute = api::get_flag_attribute(
         *mapped_file, api::FlagValueType::Boolean, offset);
     ASSERT_TRUE(attribute.ok());
     ASSERT_FALSE(*attribute & api::FlagInfoBit::HasLocalOverride);
   }
+
+  std::ifstream file2(flag_info, std::ios::binary);
+  buffer.clear();
+  file2.read(reinterpret_cast<char *>(buffer.data()), size);
+  for (int offset = 0; offset < 8; ++offset) {
+    auto attribute = get_flag_attribute_cxx(content, api::FlagValueType::Boolean, offset);
+    ASSERT_TRUE(attribute.query_success);
+    ASSERT_FALSE(attribute.flag_attribute & api::FlagInfoBit::HasLocalOverride);
+  }
 }
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index d91a713..4834834 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -1784,12 +1784,7 @@
   if has_ramdisk:
     cmd.extend(["--ramdisk", ramdisk_img.name])
 
-  img_unsigned = None
-  if info_dict.get("vboot"):
-    img_unsigned = tempfile.NamedTemporaryFile()
-    cmd.extend(["--output", img_unsigned.name])
-  else:
-    cmd.extend(["--output", img.name])
+  cmd.extend(["--output", img.name])
 
   if partition_name == "recovery":
     if info_dict.get("include_recovery_dtbo") == "true":
@@ -1801,28 +1796,6 @@
 
   RunAndCheckOutput(cmd)
 
-  # Sign the image if vboot is non-empty.
-  if info_dict.get("vboot"):
-    path = "/" + partition_name
-    img_keyblock = tempfile.NamedTemporaryFile()
-    # We have switched from the prebuilt futility binary to using the tool
-    # (futility-host) built from the source. Override the setting in the old
-    # TF.zip.
-    futility = info_dict["futility"]
-    if futility.startswith("prebuilts/"):
-      futility = "futility-host"
-    cmd = [info_dict["vboot_signer_cmd"], futility,
-           img_unsigned.name, info_dict["vboot_key"] + ".vbpubk",
-           info_dict["vboot_key"] + ".vbprivk",
-           info_dict["vboot_subkey"] + ".vbprivk",
-           img_keyblock.name,
-           img.name]
-    RunAndCheckOutput(cmd)
-
-    # Clean up the temp files.
-    img_unsigned.close()
-    img_keyblock.close()
-
   # AVB: if enabled, calculate and add hash to boot.img or recovery.img.
   if info_dict.get("avb_enable") == "true":
     avbtool = info_dict["avb_avbtool"]
@@ -2815,6 +2788,7 @@
             break
         elif handler(o, a):
           success = True
+          break
       if not success:
         raise ValueError("unknown option \"%s\"" % (o,))
 
diff --git a/tools/sbom/sbom_data.py b/tools/sbom/sbom_data.py
index b5ac8a5..fc5c704 100644
--- a/tools/sbom/sbom_data.py
+++ b/tools/sbom/sbom_data.py
@@ -30,6 +30,7 @@
 SPDXID_DOC = 'SPDXRef-DOCUMENT'
 SPDXID_PRODUCT = 'SPDXRef-PRODUCT'
 SPDXID_PLATFORM = 'SPDXRef-PLATFORM'
+SPDXID_LICENSE_APACHE = 'LicenseRef-Android-Apache-2.0'
 
 PACKAGE_NAME_PRODUCT = 'PRODUCT'
 PACKAGE_NAME_PLATFORM = 'PLATFORM'
@@ -50,7 +51,7 @@
   cpe23Type = 'cpe23Type'
 
 
-@dataclass
+@dataclass(frozen=True)
 class PackageExternalRef:
   category: PackageExternalRefCategory
   type: PackageExternalRefType
@@ -68,6 +69,7 @@
   verification_code: str = None
   file_ids: List[str] = field(default_factory=list)
   external_refs: List[PackageExternalRef] = field(default_factory=list)
+  declared_license_ids: List[str] = field(default_factory=list)
 
 
 @dataclass
@@ -75,6 +77,7 @@
   id: str
   name: str
   checksum: str
+  concluded_license_ids: List[str] = field(default_factory=list)
 
 
 class RelationshipType:
@@ -85,20 +88,27 @@
   STATIC_LINK = 'STATIC_LINK'
 
 
-@dataclass
+@dataclass(frozen=True)
 class Relationship:
   id1: str
   relationship: RelationshipType
   id2: str
 
 
-@dataclass
+@dataclass(frozen=True)
 class DocumentExternalReference:
   id: str
   uri: str
   checksum: str
 
 
+@dataclass(frozen=True)
+class License:
+  id: str
+  text: str
+  name: str
+
+
 @dataclass
 class Document:
   name: str
@@ -111,20 +121,30 @@
   packages: List[Package] = field(default_factory=list)
   files: List[File] = field(default_factory=list)
   relationships: List[Relationship] = field(default_factory=list)
+  licenses: List[License] = field(default_factory=list)
 
   def add_external_ref(self, external_ref):
     if not any(external_ref.uri == ref.uri for ref in self.external_refs):
       self.external_refs.append(external_ref)
 
   def add_package(self, package):
-    if not any(package.id == p.id for p in self.packages):
+    p = next((p for p in self.packages if package.id == p.id), None)
+    if not p:
       self.packages.append(package)
+    else:
+      for license_id in package.declared_license_ids:
+        if license_id not in p.declared_license_ids:
+          p.declared_license_ids.append(license_id)
 
   def add_relationship(self, rel):
     if not any(rel.id1 == r.id1 and rel.id2 == r.id2 and rel.relationship == r.relationship
                for r in self.relationships):
       self.relationships.append(rel)
 
+  def add_license(self, license):
+    if not any(license.id == l.id for l in self.licenses):
+      self.licenses.append(license)
+
   def generate_packages_verification_code(self):
     for package in self.packages:
       if not package.file_ids:
diff --git a/tools/sbom/sbom_data_test.py b/tools/sbom/sbom_data_test.py
index 69bc9d2..9d987c4 100644
--- a/tools/sbom/sbom_data_test.py
+++ b/tools/sbom/sbom_data_test.py
@@ -23,6 +23,7 @@
 SUPPLIER_UPSTREAM = 'Organization: upstream'
 
 SPDXID_PREBUILT_PACKAGE1 = 'SPDXRef-PREBUILT-package1'
+SPDXID_PREBUILT_PACKAGE2 = 'SPDXRef-PREBUILT-package2'
 SPDXID_SOURCE_PACKAGE1 = 'SPDXRef-SOURCE-package1'
 SPDXID_UPSTREAM_PACKAGE1 = 'SPDXRef-UPSTREAM-package1'
 
@@ -31,6 +32,9 @@
 SPDXID_FILE3 = 'SPDXRef-file3'
 SPDXID_FILE4 = 'SPDXRef-file4'
 
+SPDXID_LICENSE1 = "SPDXRef-License-1"
+SPDXID_LICENSE2 = "SPDXRef-License-2"
+
 
 class SBOMDataTest(unittest.TestCase):
 
@@ -134,6 +138,47 @@
     self.sbom_doc.generate_packages_verification_code()
     self.assertEqual(expected_package_verification_code, self.sbom_doc.packages[0].verification_code)
 
+  def test_add_package_(self):
+    self.sbom_doc.add_package(sbom_data.Package(id=SPDXID_PREBUILT_PACKAGE2,
+                                                name='Prebuilt package2',
+                                                download_location=sbom_data.VALUE_NONE,
+                                                supplier=SUPPLIER_GOOGLE,
+                                                version=BUILD_FINGER_PRINT,
+                                                ))
+    p = next((p for p in self.sbom_doc.packages if p.id == SPDXID_PREBUILT_PACKAGE2), None)
+    self.assertNotEqual(p, None)
+    self.assertEqual(p.declared_license_ids, [])
+
+    # Add same package with license 1
+    self.sbom_doc.add_package(sbom_data.Package(id=SPDXID_PREBUILT_PACKAGE2,
+                                                name='Prebuilt package2',
+                                                download_location=sbom_data.VALUE_NONE,
+                                                supplier=SUPPLIER_GOOGLE,
+                                                version=BUILD_FINGER_PRINT,
+                                                declared_license_ids=[SPDXID_LICENSE1]
+                                                ))
+    self.assertEqual(p.declared_license_ids, [SPDXID_LICENSE1])
+
+    # Add same package with license 2
+    self.sbom_doc.add_package(sbom_data.Package(id=SPDXID_PREBUILT_PACKAGE2,
+                                                name='Prebuilt package2',
+                                                download_location=sbom_data.VALUE_NONE,
+                                                supplier=SUPPLIER_GOOGLE,
+                                                version=BUILD_FINGER_PRINT,
+                                                declared_license_ids=[SPDXID_LICENSE2]
+                                                ))
+    self.assertEqual(p.declared_license_ids, [SPDXID_LICENSE1, SPDXID_LICENSE2])
+
+    # Add same package with license 2 again
+    self.sbom_doc.add_package(sbom_data.Package(id=SPDXID_PREBUILT_PACKAGE2,
+                                                name='Prebuilt package2',
+                                                download_location=sbom_data.VALUE_NONE,
+                                                supplier=SUPPLIER_GOOGLE,
+                                                version=BUILD_FINGER_PRINT,
+                                                declared_license_ids=[SPDXID_LICENSE2]
+                                                ))
+    self.assertEqual(p.declared_license_ids, [SPDXID_LICENSE1, SPDXID_LICENSE2])
+
 
 if __name__ == '__main__':
   unittest.main(verbosity=2)
diff --git a/tools/sbom/sbom_writers.py b/tools/sbom/sbom_writers.py
index 1cb864d..26b3c57 100644
--- a/tools/sbom/sbom_writers.py
+++ b/tools/sbom/sbom_writers.py
@@ -64,6 +64,11 @@
   # Relationship
   RELATIONSHIP = 'Relationship'
 
+  # License
+  LICENSE_ID = 'LicenseID'
+  LICENSE_NAME = 'LicenseName'
+  LICENSE_EXTRACTED_TEXT = 'ExtractedText'
+
 
 class TagValueWriter:
   @staticmethod
@@ -99,6 +104,12 @@
       tagvalues.append(f'{Tags.PACKAGE_VERSION}: {package.version}')
     if package.supplier:
       tagvalues.append(f'{Tags.PACKAGE_SUPPLIER}: {package.supplier}')
+
+    license = sbom_data.VALUE_NOASSERTION
+    if package.declared_license_ids:
+      license = ' OR '.join(package.declared_license_ids)
+    tagvalues.append(f'{Tags.PACKAGE_LICENSE_DECLARED}: {license}')
+
     if package.verification_code:
       tagvalues.append(f'{Tags.PACKAGE_VERIFICATION_CODE}: {package.verification_code}')
     if package.external_refs:
@@ -155,8 +166,12 @@
       f'{Tags.FILE_NAME}: {file.name}',
       f'{Tags.SPDXID}: {file.id}',
       f'{Tags.FILE_CHECKSUM}: {file.checksum}',
-      '',
     ]
+    license = sbom_data.VALUE_NOASSERTION
+    if file.concluded_license_ids:
+      license = ' OR '.join(file.concluded_license_ids)
+    tagvalues.append(f'{Tags.FILE_LICENSE_CONCLUDED}: {license}')
+    tagvalues.append('')
 
     return tagvalues
 
@@ -194,6 +209,22 @@
     return tagvalues
 
   @staticmethod
+  def marshal_license(license):
+    tagvalues = []
+    tagvalues.append(f'{Tags.LICENSE_ID}: {license.id}')
+    tagvalues.append(f'{Tags.LICENSE_NAME}: {license.name}')
+    tagvalues.append(f'{Tags.LICENSE_EXTRACTED_TEXT}: <text>{license.text}</text>')
+    return tagvalues
+
+  @staticmethod
+  def marshal_licenses(sbom_doc):
+    tagvalues = []
+    for license in sbom_doc.licenses:
+      tagvalues += TagValueWriter.marshal_license(license)
+      tagvalues.append('')
+    return tagvalues
+
+  @staticmethod
   def write(sbom_doc, file, fragment=False):
     content = []
     if not fragment:
@@ -202,6 +233,7 @@
     tagvalues, marshaled_relationships = TagValueWriter.marshal_packages(sbom_doc, fragment)
     content += tagvalues
     content += TagValueWriter.marshal_relationships(sbom_doc, marshaled_relationships)
+    content += TagValueWriter.marshal_licenses(sbom_doc)
     file.write('\n'.join(content))
 
 
@@ -236,11 +268,13 @@
   PACKAGE_EXTERNAL_REF_TYPE = 'referenceType'
   PACKAGE_EXTERNAL_REF_LOCATOR = 'referenceLocator'
   PACKAGE_HAS_FILES = 'hasFiles'
+  PACKAGE_LICENSE_DECLARED = 'licenseDeclared'
 
   # File
   FILES = 'files'
   FILE_NAME = 'fileName'
   FILE_CHECKSUMS = 'checksums'
+  FILE_LICENSE_CONCLUDED = 'licenseConcluded'
 
   # Relationship
   RELATIONSHIPS = 'relationships'
@@ -248,6 +282,12 @@
   REL_RELATED_ELEMENT_ID = 'relatedSpdxElement'
   REL_TYPE = 'relationshipType'
 
+  # License
+  LICENSES = 'hasExtractedLicensingInfos'
+  LICENSE_ID = 'licenseId'
+  LICENSE_NAME = 'name'
+  LICENSE_EXTRACTED_TEXT = 'extractedText'
+
 
 class JSONWriter:
   @staticmethod
@@ -294,6 +334,9 @@
         package[PropNames.PACKAGE_VERSION] = p.version
       if p.supplier:
         package[PropNames.PACKAGE_SUPPLIER] = p.supplier
+      package[PropNames.PACKAGE_LICENSE_DECLARED] = sbom_data.VALUE_NOASSERTION
+      if p.declared_license_ids:
+        package[PropNames.PACKAGE_LICENSE_DECLARED] = ' OR '.join(p.declared_license_ids)
       if p.verification_code:
         package[PropNames.PACKAGE_VERIFICATION_CODE] = {
           PropNames.PACKAGE_VERIFICATION_CODE_VALUE: p.verification_code
@@ -329,6 +372,9 @@
         PropNames.ALGORITHM: checksum[0],
         PropNames.CHECKSUM_VALUE: checksum[1],
       }]
+      file[PropNames.FILE_LICENSE_CONCLUDED] = sbom_data.VALUE_NOASSERTION
+      if f.concluded_license_ids:
+        file[PropNames.FILE_LICENSE_CONCLUDED] = ' OR '.join(f.concluded_license_ids)
       files.append(file)
     return {PropNames.FILES: files}
 
@@ -347,10 +393,22 @@
     return {PropNames.RELATIONSHIPS: relationships}
 
   @staticmethod
+  def marshal_licenses(sbom_doc):
+    licenses = []
+    for l in sbom_doc.licenses:
+      licenses.append({
+          PropNames.LICENSE_ID: l.id,
+          PropNames.LICENSE_NAME: l.name,
+          PropNames.LICENSE_EXTRACTED_TEXT: f'<text>{l.text}</text>'
+      })
+    return {PropNames.LICENSES: licenses}
+
+  @staticmethod
   def write(sbom_doc, file):
     doc = {}
     doc.update(JSONWriter.marshal_doc_headers(sbom_doc))
     doc.update(JSONWriter.marshal_packages(sbom_doc))
     doc.update(JSONWriter.marshal_files(sbom_doc))
     doc.update(JSONWriter.marshal_relationships(sbom_doc))
+    doc.update(JSONWriter.marshal_licenses(sbom_doc))
     file.write(json.dumps(doc, indent=4))
diff --git a/tools/sbom/sbom_writers_test.py b/tools/sbom/sbom_writers_test.py
index cf85e01..f9f5230 100644
--- a/tools/sbom/sbom_writers_test.py
+++ b/tools/sbom/sbom_writers_test.py
@@ -33,6 +33,14 @@
 SPDXID_FILE3 = 'SPDXRef-file3'
 SPDXID_FILE4 = 'SPDXRef-file4'
 
+SPDXID_LICENSE_1 = 'LicenseRef-Android-License-1'
+SPDXID_LICENSE_2 = 'LicenseRef-Android-License-2'
+SPDXID_LICENSE_3 = 'LicenseRef-Android-License-3'
+
+LICENSE_APACHE_TEXT = "LICENSE_APACHE"
+LICENSE1_TEXT = 'LICENSE 1'
+LICENSE2_TEXT = 'LICENSE 2'
+LICENSE3_TEXT = 'LICENSE 3'
 
 class SBOMWritersTest(unittest.TestCase):
 
@@ -63,6 +71,7 @@
                         download_location=sbom_data.VALUE_NONE,
                         supplier=SUPPLIER_GOOGLE,
                         version=BUILD_FINGER_PRINT,
+                        declared_license_ids=[sbom_data.SPDXID_LICENSE_APACHE]
                         ))
 
     self.sbom_doc.add_package(
@@ -71,6 +80,7 @@
                         download_location=sbom_data.VALUE_NONE,
                         supplier=SUPPLIER_GOOGLE,
                         version=BUILD_FINGER_PRINT,
+                        declared_license_ids=[SPDXID_LICENSE_1],
                         ))
 
     self.sbom_doc.add_package(
@@ -79,6 +89,7 @@
                         download_location=sbom_data.VALUE_NONE,
                         supplier=SUPPLIER_GOOGLE,
                         version=BUILD_FINGER_PRINT,
+                        declared_license_ids=[SPDXID_LICENSE_2, SPDXID_LICENSE_3],
                         external_refs=[sbom_data.PackageExternalRef(
                           category=sbom_data.PackageExternalRefCategory.SECURITY,
                           type=sbom_data.PackageExternalRefType.cpe22Type,
@@ -90,6 +101,7 @@
                         name='Upstream package1',
                         supplier=SUPPLIER_UPSTREAM,
                         version='1.1',
+                        declared_license_ids=[SPDXID_LICENSE_2, SPDXID_LICENSE_3],
                         ))
 
     self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_SOURCE_PACKAGE1,
@@ -97,11 +109,11 @@
                                                           id2=SPDXID_UPSTREAM_PACKAGE1))
 
     self.sbom_doc.files.append(
-      sbom_data.File(id=SPDXID_FILE1, name='/bin/file1', checksum='SHA1: 11111'))
+      sbom_data.File(id=SPDXID_FILE1, name='/bin/file1', checksum='SHA1: 11111', concluded_license_ids=[sbom_data.SPDXID_LICENSE_APACHE]))
     self.sbom_doc.files.append(
-      sbom_data.File(id=SPDXID_FILE2, name='/bin/file2', checksum='SHA1: 22222'))
+      sbom_data.File(id=SPDXID_FILE2, name='/bin/file2', checksum='SHA1: 22222', concluded_license_ids=[SPDXID_LICENSE_1]))
     self.sbom_doc.files.append(
-      sbom_data.File(id=SPDXID_FILE3, name='/bin/file3', checksum='SHA1: 33333'))
+      sbom_data.File(id=SPDXID_FILE3, name='/bin/file3', checksum='SHA1: 33333', concluded_license_ids=[SPDXID_LICENSE_2, SPDXID_LICENSE_3]))
     self.sbom_doc.files.append(
       sbom_data.File(id=SPDXID_FILE4, name='file4.a', checksum='SHA1: 44444'))
 
@@ -120,6 +132,11 @@
                                                           id2=SPDXID_FILE4
                                                           ))
 
+    self.sbom_doc.add_license(sbom_data.License(sbom_data.SPDXID_LICENSE_APACHE, LICENSE_APACHE_TEXT, "License-Apache"))
+    self.sbom_doc.add_license(sbom_data.License(SPDXID_LICENSE_1, LICENSE1_TEXT, "License-1"))
+    self.sbom_doc.add_license(sbom_data.License(SPDXID_LICENSE_2, LICENSE2_TEXT, "License-2"))
+    self.sbom_doc.add_license(sbom_data.License(SPDXID_LICENSE_3, LICENSE3_TEXT, "License-3"))
+
     # SBOM fragment of a APK
     self.unbundled_sbom_doc = sbom_data.Document(name='test doc',
                                                  namespace='http://www.google.com/sbom/spdx/android',
diff --git a/tools/sbom/testdata/expected_json_sbom.spdx.json b/tools/sbom/testdata/expected_json_sbom.spdx.json
index 53936c5..a877810 100644
--- a/tools/sbom/testdata/expected_json_sbom.spdx.json
+++ b/tools/sbom/testdata/expected_json_sbom.spdx.json
@@ -31,6 +31,7 @@
             "filesAnalyzed": true,
             "versionInfo": "build_finger_print",
             "supplier": "Organization: Google",
+            "licenseDeclared": "NOASSERTION",
             "packageVerificationCode": {
                 "packageVerificationCodeValue": "123456"
             },
@@ -46,7 +47,8 @@
             "downloadLocation": "NONE",
             "filesAnalyzed": false,
             "versionInfo": "build_finger_print",
-            "supplier": "Organization: Google"
+            "supplier": "Organization: Google",
+            "licenseDeclared": "LicenseRef-Android-Apache-2.0"
         },
         {
             "name": "Prebuilt package1",
@@ -54,7 +56,8 @@
             "downloadLocation": "NONE",
             "filesAnalyzed": false,
             "versionInfo": "build_finger_print",
-            "supplier": "Organization: Google"
+            "supplier": "Organization: Google",
+            "licenseDeclared": "LicenseRef-Android-License-1"
         },
         {
             "name": "Source package1",
@@ -63,6 +66,7 @@
             "filesAnalyzed": false,
             "versionInfo": "build_finger_print",
             "supplier": "Organization: Google",
+            "licenseDeclared": "LicenseRef-Android-License-2 OR LicenseRef-Android-License-3",
             "externalRefs": [
                 {
                     "referenceCategory": "SECURITY",
@@ -77,7 +81,8 @@
             "downloadLocation": "NOASSERTION",
             "filesAnalyzed": false,
             "versionInfo": "1.1",
-            "supplier": "Organization: upstream"
+            "supplier": "Organization: upstream",
+            "licenseDeclared": "LicenseRef-Android-License-2 OR LicenseRef-Android-License-3"
         }
     ],
     "files": [
@@ -89,7 +94,8 @@
                     "algorithm": "SHA1",
                     "checksumValue": "11111"
                 }
-            ]
+            ],
+            "licenseConcluded": "LicenseRef-Android-Apache-2.0"
         },
         {
             "fileName": "/bin/file2",
@@ -99,7 +105,8 @@
                     "algorithm": "SHA1",
                     "checksumValue": "22222"
                 }
-            ]
+            ],
+            "licenseConcluded": "LicenseRef-Android-License-1"
         },
         {
             "fileName": "/bin/file3",
@@ -109,7 +116,8 @@
                     "algorithm": "SHA1",
                     "checksumValue": "33333"
                 }
-            ]
+            ],
+            "licenseConcluded": "LicenseRef-Android-License-2 OR LicenseRef-Android-License-3"
         },
         {
             "fileName": "file4.a",
@@ -119,7 +127,8 @@
                     "algorithm": "SHA1",
                     "checksumValue": "44444"
                 }
-            ]
+            ],
+            "licenseConcluded": "NOASSERTION"
         }
     ],
     "relationships": [
@@ -148,5 +157,27 @@
             "relatedSpdxElement": "SPDXRef-UPSTREAM-package1",
             "relationshipType": "VARIANT_OF"
         }
+    ],
+    "hasExtractedLicensingInfos": [
+        {
+            "licenseId": "LicenseRef-Android-Apache-2.0",
+            "name": "License-Apache",
+            "extractedText": "<text>LICENSE_APACHE</text>"
+        },
+        {
+            "licenseId": "LicenseRef-Android-License-1",
+            "name": "License-1",
+            "extractedText": "<text>LICENSE 1</text>"
+        },
+        {
+            "licenseId": "LicenseRef-Android-License-2",
+            "name": "License-2",
+            "extractedText": "<text>LICENSE 2</text>"
+        },
+        {
+            "licenseId": "LicenseRef-Android-License-3",
+            "name": "License-3",
+            "extractedText": "<text>LICENSE 3</text>"
+        }
     ]
 }
\ No newline at end of file
diff --git a/tools/sbom/testdata/expected_tagvalue_sbom.spdx b/tools/sbom/testdata/expected_tagvalue_sbom.spdx
index e6fd17e..1c54410 100644
--- a/tools/sbom/testdata/expected_tagvalue_sbom.spdx
+++ b/tools/sbom/testdata/expected_tagvalue_sbom.spdx
@@ -10,6 +10,7 @@
 FileName: file4.a
 SPDXID: SPDXRef-file4
 FileChecksum: SHA1: 44444
+LicenseConcluded: NOASSERTION
 
 PackageName: PRODUCT
 SPDXID: SPDXRef-PRODUCT
@@ -17,6 +18,7 @@
 FilesAnalyzed: true
 PackageVersion: build_finger_print
 PackageSupplier: Organization: Google
+PackageLicenseDeclared: NOASSERTION
 PackageVerificationCode: 123456
 
 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-PRODUCT
@@ -24,14 +26,17 @@
 FileName: /bin/file1
 SPDXID: SPDXRef-file1
 FileChecksum: SHA1: 11111
+LicenseConcluded: LicenseRef-Android-Apache-2.0
 
 FileName: /bin/file2
 SPDXID: SPDXRef-file2
 FileChecksum: SHA1: 22222
+LicenseConcluded: LicenseRef-Android-License-1
 
 FileName: /bin/file3
 SPDXID: SPDXRef-file3
 FileChecksum: SHA1: 33333
+LicenseConcluded: LicenseRef-Android-License-2 OR LicenseRef-Android-License-3
 
 PackageName: PLATFORM
 SPDXID: SPDXRef-PLATFORM
@@ -39,6 +44,7 @@
 FilesAnalyzed: false
 PackageVersion: build_finger_print
 PackageSupplier: Organization: Google
+PackageLicenseDeclared: LicenseRef-Android-Apache-2.0
 
 PackageName: Prebuilt package1
 SPDXID: SPDXRef-PREBUILT-package1
@@ -46,6 +52,7 @@
 FilesAnalyzed: false
 PackageVersion: build_finger_print
 PackageSupplier: Organization: Google
+PackageLicenseDeclared: LicenseRef-Android-License-1
 
 PackageName: Source package1
 SPDXID: SPDXRef-SOURCE-package1
@@ -53,6 +60,7 @@
 FilesAnalyzed: false
 PackageVersion: build_finger_print
 PackageSupplier: Organization: Google
+PackageLicenseDeclared: LicenseRef-Android-License-2 OR LicenseRef-Android-License-3
 ExternalRef: SECURITY cpe22Type cpe:/a:jsoncpp_project:jsoncpp:1.9.4
 
 PackageName: Upstream package1
@@ -61,6 +69,7 @@
 FilesAnalyzed: false
 PackageVersion: 1.1
 PackageSupplier: Organization: upstream
+PackageLicenseDeclared: LicenseRef-Android-License-2 OR LicenseRef-Android-License-3
 
 Relationship: SPDXRef-SOURCE-package1 VARIANT_OF SPDXRef-UPSTREAM-package1
 
@@ -68,3 +77,19 @@
 Relationship: SPDXRef-file2 GENERATED_FROM SPDXRef-PREBUILT-package1
 Relationship: SPDXRef-file3 GENERATED_FROM SPDXRef-SOURCE-package1
 Relationship: SPDXRef-file1 STATIC_LINK SPDXRef-file4
+
+LicenseID: LicenseRef-Android-Apache-2.0
+LicenseName: License-Apache
+ExtractedText: <text>LICENSE_APACHE</text>
+
+LicenseID: LicenseRef-Android-License-1
+LicenseName: License-1
+ExtractedText: <text>LICENSE 1</text>
+
+LicenseID: LicenseRef-Android-License-2
+LicenseName: License-2
+ExtractedText: <text>LICENSE 2</text>
+
+LicenseID: LicenseRef-Android-License-3
+LicenseName: License-3
+ExtractedText: <text>LICENSE 3</text>
diff --git a/tools/sbom/testdata/expected_tagvalue_sbom_doc_describes_file.spdx b/tools/sbom/testdata/expected_tagvalue_sbom_doc_describes_file.spdx
index 428d7e3..36afc8b 100644
--- a/tools/sbom/testdata/expected_tagvalue_sbom_doc_describes_file.spdx
+++ b/tools/sbom/testdata/expected_tagvalue_sbom_doc_describes_file.spdx
@@ -10,6 +10,7 @@
 FileName: file4.a
 SPDXID: SPDXRef-file4
 FileChecksum: SHA1: 44444
+LicenseConcluded: NOASSERTION
 
 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-file4
 
@@ -19,19 +20,23 @@
 FilesAnalyzed: true
 PackageVersion: build_finger_print
 PackageSupplier: Organization: Google
+PackageLicenseDeclared: NOASSERTION
 PackageVerificationCode: 123456
 
 FileName: /bin/file1
 SPDXID: SPDXRef-file1
 FileChecksum: SHA1: 11111
+LicenseConcluded: LicenseRef-Android-Apache-2.0
 
 FileName: /bin/file2
 SPDXID: SPDXRef-file2
 FileChecksum: SHA1: 22222
+LicenseConcluded: LicenseRef-Android-License-1
 
 FileName: /bin/file3
 SPDXID: SPDXRef-file3
 FileChecksum: SHA1: 33333
+LicenseConcluded: LicenseRef-Android-License-2 OR LicenseRef-Android-License-3
 
 PackageName: PLATFORM
 SPDXID: SPDXRef-PLATFORM
@@ -39,6 +44,7 @@
 FilesAnalyzed: false
 PackageVersion: build_finger_print
 PackageSupplier: Organization: Google
+PackageLicenseDeclared: LicenseRef-Android-Apache-2.0
 
 PackageName: Prebuilt package1
 SPDXID: SPDXRef-PREBUILT-package1
@@ -46,6 +52,7 @@
 FilesAnalyzed: false
 PackageVersion: build_finger_print
 PackageSupplier: Organization: Google
+PackageLicenseDeclared: LicenseRef-Android-License-1
 
 PackageName: Source package1
 SPDXID: SPDXRef-SOURCE-package1
@@ -53,6 +60,7 @@
 FilesAnalyzed: false
 PackageVersion: build_finger_print
 PackageSupplier: Organization: Google
+PackageLicenseDeclared: LicenseRef-Android-License-2 OR LicenseRef-Android-License-3
 ExternalRef: SECURITY cpe22Type cpe:/a:jsoncpp_project:jsoncpp:1.9.4
 
 PackageName: Upstream package1
@@ -61,6 +69,7 @@
 FilesAnalyzed: false
 PackageVersion: 1.1
 PackageSupplier: Organization: upstream
+PackageLicenseDeclared: LicenseRef-Android-License-2 OR LicenseRef-Android-License-3
 
 Relationship: SPDXRef-SOURCE-package1 VARIANT_OF SPDXRef-UPSTREAM-package1
 
@@ -68,3 +77,19 @@
 Relationship: SPDXRef-file2 GENERATED_FROM SPDXRef-PREBUILT-package1
 Relationship: SPDXRef-file3 GENERATED_FROM SPDXRef-SOURCE-package1
 Relationship: SPDXRef-file1 STATIC_LINK SPDXRef-file4
+
+LicenseID: LicenseRef-Android-Apache-2.0
+LicenseName: License-Apache
+ExtractedText: <text>LICENSE_APACHE</text>
+
+LicenseID: LicenseRef-Android-License-1
+LicenseName: License-1
+ExtractedText: <text>LICENSE 1</text>
+
+LicenseID: LicenseRef-Android-License-2
+LicenseName: License-2
+ExtractedText: <text>LICENSE 2</text>
+
+LicenseID: LicenseRef-Android-License-3
+LicenseName: License-3
+ExtractedText: <text>LICENSE 3</text>
diff --git a/tools/sbom/testdata/expected_tagvalue_sbom_unbundled.spdx b/tools/sbom/testdata/expected_tagvalue_sbom_unbundled.spdx
index a00c291..4b14a4b 100644
--- a/tools/sbom/testdata/expected_tagvalue_sbom_unbundled.spdx
+++ b/tools/sbom/testdata/expected_tagvalue_sbom_unbundled.spdx
@@ -1,6 +1,7 @@
 FileName: /bin/file1.apk
 SPDXID: SPDXRef-file1
 FileChecksum: SHA1: 11111
+LicenseConcluded: NOASSERTION
 
 PackageName: Unbundled apk package
 SPDXID: SPDXRef-SOURCE-package1
@@ -8,5 +9,6 @@
 FilesAnalyzed: false
 PackageVersion: build_finger_print
 PackageSupplier: Organization: Google
+PackageLicenseDeclared: NOASSERTION
 
 Relationship: SPDXRef-file1 GENERATED_FROM SPDXRef-SOURCE-package1
diff --git a/tools/tool_event_logger/proto/tool_event.proto b/tools/tool_event_logger/proto/tool_event.proto
index 61e28a2..ef71eac 100644
--- a/tools/tool_event_logger/proto/tool_event.proto
+++ b/tools/tool_event_logger/proto/tool_event.proto
@@ -27,6 +27,8 @@
   string source_root = 3;
   // Name of the tool used.
   string tool_tag = 6;
+  // Name of the host workstation.
+  string host_name = 7;
 
   oneof event {
     InvocationStarted invocation_started = 4;
diff --git a/tools/tool_event_logger/tool_event_logger.py b/tools/tool_event_logger/tool_event_logger.py
index 65a9696..b249d91 100644
--- a/tools/tool_event_logger/tool_event_logger.py
+++ b/tools/tool_event_logger/tool_event_logger.py
@@ -38,6 +38,7 @@
       tool_tag: str,
       invocation_id: str,
       user_name: str,
+      host_name: str,
       source_root: str,
       platform_version: str,
       python_version: str,
@@ -46,6 +47,7 @@
     self.tool_tag = tool_tag
     self.invocation_id = invocation_id
     self.user_name = user_name
+    self.host_name = host_name
     self.source_root = source_root
     self.platform_version = platform_version
     self.python_version = python_version
@@ -57,6 +59,7 @@
         tool_tag=tool_tag,
         invocation_id=str(uuid.uuid4()),
         user_name=getpass.getuser(),
+        host_name=platform.node(),
         source_root=os.environ.get('ANDROID_BUILD_TOP', ''),
         platform_version=platform.platform(),
         python_version=platform.python_version(),
@@ -110,6 +113,7 @@
         tool_tag=self.tool_tag,
         invocation_id=self.invocation_id,
         user_name=self.user_name,
+        host_name=self.host_name,
         source_root=self.source_root,
     )
 
diff --git a/tools/tool_event_logger/tool_event_logger_test.py b/tools/tool_event_logger/tool_event_logger_test.py
index 34b6c35..788812a 100644
--- a/tools/tool_event_logger/tool_event_logger_test.py
+++ b/tools/tool_event_logger/tool_event_logger_test.py
@@ -25,6 +25,7 @@
 
 TEST_INVOCATION_ID = 'test_invocation_id'
 TEST_USER_NAME = 'test_user'
+TEST_HOST_NAME = 'test_host_name'
 TEST_TOOL_TAG = 'test_tool'
 TEST_SOURCE_ROOT = 'test_source_root'
 TEST_PLATFORM_VERSION = 'test_platform_version'
@@ -41,6 +42,7 @@
         TEST_TOOL_TAG,
         TEST_INVOCATION_ID,
         TEST_USER_NAME,
+        TEST_HOST_NAME,
         TEST_SOURCE_ROOT,
         TEST_PLATFORM_VERSION,
         TEST_PYTHON_VERSION,
@@ -65,6 +67,7 @@
     log_event = tool_event_pb2.ToolEvent.FromString(sent_event.source_extension)
     self.assertEqual(log_event.invocation_id, TEST_INVOCATION_ID)
     self.assertEqual(log_event.user_name, TEST_USER_NAME)
+    self.assertEqual(log_event.host_name, TEST_HOST_NAME)
     self.assertEqual(log_event.tool_tag, TEST_TOOL_TAG)
     self.assertEqual(log_event.source_root, TEST_SOURCE_ROOT)